mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Bug 699844 - Remove the Bookmarks annotations service API. r=mak
Differential Revision: https://phabricator.services.mozilla.com/D93315
This commit is contained in:
parent
77e1109e9e
commit
080900a436
@ -31,9 +31,6 @@
|
||||
#define NS_NAVHISTORYSERVICE_CONTRACTID \
|
||||
"@mozilla.org/browser/nav-history-service;1"
|
||||
|
||||
#define NS_ANNOTATIONSERVICE_CONTRACTID \
|
||||
"@mozilla.org/browser/annotation-service;1"
|
||||
|
||||
#define NS_NAVBOOKMARKSSERVICE_CONTRACTID \
|
||||
"@mozilla.org/browser/nav-bookmarks-service;1"
|
||||
|
||||
@ -91,13 +88,6 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define NS_ANNOTATIONSERVICE_CID \
|
||||
{ \
|
||||
0x5e8d4751, 0x1852, 0x434b, { \
|
||||
0xa9, 0x92, 0x2c, 0x6d, 0x2a, 0x25, 0xfa, 0x46 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NS_NAVBOOKMARKSSERVICE_CID \
|
||||
{ \
|
||||
0x9de95a0c, 0x39a4, 0x4d64, { \
|
||||
|
@ -124,6 +124,11 @@ function notify(observers, notification, args = []) {
|
||||
}
|
||||
|
||||
var History = Object.freeze({
|
||||
ANNOTATION_EXPIRE_NEVER: 4,
|
||||
// Constants for the type of annotation.
|
||||
ANNOTATION_TYPE_STRING: 3,
|
||||
ANNOTATION_TYPE_INT64: 5,
|
||||
|
||||
/**
|
||||
* Fetch the available information for one page.
|
||||
*
|
||||
@ -1685,8 +1690,8 @@ var update = async function(db, pageInfo) {
|
||||
// accessing page annotations via the annotation service.
|
||||
let type =
|
||||
typeof content == "string"
|
||||
? Ci.nsIAnnotationService.TYPE_STRING
|
||||
: Ci.nsIAnnotationService.TYPE_INT64;
|
||||
? History.ANNOTATION_TYPE_STRING
|
||||
: History.ANNOTATION_TYPE_INT64;
|
||||
let date = PlacesUtils.toPRTime(new Date());
|
||||
|
||||
// This will replace the id every time an annotation is updated. This is
|
||||
@ -1705,7 +1710,7 @@ var update = async function(db, pageInfo) {
|
||||
id,
|
||||
anno_name: anno,
|
||||
content,
|
||||
expiration: PlacesUtils.annotations.EXPIRE_NEVER,
|
||||
expiration: History.ANNOTATION_EXPIRE_NEVER,
|
||||
type,
|
||||
// The date fields are unused, so we just set them both to the latest.
|
||||
date_added: date,
|
||||
|
@ -1976,13 +1976,6 @@ XPCOMUtils.defineLazyGetter(PlacesUtils, "bookmarks", () => {
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
PlacesUtils,
|
||||
"annotations",
|
||||
"@mozilla.org/browser/annotation-service;1",
|
||||
"nsIAnnotationService"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
PlacesUtils,
|
||||
"tagging",
|
||||
|
@ -19,14 +19,6 @@ Classes = [
|
||||
'type': 'nsAnnoProtocolHandler',
|
||||
'headers': ['/toolkit/components/places/nsAnnoProtocolHandler.h'],
|
||||
},
|
||||
{
|
||||
'cid': '{5e8d4751-1852-434b-a992-2c6d2a25fa46}',
|
||||
'contract_ids': ['@mozilla.org/browser/annotation-service;1'],
|
||||
'singleton': True,
|
||||
'type': 'nsAnnotationService',
|
||||
'headers': ['/toolkit/components/places/nsAnnotationService.h'],
|
||||
'constructor': 'nsAnnotationService::GetSingleton',
|
||||
},
|
||||
{
|
||||
'cid': '{984e3259-9266-49cf-b605-60b022a00756}',
|
||||
'contract_ids': ['@mozilla.org/browser/favicon-service;1'],
|
||||
|
@ -19,7 +19,6 @@ if CONFIG['MOZ_PLACES']:
|
||||
'mozIPlacesAutoComplete.idl',
|
||||
'mozIPlacesPendingOperation.idl',
|
||||
'mozISyncedBookmarksMirror.idl',
|
||||
'nsIAnnotationService.idl',
|
||||
'nsIFaviconService.idl',
|
||||
'nsINavBookmarksService.idl',
|
||||
'nsITaggingService.idl',
|
||||
@ -40,7 +39,6 @@ if CONFIG['MOZ_PLACES']:
|
||||
'Helpers.cpp',
|
||||
'History.cpp',
|
||||
'nsAnnoProtocolHandler.cpp',
|
||||
'nsAnnotationService.cpp',
|
||||
'nsFaviconService.cpp',
|
||||
'nsNavBookmarks.cpp',
|
||||
'nsNavHistory.cpp',
|
||||
|
@ -1,552 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "nsAnnotationService.h"
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsPlacesTables.h"
|
||||
#include "nsPlacesIndexes.h"
|
||||
#include "nsPlacesMacros.h"
|
||||
#include "Helpers.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVariant.h"
|
||||
#include "mozilla/storage.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#include "nsNetCID.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::places;
|
||||
|
||||
const int32_t nsAnnotationService::kAnnoIndex_ID = 0;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_PageOrItem = 1;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_NameID = 2;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_Content = 3;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_Flags = 4;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_Expiration = 5;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_Type = 6;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_DateAdded = 7;
|
||||
const int32_t nsAnnotationService::kAnnoIndex_LastModified = 8;
|
||||
|
||||
PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsAnnotationService, gAnnotationService)
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAnnotationService, nsIAnnotationService,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
nsAnnotationService::nsAnnotationService() {
|
||||
NS_ASSERTION(!gAnnotationService,
|
||||
"Attempting to create two instances of the service!");
|
||||
gAnnotationService = this;
|
||||
}
|
||||
|
||||
nsAnnotationService::~nsAnnotationService() {
|
||||
NS_ASSERTION(gAnnotationService == this,
|
||||
"Deleting a non-singleton instance of the service");
|
||||
if (gAnnotationService == this) gAnnotationService = nullptr;
|
||||
}
|
||||
|
||||
nsresult nsAnnotationService::Init() {
|
||||
mDB = Database::GetDatabase();
|
||||
NS_ENSURE_STATE(mDB);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAnnotationService::SetAnnotationStringInternal(
|
||||
int64_t aItemId, BookmarkData* aBookmark, const nsACString& aName,
|
||||
const nsAString& aValue, int32_t aFlags, uint16_t aExpiration) {
|
||||
mozStorageTransaction transaction(mDB->MainConn(), false);
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
|
||||
nsresult rv =
|
||||
StartSetAnnotation(aItemId, aBookmark, aName, aFlags, aExpiration,
|
||||
nsIAnnotationService::TYPE_STRING, statement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
rv = statement->BindStringByName("content"_ns, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnnotationService::SetItemAnnotation(int64_t aItemId, const nsACString& aName,
|
||||
nsIVariant* aValue, int32_t aFlags,
|
||||
uint16_t aExpiration, uint16_t aSource,
|
||||
bool aDontUpdateLastModified) {
|
||||
AUTO_PROFILER_LABEL("nsAnnotationService::SetItemAnnotation", OTHER);
|
||||
|
||||
NS_ENSURE_ARG_MIN(aItemId, 1);
|
||||
NS_ENSURE_ARG(aValue);
|
||||
|
||||
uint16_t dataType = aValue->GetDataType();
|
||||
BookmarkData bookmark;
|
||||
|
||||
switch (dataType) {
|
||||
case nsIDataType::VTYPE_INT8:
|
||||
case nsIDataType::VTYPE_UINT8:
|
||||
case nsIDataType::VTYPE_INT16:
|
||||
case nsIDataType::VTYPE_UINT16:
|
||||
case nsIDataType::VTYPE_INT32:
|
||||
case nsIDataType::VTYPE_UINT32:
|
||||
case nsIDataType::VTYPE_BOOL: {
|
||||
int32_t valueInt;
|
||||
nsresult rv = aValue->GetAsInt32(&valueInt);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = SetAnnotationInt32Internal(aItemId, &bookmark, aName, valueInt,
|
||||
aFlags, aExpiration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
}
|
||||
// Fall through int64_t case otherwise.
|
||||
[[fallthrough]];
|
||||
}
|
||||
case nsIDataType::VTYPE_INT64:
|
||||
case nsIDataType::VTYPE_UINT64: {
|
||||
int64_t valueLong;
|
||||
nsresult rv = aValue->GetAsInt64(&valueLong);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = SetAnnotationInt64Internal(aItemId, &bookmark, aName, valueLong,
|
||||
aFlags, aExpiration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
}
|
||||
// Fall through double case otherwise.
|
||||
[[fallthrough]];
|
||||
}
|
||||
case nsIDataType::VTYPE_FLOAT:
|
||||
case nsIDataType::VTYPE_DOUBLE: {
|
||||
double valueDouble;
|
||||
nsresult rv = aValue->GetAsDouble(&valueDouble);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = SetAnnotationDoubleInternal(aItemId, &bookmark, aName, valueDouble,
|
||||
aFlags, aExpiration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
}
|
||||
case nsIDataType::VTYPE_CHAR:
|
||||
case nsIDataType::VTYPE_WCHAR:
|
||||
case nsIDataType::VTYPE_CHAR_STR:
|
||||
case nsIDataType::VTYPE_WCHAR_STR:
|
||||
case nsIDataType::VTYPE_STRING_SIZE_IS:
|
||||
case nsIDataType::VTYPE_WSTRING_SIZE_IS:
|
||||
case nsIDataType::VTYPE_UTF8STRING:
|
||||
case nsIDataType::VTYPE_CSTRING:
|
||||
case nsIDataType::VTYPE_ASTRING: {
|
||||
nsAutoString stringValue;
|
||||
nsresult rv = aValue->GetAsAString(stringValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = SetAnnotationStringInternal(aItemId, &bookmark, aName, stringValue,
|
||||
aFlags, aExpiration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAnnotationService::SetAnnotationInt32Internal(
|
||||
int64_t aItemId, BookmarkData* aBookmark, const nsACString& aName,
|
||||
int32_t aValue, int32_t aFlags, uint16_t aExpiration) {
|
||||
mozStorageTransaction transaction(mDB->MainConn(), false);
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv =
|
||||
StartSetAnnotation(aItemId, aBookmark, aName, aFlags, aExpiration,
|
||||
nsIAnnotationService::TYPE_INT32, statement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
rv = statement->BindInt32ByName("content"_ns, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAnnotationService::SetAnnotationInt64Internal(
|
||||
int64_t aItemId, BookmarkData* aBookmark, const nsACString& aName,
|
||||
int64_t aValue, int32_t aFlags, uint16_t aExpiration) {
|
||||
mozStorageTransaction transaction(mDB->MainConn(), false);
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv =
|
||||
StartSetAnnotation(aItemId, aBookmark, aName, aFlags, aExpiration,
|
||||
nsIAnnotationService::TYPE_INT64, statement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
rv = statement->BindInt64ByName("content"_ns, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAnnotationService::SetAnnotationDoubleInternal(
|
||||
int64_t aItemId, BookmarkData* aBookmark, const nsACString& aName,
|
||||
double aValue, int32_t aFlags, uint16_t aExpiration) {
|
||||
mozStorageTransaction transaction(mDB->MainConn(), false);
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv =
|
||||
StartSetAnnotation(aItemId, aBookmark, aName, aFlags, aExpiration,
|
||||
nsIAnnotationService::TYPE_DOUBLE, statement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
rv = statement->BindDoubleByName("content"_ns, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAnnotationService::GetValueFromStatement(
|
||||
nsCOMPtr<mozIStorageStatement>& aStatement, nsIVariant** _retval) {
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> value = new nsVariant();
|
||||
int32_t type = aStatement->AsInt32(kAnnoIndex_Type);
|
||||
switch (type) {
|
||||
case nsIAnnotationService::TYPE_INT32:
|
||||
case nsIAnnotationService::TYPE_INT64:
|
||||
case nsIAnnotationService::TYPE_DOUBLE: {
|
||||
rv = value->SetAsDouble(aStatement->AsDouble(kAnnoIndex_Content));
|
||||
break;
|
||||
}
|
||||
case nsIAnnotationService::TYPE_STRING: {
|
||||
nsAutoString valueString;
|
||||
rv = aStatement->GetString(kAnnoIndex_Content, valueString);
|
||||
if (NS_SUCCEEDED(rv)) rv = value->SetAsAString(valueString);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
value.forget(_retval);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnnotationService::GetItemAnnotation(int64_t aItemId, const nsACString& aName,
|
||||
nsIVariant** _retval) {
|
||||
NS_ENSURE_ARG_MIN(aItemId, 1);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv = StartGetAnnotation(aItemId, aName, statement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
return GetValueFromStatement(statement, _retval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @note We don't remove anything from the moz_anno_attributes table. If we
|
||||
* delete the last item of a given name, that item really should go away.
|
||||
* It will be cleaned up by expiration.
|
||||
*/
|
||||
nsresult nsAnnotationService::RemoveAnnotationInternal(
|
||||
int64_t aItemId, BookmarkData* aBookmark, const nsACString& aName) {
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
statement = mDB->GetStatement(
|
||||
"DELETE FROM moz_items_annos "
|
||||
"WHERE item_id = :item_id "
|
||||
"AND anno_attribute_id = "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)");
|
||||
NS_ENSURE_STATE(statement);
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
nsresult rv;
|
||||
rv = statement->BindInt64ByName("item_id"_ns, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->BindUTF8StringByName("anno_name"_ns, aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
if (bookmarks) {
|
||||
MOZ_ASSERT(aBookmark);
|
||||
if (NS_FAILED(bookmarks->FetchItemInfo(aItemId, *aBookmark))) {
|
||||
aBookmark->id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnnotationService::RemoveItemAnnotation(int64_t aItemId,
|
||||
const nsACString& aName,
|
||||
uint16_t aSource) {
|
||||
NS_ENSURE_ARG_MIN(aItemId, 1);
|
||||
|
||||
BookmarkData bookmark;
|
||||
nsresult rv = RemoveAnnotationInternal(aItemId, &bookmark, aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAnnotationService::RemoveItemAnnotations(int64_t aItemId) {
|
||||
NS_ENSURE_ARG_MIN(aItemId, 1);
|
||||
|
||||
// Should this be precompiled or a getter?
|
||||
nsCOMPtr<mozIStorageStatement> statement =
|
||||
mDB->GetStatement("DELETE FROM moz_items_annos WHERE item_id = :item_id");
|
||||
NS_ENSURE_STATE(statement);
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
nsresult rv = statement->BindInt64ByName("item_id"_ns, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAnnotationService::ItemHasAnnotation(int64_t aItemId, const nsACString& aName,
|
||||
bool* _hasAnno) {
|
||||
NS_ENSURE_ARG_MIN(aItemId, 1);
|
||||
NS_ENSURE_ARG_POINTER(_hasAnno);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
|
||||
"SELECT b.id, "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, "
|
||||
"a.id, a.dateAdded "
|
||||
"FROM moz_bookmarks b "
|
||||
"LEFT JOIN moz_items_annos a ON a.item_id = b.id "
|
||||
"AND a.anno_attribute_id = nameid "
|
||||
"WHERE b.id = :item_id");
|
||||
NS_ENSURE_STATE(stmt);
|
||||
mozStorageStatementScoper checkAnnoScoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindUTF8StringByName("anno_name"_ns, aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64ByName("item_id"_ns, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasResult;
|
||||
rv = stmt->ExecuteStep(&hasResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!hasResult) {
|
||||
// We are trying to get an annotation on an invalid bookmarks or
|
||||
// history entry.
|
||||
// Here we preserve the old behavior, returning that we don't have the
|
||||
// annotation, ignoring the fact itemId is invalid.
|
||||
// Otherwise we should return NS_ERROR_INVALID_ARG, but this will somehow
|
||||
// break the API. In future we could want to be pickier.
|
||||
*_hasAnno = false;
|
||||
} else {
|
||||
int64_t annotationId = stmt->AsInt64(2);
|
||||
*_hasAnno = (annotationId > 0);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This loads the statement and steps it once so you can get data out of it.
|
||||
*
|
||||
* @note You have to reset the statement when you're done if this succeeds.
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if the annotation is not found.
|
||||
*/
|
||||
|
||||
nsresult nsAnnotationService::StartGetAnnotation(
|
||||
int64_t aItemId, const nsACString& aName,
|
||||
nsCOMPtr<mozIStorageStatement>& aStatement) {
|
||||
aStatement = mDB->GetStatement(
|
||||
"SELECT a.id, a.item_id, :anno_name, a.content, a.flags, "
|
||||
"a.expiration, a.type "
|
||||
"FROM moz_anno_attributes n "
|
||||
"JOIN moz_items_annos a ON a.anno_attribute_id = n.id "
|
||||
"WHERE a.item_id = :item_id "
|
||||
"AND n.name = :anno_name");
|
||||
NS_ENSURE_STATE(aStatement);
|
||||
mozStorageStatementScoper getAnnoScoper(aStatement);
|
||||
|
||||
nsresult rv;
|
||||
rv = aStatement->BindInt64ByName("item_id"_ns, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStatement->BindUTF8StringByName("anno_name"_ns, aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasResult = false;
|
||||
rv = aStatement->ExecuteStep(&hasResult);
|
||||
if (NS_FAILED(rv) || !hasResult) return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// on success, DON'T reset the statement, the caller needs to read from it,
|
||||
// and it is the caller's job to reset it.
|
||||
getAnnoScoper.Abandon();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This does most of the setup work needed to set an annotation, except for
|
||||
* binding the the actual value and executing the statement.
|
||||
* It will either update an existing annotation or insert a new one.
|
||||
*
|
||||
* @note The aStatement RESULT IS NOT ADDREFED. This is just one of the class
|
||||
* vars, which control its scope. DO NOT RELEASE.
|
||||
* The caller must take care of resetting the statement if this succeeds.
|
||||
*/
|
||||
nsresult nsAnnotationService::StartSetAnnotation(
|
||||
int64_t aItemId, BookmarkData* aBookmark, const nsACString& aName,
|
||||
int32_t aFlags, uint16_t aExpiration, uint16_t aType,
|
||||
nsCOMPtr<mozIStorageStatement>& aStatement) {
|
||||
MOZ_ASSERT(aExpiration == EXPIRE_NEVER, "Only EXPIRE_NEVER is supported");
|
||||
NS_ENSURE_ARG(aExpiration == EXPIRE_NEVER);
|
||||
|
||||
// Ensure the annotation name exists.
|
||||
nsCOMPtr<mozIStorageStatement> addNameStmt = mDB->GetStatement(
|
||||
"INSERT OR IGNORE INTO moz_anno_attributes (name) VALUES (:anno_name)");
|
||||
NS_ENSURE_STATE(addNameStmt);
|
||||
mozStorageStatementScoper scoper(addNameStmt);
|
||||
|
||||
nsresult rv = addNameStmt->BindUTF8StringByName("anno_name"_ns, aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = addNameStmt->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We have to check 2 things:
|
||||
// - if the annotation already exists we should update it.
|
||||
// - we should not allow setting annotations on invalid URIs or itemIds.
|
||||
// This query will tell us:
|
||||
// - whether the item or page exists.
|
||||
// - whether the annotation already exists.
|
||||
// - the nameID associated with the annotation name.
|
||||
// - the id and dateAdded of the old annotation, if it exists.
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
|
||||
"SELECT b.id, "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, "
|
||||
"a.id, a.dateAdded, b.parent, b.type, b.lastModified, b.guid, p.guid "
|
||||
"FROM moz_bookmarks b "
|
||||
"JOIN moz_bookmarks p ON p.id = b.parent "
|
||||
"LEFT JOIN moz_items_annos a ON a.item_id = b.id "
|
||||
"AND a.anno_attribute_id = nameid "
|
||||
"WHERE b.id = :item_id");
|
||||
NS_ENSURE_STATE(stmt);
|
||||
mozStorageStatementScoper checkAnnoScoper(stmt);
|
||||
|
||||
rv = stmt->BindUTF8StringByName("anno_name"_ns, aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64ByName("item_id"_ns, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasResult;
|
||||
rv = stmt->ExecuteStep(&hasResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!hasResult) {
|
||||
// We are trying to create an annotation on an invalid bookmark
|
||||
// or history entry.
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int64_t fkId = stmt->AsInt64(0);
|
||||
int64_t nameID = stmt->AsInt64(1);
|
||||
int64_t oldAnnoId = stmt->AsInt64(2);
|
||||
int64_t oldAnnoDate = stmt->AsInt64(3);
|
||||
|
||||
aStatement = mDB->GetStatement(
|
||||
"INSERT OR REPLACE INTO moz_items_annos "
|
||||
"(id, item_id, anno_attribute_id, content, flags, "
|
||||
"expiration, type, dateAdded, lastModified) "
|
||||
"VALUES (:id, :fk, :name_id, :content, :flags, "
|
||||
":expiration, :type, :date_added, :last_modified)");
|
||||
|
||||
// Since we're already querying `moz_bookmarks`, we fetch the changed
|
||||
// bookmark's info here, instead of using `FetchItemInfo`.
|
||||
MOZ_ASSERT(aBookmark);
|
||||
aBookmark->id = fkId;
|
||||
aBookmark->parentId = stmt->AsInt64(4);
|
||||
aBookmark->type = stmt->AsInt64(5);
|
||||
|
||||
aBookmark->lastModified = static_cast<PRTime>(stmt->AsInt64(6));
|
||||
if (NS_FAILED(stmt->GetUTF8String(7, aBookmark->guid)) ||
|
||||
NS_FAILED(stmt->GetUTF8String(8, aBookmark->parentGuid))) {
|
||||
aBookmark->id = -1;
|
||||
}
|
||||
NS_ENSURE_STATE(aStatement);
|
||||
mozStorageStatementScoper setAnnoScoper(aStatement);
|
||||
|
||||
// Don't replace existing annotations.
|
||||
if (oldAnnoId > 0) {
|
||||
rv = aStatement->BindInt64ByName("id"_ns, oldAnnoId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStatement->BindInt64ByName("date_added"_ns, oldAnnoDate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
rv = aStatement->BindNullByName("id"_ns);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStatement->BindInt64ByName("date_added"_ns, RoundedPRNow());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = aStatement->BindInt64ByName("fk"_ns, fkId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStatement->BindInt64ByName("name_id"_ns, nameID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStatement->BindInt32ByName("flags"_ns, aFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStatement->BindInt32ByName("expiration"_ns, aExpiration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStatement->BindInt32ByName("type"_ns, aType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aStatement->BindInt64ByName("last_modified"_ns, RoundedPRNow());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// On success, leave the statement open, the caller will set the value
|
||||
// and execute the statement.
|
||||
setAnnoScoper.Abandon();
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAnnotationService_h___
|
||||
#define nsAnnotationService_h___
|
||||
|
||||
#include "nsIAnnotationService.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "Database.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace places {
|
||||
|
||||
struct BookmarkData;
|
||||
|
||||
} // namespace places
|
||||
} // namespace mozilla
|
||||
|
||||
class nsAnnotationService final : public nsIAnnotationService,
|
||||
public nsSupportsWeakReference {
|
||||
using BookmarkData = mozilla::places::BookmarkData;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIANNOTATIONSERVICE
|
||||
|
||||
nsAnnotationService();
|
||||
|
||||
/**
|
||||
* Obtains the service's object.
|
||||
*/
|
||||
static already_AddRefed<nsAnnotationService> GetSingleton();
|
||||
|
||||
/**
|
||||
* Initializes the service's object. This should only be called once.
|
||||
*/
|
||||
nsresult Init();
|
||||
|
||||
/**
|
||||
* Returns a cached pointer to the annotation service for consumers in the
|
||||
* places directory.
|
||||
*/
|
||||
static nsAnnotationService* GetAnnotationService() {
|
||||
if (!gAnnotationService) {
|
||||
nsCOMPtr<nsIAnnotationService> serv =
|
||||
do_GetService(NS_ANNOTATIONSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(serv, nullptr);
|
||||
NS_ASSERTION(gAnnotationService,
|
||||
"Should have static instance pointer now");
|
||||
}
|
||||
return gAnnotationService;
|
||||
}
|
||||
|
||||
private:
|
||||
~nsAnnotationService();
|
||||
|
||||
protected:
|
||||
RefPtr<mozilla::places::Database> mDB;
|
||||
|
||||
static nsAnnotationService* gAnnotationService;
|
||||
|
||||
static const int kAnnoIndex_ID;
|
||||
static const int kAnnoIndex_PageOrItem;
|
||||
static const int kAnnoIndex_NameID;
|
||||
static const int kAnnoIndex_Content;
|
||||
static const int kAnnoIndex_Flags;
|
||||
static const int kAnnoIndex_Expiration;
|
||||
static const int kAnnoIndex_Type;
|
||||
static const int kAnnoIndex_DateAdded;
|
||||
static const int kAnnoIndex_LastModified;
|
||||
|
||||
nsresult StartGetAnnotation(int64_t aItemId, const nsACString& aName,
|
||||
nsCOMPtr<mozIStorageStatement>& aStatement);
|
||||
|
||||
nsresult StartSetAnnotation(int64_t aItemId, BookmarkData* aBookmark,
|
||||
const nsACString& aName, int32_t aFlags,
|
||||
uint16_t aExpiration, uint16_t aType,
|
||||
nsCOMPtr<mozIStorageStatement>& aStatement);
|
||||
|
||||
nsresult SetAnnotationStringInternal(int64_t aItemId, BookmarkData* aBookmark,
|
||||
const nsACString& aName,
|
||||
const nsAString& aValue, int32_t aFlags,
|
||||
uint16_t aExpiration);
|
||||
nsresult SetAnnotationInt32Internal(int64_t aItemId, BookmarkData* aBookmark,
|
||||
const nsACString& aName, int32_t aValue,
|
||||
int32_t aFlags, uint16_t aExpiration);
|
||||
nsresult SetAnnotationInt64Internal(int64_t aItemId, BookmarkData* aBookmark,
|
||||
const nsACString& aName, int64_t aValue,
|
||||
int32_t aFlags, uint16_t aExpiration);
|
||||
nsresult SetAnnotationDoubleInternal(int64_t aItemId, BookmarkData* aBookmark,
|
||||
const nsACString& aName, double aValue,
|
||||
int32_t aFlags, uint16_t aExpiration);
|
||||
|
||||
nsresult RemoveAnnotationInternal(int64_t aItemId, BookmarkData* aBookmark,
|
||||
const nsACString& aName);
|
||||
|
||||
nsresult GetValueFromStatement(nsCOMPtr<mozIStorageStatement>& aStatement,
|
||||
nsIVariant** _retval);
|
||||
|
||||
public:
|
||||
nsresult RemoveItemAnnotations(int64_t aItemId);
|
||||
};
|
||||
|
||||
#endif /* nsAnnotationService_h___ */
|
@ -1,104 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIVariant;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* THE ANNOTATION SERVICE API IS
|
||||
*
|
||||
* === D E P R E C A T E D ===
|
||||
*
|
||||
* See https://bugzilla.mozilla.org/show_bug.cgi?id=699844
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
[scriptable, uuid(D4CDAAB1-8EEC-47A8-B420-AD7CB333056A)]
|
||||
interface nsIAnnotationService : nsISupports
|
||||
{
|
||||
/**
|
||||
* Valid values for aExpiration, which sets the expiration policy for your
|
||||
* annotation.
|
||||
*/
|
||||
|
||||
// For annotations that only live as long as the URI is in the database.
|
||||
// A page annotation will expire if the page has no visits
|
||||
// and is not bookmarked.
|
||||
// An item annotation will expire when the item is deleted.
|
||||
const unsigned short EXPIRE_NEVER = 4;
|
||||
|
||||
// type constants
|
||||
const unsigned short TYPE_INT32 = 1;
|
||||
const unsigned short TYPE_DOUBLE = 2;
|
||||
const unsigned short TYPE_STRING = 3;
|
||||
const unsigned short TYPE_INT64 = 5;
|
||||
|
||||
/**
|
||||
* Sets an annotation, overwriting any previous annotation with the same
|
||||
* URL/name. IT IS YOUR JOB TO NAMESPACE YOUR ANNOTATION NAMES.
|
||||
* Use the form "namespace/value", so your name would be like
|
||||
* "bills_extension/page_state" or "history/thumbnail".
|
||||
*
|
||||
* Do not use characters that are not valid in URLs such as spaces, ":",
|
||||
* commas, or most other symbols. You should stick to ASCII letters and
|
||||
* numbers plus "_", "-", and "/".
|
||||
*
|
||||
* aExpiration is one of EXPIRE_* above. aFlags should be 0 for now, some
|
||||
* flags will be defined in the future.
|
||||
*
|
||||
* For item annotations, aSource should be a change source constant from
|
||||
* nsINavBookmarksService::SOURCE_*, and defaults to SOURCE_DEFAULT if
|
||||
* omitted. Setting an item annotation also notifies
|
||||
* `nsINavBookmarkObserver::onItemChanged` for the affected item.
|
||||
*
|
||||
* The annotation "favicon" is special. Favicons are stored in the favicon
|
||||
* service, but are special cased in the protocol handler so they look like
|
||||
* annotations. Do not set favicons using this service, it will not work.
|
||||
*
|
||||
* Only C++ consumers may use the type-specific methods.
|
||||
*
|
||||
* @throws NS_ERROR_ILLEGAL_VALUE if the page or the bookmark doesn't exist.
|
||||
*/
|
||||
void setItemAnnotation(in long long aItemId,
|
||||
in AUTF8String aName,
|
||||
in nsIVariant aValue,
|
||||
in long aFlags,
|
||||
in unsigned short aExpiration,
|
||||
[optional] in unsigned short aSource,
|
||||
[optional] in bool aDontUpdateLastModified);
|
||||
|
||||
/**
|
||||
* Retrieves the value of a given annotation. Throws an error if the
|
||||
* annotation does not exist. C++ consumers may use the type-specific
|
||||
* methods.
|
||||
*
|
||||
* The type-specific methods throw if the given annotation is set in
|
||||
* a different type.
|
||||
*/
|
||||
nsIVariant getItemAnnotation(in long long aItemId,
|
||||
in AUTF8String aName);
|
||||
|
||||
/**
|
||||
* Test for annotation existence.
|
||||
*/
|
||||
boolean itemHasAnnotation(in long long aItemId,
|
||||
in AUTF8String aName);
|
||||
|
||||
/**
|
||||
* Removes a specific annotation. Succeeds even if the annotation is
|
||||
* not found.
|
||||
*
|
||||
* Removing an item annotation also notifies
|
||||
* `nsINavBookmarkObserver::onItemChanged` for the affected item.
|
||||
*/
|
||||
void removeItemAnnotation(in long long aItemId,
|
||||
in AUTF8String aName,
|
||||
[optional] in unsigned short aSource);
|
||||
};
|
@ -6,7 +6,6 @@
|
||||
#include "nsNavBookmarks.h"
|
||||
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsAnnotationService.h"
|
||||
#include "nsPlacesMacros.h"
|
||||
#include "Helpers.h"
|
||||
|
||||
@ -560,16 +559,6 @@ nsNavBookmarks::RemoveItem(int64_t aItemId, uint16_t aSource) {
|
||||
|
||||
mozStorageTransaction transaction(mDB->MainConn(), false);
|
||||
|
||||
// First, if not a tag, remove item annotations.
|
||||
int64_t tagsRootId = TagsRootId();
|
||||
bool isUntagging = bookmark.grandParentId == tagsRootId;
|
||||
if (bookmark.parentId != tagsRootId && !isUntagging) {
|
||||
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
|
||||
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = annosvc->RemoveItemAnnotations(bookmark.id);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (bookmark.type == TYPE_FOLDER) {
|
||||
// Remove all of the folder's children.
|
||||
rv = RemoveFolderChildren(bookmark.id, aSource);
|
||||
@ -610,7 +599,8 @@ nsNavBookmarks::RemoveItem(int64_t aItemId, uint16_t aSource) {
|
||||
syncChangeDelta);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isUntagging) {
|
||||
int64_t tagsRootId = TagsRootId();
|
||||
if (bookmark.grandParentId == tagsRootId) {
|
||||
// If we're removing a tag, increment the change counter for all bookmarks
|
||||
// with the URI.
|
||||
rv = AddSyncChangesForBookmarksWithURL(bookmark.url, syncChangeDelta);
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include "mozIPlacesAutoComplete.h"
|
||||
#include "nsNavBookmarks.h"
|
||||
#include "nsAnnotationService.h"
|
||||
#include "nsFaviconService.h"
|
||||
#include "nsPlacesMacros.h"
|
||||
#include "nsPlacesTriggers.h"
|
||||
@ -117,9 +116,6 @@ using namespace mozilla::places;
|
||||
// for repeating stuff. These are milliseconds between "now" cache refreshes.
|
||||
#define RENEW_CACHED_NOW_TIMEOUT ((int32_t)3 * PR_MSEC_PER_SEC)
|
||||
|
||||
// character-set annotation
|
||||
#define CHARSET_ANNO "URIProperties/characterSet"_ns
|
||||
|
||||
// These macros are used when splitting history by date.
|
||||
// These are the day containers and catch-all final container.
|
||||
#define HISTORY_ADDITIONAL_DATE_CONT_NUM 3
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsNavBookmarks.h"
|
||||
#include "nsFaviconService.h"
|
||||
#include "nsAnnotationService.h"
|
||||
#include "Helpers.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "nsDebug.h"
|
||||
|
@ -42,11 +42,6 @@ add_task(async function test_eraseEverything() {
|
||||
url: "http://mozilla.org/",
|
||||
});
|
||||
checkBookmarkObject(unfiledBookmarkInFolder);
|
||||
await setItemAnnotation(
|
||||
unfiledBookmarkInFolder.guid,
|
||||
"testanno1",
|
||||
"testvalue1"
|
||||
);
|
||||
|
||||
let menuFolder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
@ -65,7 +60,6 @@ add_task(async function test_eraseEverything() {
|
||||
url: "http://mozilla.org/",
|
||||
});
|
||||
checkBookmarkObject(menuBookmarkInFolder);
|
||||
await setItemAnnotation(menuBookmarkInFolder.guid, "testanno1", "testvalue1");
|
||||
|
||||
let toolbarFolder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
@ -84,11 +78,6 @@ add_task(async function test_eraseEverything() {
|
||||
url: "http://mozilla.org/",
|
||||
});
|
||||
checkBookmarkObject(toolbarBookmarkInFolder);
|
||||
await setItemAnnotation(
|
||||
toolbarBookmarkInFolder.guid,
|
||||
"testanno1",
|
||||
"testvalue1"
|
||||
);
|
||||
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
Assert.ok(frecencyForUrl("http://example.com/") > frecencyForExample);
|
||||
@ -103,17 +92,6 @@ add_task(async function test_eraseEverything() {
|
||||
|
||||
Assert.equal(frecencyForUrl("http://example.com/"), frecencyForExample);
|
||||
Assert.equal(frecencyForUrl("http://example.com/"), frecencyForMozilla);
|
||||
|
||||
// Check there are no orphan annotations.
|
||||
let conn = await PlacesUtils.promiseDBConnection();
|
||||
let annoAttrs = await conn.execute(
|
||||
`SELECT id, name FROM moz_anno_attributes`
|
||||
);
|
||||
Assert.equal(annoAttrs.length, 0);
|
||||
let annos = await conn.execute(
|
||||
`SELECT item_id, anno_attribute_id FROM moz_items_annos`
|
||||
);
|
||||
Assert.equal(annos.length, 0);
|
||||
});
|
||||
|
||||
add_task(async function test_eraseEverything_roots() {
|
||||
|
@ -285,30 +285,6 @@ add_task(async function remove_multiple_bookmarks_complex() {
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
});
|
||||
|
||||
add_task(async function remove_bookmark_orphans() {
|
||||
let bm1 = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
url: "http://example.com/",
|
||||
title: "a bookmark",
|
||||
});
|
||||
checkBookmarkObject(bm1);
|
||||
await setItemAnnotation(bm1.guid, "testanno", "testvalue");
|
||||
|
||||
await PlacesUtils.bookmarks.remove(bm1.guid);
|
||||
|
||||
// Check there are no orphan annotations.
|
||||
let conn = await PlacesUtils.promiseDBConnection();
|
||||
let annoAttrs = await conn.execute(
|
||||
`SELECT id, name FROM moz_anno_attributes`
|
||||
);
|
||||
Assert.equal(annoAttrs.length, 0);
|
||||
let annos = await conn.execute(
|
||||
`SELECT item_id, anno_attribute_id FROM moz_items_annos`
|
||||
);
|
||||
Assert.equal(annos.length, 0);
|
||||
});
|
||||
|
||||
add_task(async function remove_bookmark_empty_title() {
|
||||
let bm1 = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
|
@ -11,14 +11,8 @@
|
||||
* database.
|
||||
* If the annotation is a page annotation this will happen when the page is
|
||||
* expired, namely when the page has no visits and is not bookmarked.
|
||||
* Otherwise if it's an item annotation the annotation will be expired when
|
||||
* the item is removed, thus expiration won't handle this case at all.
|
||||
*/
|
||||
|
||||
var as = Cc["@mozilla.org/browser/annotation-service;1"].getService(
|
||||
Ci.nsIAnnotationService
|
||||
);
|
||||
|
||||
add_task(async function test_annos_expire_never() {
|
||||
// Set interval to a large value so we don't expire on it.
|
||||
setInterval(3600); // 1h
|
||||
@ -45,26 +39,6 @@ add_task(async function test_annos_expire_never() {
|
||||
pages = await getPagesWithAnnotation("page_expire2");
|
||||
Assert.equal(pages.length, 5);
|
||||
|
||||
// Add some bookmarked page and a couple expire never annotations for each.
|
||||
for (let i = 0; i < 5; i++) {
|
||||
let pageURI = uri("http://item_anno." + i + ".mozilla.org/");
|
||||
// We also add a visit before bookmarking.
|
||||
await PlacesTestUtils.addVisits({ uri: pageURI, visitDate: now++ });
|
||||
let bm = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: pageURI,
|
||||
title: null,
|
||||
});
|
||||
let id = await PlacesUtils.promiseItemId(bm.guid);
|
||||
as.setItemAnnotation(id, "item_persist1", "test", 0, as.EXPIRE_NEVER);
|
||||
as.setItemAnnotation(id, "item_persist2", "test", 0, as.EXPIRE_NEVER);
|
||||
}
|
||||
|
||||
let items = await getItemsWithAnnotation("item_persist1");
|
||||
Assert.equal(items.length, 5);
|
||||
items = await getItemsWithAnnotation("item_persist2");
|
||||
Assert.equal(items.length, 5);
|
||||
|
||||
// Add other visited page and a couple expire never annotations for each.
|
||||
// We won't expire these visits, so the annotations should survive.
|
||||
for (let i = 0; i < 5; i++) {
|
||||
@ -85,16 +59,12 @@ add_task(async function test_annos_expire_never() {
|
||||
Assert.equal(pages.length, 5);
|
||||
|
||||
// Expire all visits for the first 5 pages and the bookmarks.
|
||||
await promiseForceExpirationStep(10);
|
||||
await promiseForceExpirationStep(5);
|
||||
|
||||
pages = await getPagesWithAnnotation("page_expire1");
|
||||
Assert.equal(pages.length, 0);
|
||||
pages = await getPagesWithAnnotation("page_expire2");
|
||||
Assert.equal(pages.length, 0);
|
||||
items = await getItemsWithAnnotation("item_persist1");
|
||||
Assert.equal(items.length, 5);
|
||||
items = await getItemsWithAnnotation("item_persist2");
|
||||
Assert.equal(items.length, 5);
|
||||
pages = await getPagesWithAnnotation("page_persist1");
|
||||
Assert.equal(pages.length, 5);
|
||||
pages = await getPagesWithAnnotation("page_persist2");
|
||||
|
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
add_task(async function test_historyClear() {
|
||||
let as = PlacesUtils.annotations;
|
||||
// Set interval to a large value so we don't expire on it.
|
||||
setInterval(3600); // 1h
|
||||
|
||||
@ -24,14 +23,11 @@ add_task(async function test_historyClear() {
|
||||
let pageURI = uri("http://item_anno." + i + ".mozilla.org/");
|
||||
// This visit will be expired.
|
||||
await PlacesTestUtils.addVisits({ uri: pageURI });
|
||||
let bm = await PlacesUtils.bookmarks.insert({
|
||||
await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: pageURI,
|
||||
title: null,
|
||||
});
|
||||
let id = await PlacesUtils.promiseItemId(bm.guid);
|
||||
// Will persist because it's an EXPIRE_NEVER item anno.
|
||||
as.setItemAnnotation(id, "persist", "test", 0, as.EXPIRE_NEVER);
|
||||
// Will persist because the page is bookmarked.
|
||||
await PlacesUtils.history.update({
|
||||
url: pageURI,
|
||||
@ -58,12 +54,4 @@ add_task(async function test_historyClear() {
|
||||
|
||||
let pages = await getPagesWithAnnotation("persist");
|
||||
Assert.equal(pages.length, 5);
|
||||
|
||||
let items = await getItemsWithAnnotation("persist");
|
||||
Assert.equal(items.length, 5);
|
||||
|
||||
for (let guid of items) {
|
||||
// Check item exists.
|
||||
Assert.ok(await PlacesUtils.bookmarks.fetch({ guid }), "item exists");
|
||||
}
|
||||
});
|
||||
|
@ -988,46 +988,6 @@ function getPagesWithAnnotation(name) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URLs of pages that have a particular annotation.
|
||||
*
|
||||
* @param {String} name The name of the annotation to search for.
|
||||
* @return An array of GUIDs found.
|
||||
*/
|
||||
function getItemsWithAnnotation(name) {
|
||||
return PlacesUtils.promiseDBConnection().then(async db => {
|
||||
let rows = await db.execute(
|
||||
`
|
||||
SELECT b.guid FROM moz_anno_attributes n
|
||||
JOIN moz_items_annos a ON n.id = a.anno_attribute_id
|
||||
JOIN moz_bookmarks b ON b.id = a.item_id
|
||||
WHERE n.name = :name
|
||||
`,
|
||||
{ name }
|
||||
);
|
||||
|
||||
return rows.map(row => row.getResultByName("guid"));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an annotation for an item.
|
||||
*
|
||||
* @param {String} guid The GUID of the item.
|
||||
* @param {String} name The name of the annotation.
|
||||
* @param {Number|String} value The value of the annotation.
|
||||
*/
|
||||
async function setItemAnnotation(guid, name, value) {
|
||||
let id = await PlacesUtils.promiseItemId(guid);
|
||||
PlacesUtils.annotations.setItemAnnotation(
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks there are no orphan page annotations in the database, and no
|
||||
* orphan anno attribute names.
|
||||
|
@ -363,8 +363,8 @@ add_task(async function test_simple_change_annotations() {
|
||||
{
|
||||
content: "testContent",
|
||||
flags: 0,
|
||||
type: Ci.nsIAnnotationService.TYPE_STRING,
|
||||
expiration: Ci.nsIAnnotationService.EXPIRE_NEVER,
|
||||
type: PlacesUtils.history.ANNOTATION_TYPE_STRING,
|
||||
expiration: PlacesUtils.history.ANNOTATION_EXPIRE_NEVER,
|
||||
},
|
||||
annotationInfo[0],
|
||||
"Should have stored the correct annotation data in the db"
|
||||
@ -425,8 +425,8 @@ add_task(async function test_simple_change_annotations() {
|
||||
{
|
||||
content: 1234,
|
||||
flags: 0,
|
||||
type: Ci.nsIAnnotationService.TYPE_INT64,
|
||||
expiration: Ci.nsIAnnotationService.EXPIRE_NEVER,
|
||||
type: PlacesUtils.history.ANNOTATION_TYPE_INT64,
|
||||
expiration: PlacesUtils.history.ANNOTATION_EXPIRE_NEVER,
|
||||
},
|
||||
annotationInfo[0],
|
||||
"Should have updated the annotation data in the db"
|
||||
|
@ -14,7 +14,6 @@
|
||||
var hs = PlacesUtils.history;
|
||||
var bs = PlacesUtils.bookmarks;
|
||||
var ts = PlacesUtils.tagging;
|
||||
var as = PlacesUtils.annotations;
|
||||
var fs = PlacesUtils.favicons;
|
||||
|
||||
var mDBConn = hs.DBConnection;
|
||||
@ -2762,7 +2761,6 @@ tests.push({
|
||||
url: this._uri2,
|
||||
annotations: new Map([["anno", "anno"]]),
|
||||
});
|
||||
as.setItemAnnotation(this._bookmarkId, "anno", "anno", 0, as.EXPIRE_NEVER);
|
||||
},
|
||||
|
||||
async check() {
|
||||
@ -2790,7 +2788,6 @@ tests.push({
|
||||
includeAnnotations: true,
|
||||
});
|
||||
Assert.equal(pageInfo.annotations.get("anno"), "anno");
|
||||
Assert.equal(as.getItemAnnotation(this._bookmarkId, "anno"), "anno");
|
||||
|
||||
await new Promise(resolve => {
|
||||
fs.getFaviconURLForPage(this._uri2, aFaviconURI => {
|
||||
|
@ -104,23 +104,6 @@ async function task_populateDB(aArray) {
|
||||
});
|
||||
}
|
||||
|
||||
if (qdata.isItemAnnotation) {
|
||||
if (qdata.removeAnnotation) {
|
||||
PlacesUtils.annotations.removeItemAnnotation(
|
||||
qdata.itemId,
|
||||
qdata.annoName
|
||||
);
|
||||
} else {
|
||||
PlacesUtils.annotations.setItemAnnotation(
|
||||
qdata.itemId,
|
||||
qdata.annoName,
|
||||
qdata.annoVal,
|
||||
0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (qdata.isFolder) {
|
||||
await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: qdata.parentGuid,
|
||||
@ -203,7 +186,6 @@ function queryData(obj) {
|
||||
this.removeAnnotation = !!obj.removeAnnotation;
|
||||
this.annoName = obj.annoName ? obj.annoName : "";
|
||||
this.annoVal = obj.annoVal ? obj.annoVal : "";
|
||||
this.isItemAnnotation = obj.isItemAnnotation ? obj.isItemAnnotation : false;
|
||||
this.itemId = obj.itemId ? obj.itemId : 0;
|
||||
this.annoMimeType = obj.annoMimeType ? obj.annoMimeType : "";
|
||||
this.isTag = obj.isTag ? obj.isTag : false;
|
||||
|
@ -1,164 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Get annotation service
|
||||
try {
|
||||
var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].getService(
|
||||
Ci.nsIAnnotationService
|
||||
);
|
||||
} catch (ex) {
|
||||
do_throw("Could not get annotation service\n");
|
||||
}
|
||||
|
||||
add_task(async function test_execute() {
|
||||
let testURI = uri("http://mozilla.com/");
|
||||
let testItem = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: "",
|
||||
url: testURI,
|
||||
});
|
||||
let testItemId = await PlacesUtils.promiseItemId(testItem.guid);
|
||||
let testAnnoName = "moz-test-places/annotations";
|
||||
let testAnnoVal = "test";
|
||||
let earlierDate = new Date(Date.now() - 1000);
|
||||
|
||||
// string item-annotation
|
||||
let item = await PlacesUtils.bookmarks.fetch(testItem.guid);
|
||||
|
||||
// Verify that lastModified equals dateAdded before we set the annotation.
|
||||
Assert.equal(item.lastModified.getTime(), item.dateAdded.getTime());
|
||||
// Workaround possible VM timers issues moving last modified to the past.
|
||||
await PlacesUtils.bookmarks.update({
|
||||
guid: item.guid,
|
||||
dateAdded: earlierDate,
|
||||
lastModified: earlierDate,
|
||||
});
|
||||
|
||||
try {
|
||||
annosvc.setItemAnnotation(
|
||||
testItemId,
|
||||
testAnnoName,
|
||||
testAnnoVal,
|
||||
0,
|
||||
annosvc.EXPIRE_NEVER
|
||||
);
|
||||
} catch (ex) {
|
||||
do_throw("unable to add item annotation " + ex);
|
||||
}
|
||||
|
||||
let updatedItem = await PlacesUtils.bookmarks.fetch(testItem.guid);
|
||||
|
||||
Assert.equal(
|
||||
updatedItem.lastModified.getTime(),
|
||||
earlierDate.getTime(),
|
||||
"Setting an item annotation should not update lastModified"
|
||||
);
|
||||
|
||||
try {
|
||||
var annoVal = annosvc.getItemAnnotation(testItemId, testAnnoName);
|
||||
// verify the anno value
|
||||
Assert.ok(testAnnoVal === annoVal);
|
||||
} catch (ex) {
|
||||
do_throw("unable to get item annotation");
|
||||
}
|
||||
|
||||
try {
|
||||
annosvc.getItemAnnotation(testURI, "blah");
|
||||
do_throw("fetching item-annotation that doesn't exist, should've thrown");
|
||||
} catch (ex) {}
|
||||
|
||||
// test int32 anno type
|
||||
var int32Key = testAnnoName + "/types/Int32";
|
||||
var int32Val = 23;
|
||||
annosvc.setItemAnnotation(
|
||||
testItemId,
|
||||
int32Key,
|
||||
int32Val,
|
||||
0,
|
||||
annosvc.EXPIRE_NEVER
|
||||
);
|
||||
Assert.ok(annosvc.itemHasAnnotation(testItemId, int32Key));
|
||||
let storedVal = annosvc.getItemAnnotation(testItemId, int32Key);
|
||||
Assert.ok(int32Val === storedVal);
|
||||
|
||||
// test int64 anno type
|
||||
var int64Key = testAnnoName + "/types/Int64";
|
||||
var int64Val = 4294967296;
|
||||
annosvc.setItemAnnotation(
|
||||
testItemId,
|
||||
int64Key,
|
||||
int64Val,
|
||||
0,
|
||||
annosvc.EXPIRE_NEVER
|
||||
);
|
||||
Assert.ok(annosvc.itemHasAnnotation(testItemId, int64Key));
|
||||
storedVal = annosvc.getItemAnnotation(testItemId, int64Key);
|
||||
Assert.ok(int64Val === storedVal);
|
||||
|
||||
// test double anno type
|
||||
var doubleKey = testAnnoName + "/types/Double";
|
||||
var doubleVal = 0.000002342;
|
||||
annosvc.setItemAnnotation(
|
||||
testItemId,
|
||||
doubleKey,
|
||||
doubleVal,
|
||||
0,
|
||||
annosvc.EXPIRE_NEVER
|
||||
);
|
||||
Assert.ok(annosvc.itemHasAnnotation(testItemId, doubleKey));
|
||||
storedVal = annosvc.getItemAnnotation(testItemId, doubleKey);
|
||||
Assert.ok(doubleVal === storedVal);
|
||||
|
||||
// test annotation removal
|
||||
annosvc.setItemAnnotation(
|
||||
testItemId,
|
||||
testAnnoName,
|
||||
testAnnoVal,
|
||||
0,
|
||||
annosvc.EXPIRE_NEVER
|
||||
);
|
||||
// verify that removing an annotation does not update the last modified date
|
||||
testItem = await PlacesUtils.bookmarks.fetch(testItem.guid);
|
||||
|
||||
// Workaround possible VM timers issues moving last modified to the past.
|
||||
await PlacesUtils.bookmarks.update({
|
||||
guid: testItem.guid,
|
||||
dateAdded: earlierDate,
|
||||
lastModified: earlierDate,
|
||||
});
|
||||
annosvc.removeItemAnnotation(testItemId, int32Key);
|
||||
|
||||
testItem = await PlacesUtils.bookmarks.fetch(testItem.guid);
|
||||
info(
|
||||
"verify that removing an annotation does not update the last modified date"
|
||||
);
|
||||
Assert.equal(
|
||||
testItem.lastModified.getTime(),
|
||||
earlierDate.getTime(),
|
||||
"Setting an item annotation should not update lastModified"
|
||||
);
|
||||
|
||||
// test that getItems/PagesWithAnnotation returns an empty array after
|
||||
// removing all items/pages which had the annotation set, see bug 380317.
|
||||
Assert.equal((await getItemsWithAnnotation(int32Key)).length, 0);
|
||||
Assert.equal((await getPagesWithAnnotation(int32Key)).length, 0);
|
||||
|
||||
// Setting item annotations on invalid item ids should throw
|
||||
var invalidIds = [-1, 0, 37643];
|
||||
for (var id of invalidIds) {
|
||||
try {
|
||||
annosvc.setItemAnnotation(id, "foo", "bar", 0, annosvc.EXPIRE_NEVER);
|
||||
do_throw("setItemAnnotation* should throw for invalid item id: " + id);
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
// setting an annotation with EXPIRE_HISTORY for an item should throw
|
||||
item = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: "",
|
||||
url: testURI,
|
||||
});
|
||||
});
|
@ -21,7 +21,7 @@ var histograms = {
|
||||
PLACES_EXPIRATION_STEPS_TO_CLEAN2: val => Assert.ok(val > 1),
|
||||
PLACES_IDLE_FRECENCY_DECAY_TIME_MS: val => Assert.ok(val >= 0),
|
||||
PLACES_IDLE_MAINTENANCE_TIME_MS: val => Assert.ok(val > 0),
|
||||
PLACES_ANNOS_BOOKMARKS_COUNT: val => Assert.equal(val, 1),
|
||||
PLACES_ANNOS_BOOKMARKS_COUNT: val => Assert.equal(val, 0),
|
||||
PLACES_ANNOS_PAGES_COUNT: val => Assert.equal(val, 1),
|
||||
PLACES_MAINTENANCE_DAYSFROMLAST: val => Assert.ok(val >= 0),
|
||||
};
|
||||
@ -69,7 +69,7 @@ add_task(async function test_execute() {
|
||||
// Put some trash in the database.
|
||||
let uri = Services.io.newURI("http://moz.org/");
|
||||
|
||||
let bookmarks = await PlacesUtils.bookmarks.insertTree({
|
||||
PlacesUtils.bookmarks.insertTree({
|
||||
guid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
children: [
|
||||
{
|
||||
@ -94,7 +94,6 @@ add_task(async function test_execute() {
|
||||
content += "0";
|
||||
}
|
||||
|
||||
await setItemAnnotation(bookmarks[1].guid, "test-anno", content);
|
||||
await PlacesUtils.history.update({
|
||||
url: uri,
|
||||
annotations: new Map([["test-anno", content]]),
|
||||
|
@ -43,7 +43,6 @@ skip-if = appname == "thunderbird"
|
||||
[test_1105208.js]
|
||||
[test_1105866.js]
|
||||
[test_1606731.js]
|
||||
[test_annotations.js]
|
||||
[test_asyncExecuteLegacyQueries.js]
|
||||
[test_async_transactions.js]
|
||||
[test_bookmarks_json.js]
|
||||
|
Loading…
Reference in New Issue
Block a user