--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -29,22 +29,20 @@ XPCOMUtils.defineLazyGetter(this, "MOZ_A
// we really just want "\n". On other platforms, the transferable system
// converts "\r\n" to "\n".
const NEWLINE = AppConstants.platform == "macosx" ? "\n" : "\r\n";
// Timers resolution is not always good, it can have a 16ms precision on Win.
const TIMERS_RESOLUTION_SKEW_MS = 16;
function QI_node(aNode, aIID) {
- var result = null;
try {
- result = aNode.QueryInterface(aIID);
- } catch (e) {
- }
- return result;
+ return aNode.QueryInterface(aIID);
+ } catch (ex) {}
+ return null;
}
function asContainer(aNode) {
return QI_node(aNode, Ci.nsINavHistoryContainerResultNode);
}
function asQuery(aNode) {
return QI_node(aNode, Ci.nsINavHistoryQueryResultNode);
}
@@ -74,18 +72,20 @@ function notify(observers, notification,
* @param keyword
* The keyword to notify, or empty string if a keyword was removed.
*/
async function notifyKeywordChange(url, keyword, source) {
// Notify bookmarks about the removal.
let bookmarks = [];
await PlacesUtils.bookmarks.fetch({ url }, b => bookmarks.push(b));
for (let bookmark of bookmarks) {
- bookmark.id = await PlacesUtils.promiseItemId(bookmark.guid);
- bookmark.parentId = await PlacesUtils.promiseItemId(bookmark.parentGuid);
+ let ids = await PlacesUtils.promiseManyItemIds([bookmark.guid,
+ bookmark.parentGuid]);
+ bookmark.id = ids.get(bookmark.guid);
+ bookmark.parentId = ids.get(bookmark.parentGuid);
}
let observers = PlacesUtils.bookmarks.getObservers();
for (let bookmark of bookmarks) {
notify(observers, "onItemChanged", [ bookmark.id, "keyword", false,
keyword,
bookmark.lastModified * 1000,
bookmark.type,
bookmark.parentId,
@@ -189,16 +189,32 @@ function serializeNode(aNode, aIsLivemar
}
// Imposed to limit database size.
const DB_URL_LENGTH_MAX = 65536;
const DB_TITLE_LENGTH_MAX = 4096;
const DB_DESCRIPTION_LENGTH_MAX = 256;
/**
+ * Executes a boolean validate function, throwing if it returns false.
+ *
+ * @param boolValidateFn
+ * A boolean validate function.
+ * @return the input value.
+ * @throws if input doesn't pass the validate function.
+ */
+function simpleValidateFunc(boolValidateFn) {
+ return (v, input) => {
+ if (!boolValidateFn(v, input))
+ throw new Error("Invalid value");
+ return v;
+ };
+}
+
+/**
* List of bookmark object validators, one per each known property.
* Validators must throw if the property value is invalid and return a fixed up
* version of the value, if needed.
*/
const BOOKMARK_VALIDATORS = Object.freeze({
guid: simpleValidateFunc(v => PlacesUtils.isValidGuid(v)),
parentGuid: simpleValidateFunc(v => PlacesUtils.isValidGuid(v)),
guidPrefix: simpleValidateFunc(v => PlacesUtils.isValidGuidPrefix(v)),
@@ -673,19 +689,16 @@ this.PlacesUtils = {
Services.obs.removeObserver(this, this.TOPIC_SHUTDOWN);
while (this._shutdownFunctions.length > 0) {
this._shutdownFunctions.shift().apply(this);
}
break;
}
},
- onPageAnnotationSet() {},
- onPageAnnotationRemoved() {},
-
/**
* Determines whether or not a ResultNode is a host container.
* @param aNode
* A result node
* @returns true if the node is a host container, false otherwise
*/
nodeIsHost: function PU_nodeIsHost(aNode) {
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
@@ -951,17 +964,17 @@ this.PlacesUtils = {
let titleString = "";
if (parts.length > i + 1)
titleString = parts[i + 1];
else {
// for drag and drop of files, try to use the leafName as title
try {
titleString = Services.io.newURI(uriString).QueryInterface(Ci.nsIURL)
.fileName;
- } catch (e) {}
+ } catch (ex) {}
}
// note: Services.io.newURI() will throw if uriString is not a valid URI
if (Services.io.newURI(uriString)) {
nodes.push({ uri: uriString,
title: titleString ? titleString : uriString,
type: this.TYPE_X_MOZ_URL });
}
}
@@ -1414,75 +1427,66 @@ this.PlacesUtils = {
* Sets the character-set for a URI.
*
* @param {nsIURI} aURI
* @param {String} aCharset character-set value.
* @return {Promise}
*/
setCharsetForURI: function PU_setCharsetForURI(aURI, aCharset) {
return new Promise(resolve => {
-
// Delaying to catch issues with asynchronous behavior while waiting
// to implement asynchronous annotations in bug 699844.
Services.tm.dispatchToMainThread(function() {
if (aCharset && aCharset.length > 0) {
PlacesUtils.annotations.setPageAnnotation(
aURI, PlacesUtils.CHARSET_ANNO, aCharset, 0,
Ci.nsIAnnotationService.EXPIRE_NEVER);
} else {
PlacesUtils.annotations.removePageAnnotation(
aURI, PlacesUtils.CHARSET_ANNO);
}
resolve();
});
-
});
},
/**
* Gets the last saved character-set for a URI.
*
* @param aURI nsIURI
* @return {Promise}
* @resolve a character-set or null.
*/
getCharsetForURI: function PU_getCharsetForURI(aURI) {
return new Promise(resolve => {
-
Services.tm.dispatchToMainThread(function() {
let charset = null;
-
try {
charset = PlacesUtils.annotations.getPageAnnotation(aURI,
PlacesUtils.CHARSET_ANNO);
} catch (ex) { }
-
resolve(charset);
});
-
});
},
/**
* Gets favicon data for a given page url.
*
* @param aPageUrl url of the page to look favicon for.
* @resolves to an object representing a favicon entry, having the following
* properties: { uri, dataLen, data, mimeType }
* @rejects JavaScript exception if the given url has no associated favicon.
*/
promiseFaviconData(aPageUrl) {
return new Promise((resolve, reject) => {
PlacesUtils.favicons.getFaviconDataForPage(NetUtil.newURI(aPageUrl),
- function(aURI, aDataLen, aData, aMimeType) {
- if (aURI) {
- resolve({ uri: aURI,
- dataLen: aDataLen,
- data: aData,
- mimeType: aMimeType });
+ function(uri, dataLen, data, mimeType) {
+ if (uri) {
+ resolve({ uri, dataLen, data, mimeType });
} else {
reject();
}
});
});
},
/**
@@ -1672,18 +1676,18 @@ this.PlacesUtils = {
item.typeCode = type;
if (type == Ci.nsINavBookmarksService.TYPE_BOOKMARK)
copyProps("charset", "tags", "iconuri");
// Add annotations.
if (aRow.getResultByName("has_annos")) {
try {
item.annos = PlacesUtils.getAnnotationsForItem(itemId);
- } catch (e) {
- Cu.reportError("Unexpected error while reading annotations " + e);
+ } catch (ex) {
+ Cu.reportError("Unexpected error while reading annotations " + ex);
}
}
switch (type) {
case Ci.nsINavBookmarksService.TYPE_BOOKMARK:
item.type = PlacesUtils.TYPE_X_MOZ_PLACE;
// If this throws due to an invalid url, the item will be skipped.
item.uri = NetUtil.newURI(aRow.getResultByName("url")).spec;
@@ -1751,17 +1755,16 @@ this.PlacesUtils = {
JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id
WHERE place_id = h.id AND n.name = :charset_anno
) AS charset
FROM descendants d
LEFT JOIN moz_bookmarks b3 ON b3.id = d.parent
LEFT JOIN moz_places h ON h.id = d.fk
ORDER BY d.level, d.parent, d.position`;
-
if (!aItemGuid)
aItemGuid = this.bookmarks.rootGuid;
let hasExcludeItemsCallback =
aOptions.hasOwnProperty("excludeItemsCallback");
let excludedParents = new Set();
let shouldExcludeItem = (aItem, aParentGuid) => {
let exclude = excludedParents.has(aParentGuid) ||
@@ -2001,18 +2004,23 @@ PlacesUtils.keywords = {
let hasKeyword = "keyword" in keywordOrEntry;
let hasUrl = "url" in keywordOrEntry;
if (!hasKeyword && !hasUrl)
throw new Error("At least keyword or url must be provided");
if (onResult && typeof onResult != "function")
throw new Error("onResult callback must be a valid function");
- if (hasUrl)
- keywordOrEntry.url = new URL(keywordOrEntry.url);
+ if (hasUrl) {
+ try {
+ keywordOrEntry.url = BOOKMARK_VALIDATORS.url(keywordOrEntry.url);
+ } catch (ex) {
+ throw new Error(keywordOrEntry.url + " is not a valid URL");
+ }
+ }
if (hasKeyword)
keywordOrEntry.keyword = keywordOrEntry.keyword.trim().toLowerCase();
let safeOnResult = entry => {
if (onResult) {
try {
onResult(entry);
} catch (ex) {
@@ -2047,17 +2055,17 @@ PlacesUtils.keywords = {
/**
* Adds a new keyword and postData for the given URL.
*
* @param keywordEntry
* An object describing the keyword to insert, in the form:
* {
* keyword: non-empty string,
- * URL: URL or href to associate to the keyword,
+ * url: URL or href to associate to the keyword,
* postData: optional POST data to associate to the keyword
* source: The change source, forwarded to all bookmark observers.
* Defaults to nsINavBookmarksService::SOURCE_DEFAULT.
* }
* @note Do not define a postData property if there isn't any POST data.
* Defining an empty string for POST data is equivalent to not having it.
* @resolves when the addition is complete.
*/
@@ -2076,17 +2084,21 @@ PlacesUtils.keywords = {
if (!("source" in keywordEntry)) {
keywordEntry.source = PlacesUtils.bookmarks.SOURCES.DEFAULT;
}
let { keyword, url, source } = keywordEntry;
keyword = keyword.trim().toLowerCase();
let postData = keywordEntry.postData || "";
// This also checks href for validity
- url = new URL(url);
+ try {
+ url = BOOKMARK_VALIDATORS.url(url);
+ } catch (ex) {
+ throw new Error(url + " is not a valid URL");
+ }
return PlacesUtils.withConnectionWrapper("PlacesUtils.keywords.insert", async db => {
let cache = await promiseKeywordsCache();
// Trying to set the same keyword is a no-op.
let oldEntry = cache.get(keyword);
if (oldEntry && oldEntry.url.href == url.href &&
(oldEntry.postData || "") == postData) {
@@ -2561,24 +2573,8 @@ var GuidHelper = {
};
PlacesUtils.bookmarks.addObserver(this.observer);
PlacesUtils.registerShutdownFunction(() => {
PlacesUtils.bookmarks.removeObserver(this.observer);
});
}
}
};
-
-/**
- * Executes a boolean validate function, throwing if it returns false.
- *
- * @param boolValidateFn
- * A boolean validate function.
- * @return the input value.
- * @throws if input doesn't pass the validate function.
- */
-function simpleValidateFunc(boolValidateFn) {
- return (v, input) => {
- if (!boolValidateFn(v, input))
- throw new Error("Invalid value");
- return v;
- };
-}
--- a/toolkit/components/places/nsINavBookmarksService.idl
+++ b/toolkit/components/places/nsINavBookmarksService.idl
@@ -532,34 +532,23 @@ interface nsINavBookmarksService : nsISu
/**
/**
* Get the parent folder's id for an item.
*/
long long getFolderIdForItem(in long long aItemId);
/**
- * Associates the given keyword with the given bookmark.
- *
- * Use an empty keyword to clear the keyword associated with the URI.
- * In both of these cases, succeeds but does nothing if the URL/keyword is not found.
- *
- * @deprecated Use PlacesUtils.keywords.insert() API instead.
- */
- void setKeywordForBookmark(in long long aItemId,
- in AString aKeyword,
- [optional] in unsigned short aSource);
-
- /**
* Retrieves the keyword for the given bookmark. Will be void string
* (null in JS) if no such keyword is found.
*
* @deprecated Use PlacesUtils.keywords.fetch() API instead.
*/
AString getKeywordForBookmark(in long long aItemId);
+
/**
* Adds a bookmark observer. If ownsWeak is false, the bookmark service will
* keep an owning reference to the observer. If ownsWeak is true, then
* aObserver must implement nsISupportsWeakReference, and the bookmark
* service will keep a weak reference to the observer.
*/
void addObserver(in nsINavBookmarkObserver observer,
[optional] in boolean ownsWeak);
--- a/toolkit/components/places/nsNavBookmarks.cpp
+++ b/toolkit/components/places/nsNavBookmarks.cpp
@@ -2245,275 +2245,16 @@ nsNavBookmarks::GetBookmarksForURI(nsIUR
}
return NS_OK;
}
NS_IMETHODIMP
-nsNavBookmarks::SetKeywordForBookmark(int64_t aBookmarkId,
- const nsAString& aUserCasedKeyword,
- uint16_t aSource)
-{
- NS_ENSURE_ARG_MIN(aBookmarkId, 1);
-
- // This also ensures the bookmark is valid.
- BookmarkData bookmark;
- nsresult rv = FetchItemInfo(aBookmarkId, bookmark);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIURI> uri;
- rv = NS_NewURI(getter_AddRefs(uri), bookmark.url);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Shortcuts are always lowercased internally.
- nsAutoString keyword(aUserCasedKeyword);
- ToLowerCase(keyword);
-
- // The same URI can be associated to more than one keyword, provided the post
- // data differs. Check if there are already keywords associated to this uri.
- nsTArray<nsString> oldKeywords;
- {
- nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
- "SELECT keyword FROM moz_keywords WHERE place_id = :place_id"
- );
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
- rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("place_id"), bookmark.placeId);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool hasMore;
- while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore) {
- nsString oldKeyword;
- rv = stmt->GetString(0, oldKeyword);
- NS_ENSURE_SUCCESS(rv, rv);
- oldKeywords.AppendElement(oldKeyword);
- }
- }
-
- // Trying to remove a non-existent keyword is a no-op.
- if (keyword.IsEmpty() && oldKeywords.Length() == 0) {
- return NS_OK;
- }
-
- int64_t syncChangeDelta = DetermineSyncChangeDelta(aSource);
-
- mozStorageTransaction transaction(mDB->MainConn(), false);
-
- // Remove the existing keywords.
- // Note this is wrong because in the insert-new-keyword case we should only
- // remove those having the same POST data, but this API doesn't allow that.
- // And in any case, this API is going away.
- for (uint32_t i = 0; i < oldKeywords.Length(); ++i) {
- nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
- "DELETE FROM moz_keywords WHERE keyword = :old_keyword"
- );
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
- rv = stmt->BindStringByName(NS_LITERAL_CSTRING("old_keyword"),
- oldKeywords[i]);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = stmt->Execute();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (keyword.IsEmpty()) {
- // We are removing the existing keywords.
- for (uint32_t i = 0; i < oldKeywords.Length(); ++i) {
- nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
- "DELETE FROM moz_keywords WHERE keyword = :old_keyword"
- );
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
- rv = stmt->BindStringByName(NS_LITERAL_CSTRING("old_keyword"),
- oldKeywords[i]);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = stmt->Execute();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsTArray<BookmarkData> bookmarks;
- rv = GetBookmarksForURI(uri, bookmarks);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (syncChangeDelta && !bookmarks.IsEmpty()) {
- // Build a query to update all bookmarks in a single statement.
- nsAutoCString changedIds;
- changedIds.AppendInt(bookmarks[0].id);
- for (uint32_t i = 1; i < bookmarks.Length(); ++i) {
- changedIds.Append(',');
- changedIds.AppendInt(bookmarks[i].id);
- }
- // Update the sync change counter for all bookmarks with the removed
- // keyword.
- nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
- NS_LITERAL_CSTRING(
- "UPDATE moz_bookmarks SET "
- "syncChangeCounter = syncChangeCounter + :delta "
- "WHERE id IN (") + changedIds + NS_LITERAL_CSTRING(")")
- );
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
-
- rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("delta"),
- syncChangeDelta);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = stmt->Execute();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = transaction.Commit();
- NS_ENSURE_SUCCESS(rv, rv);
-
- for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
- NOTIFY_OBSERVERS(mCanNotify, mObservers, nsINavBookmarkObserver,
- OnItemChanged(bookmarks[i].id,
- NS_LITERAL_CSTRING("keyword"),
- false,
- EmptyCString(),
- bookmarks[i].lastModified,
- TYPE_BOOKMARK,
- bookmarks[i].parentId,
- bookmarks[i].guid,
- bookmarks[i].parentGuid,
- // Abusing oldVal to pass out the url.
- bookmark.url,
- aSource));
- }
-
- return NS_OK;
- }
-
- // A keyword can only be associated to a single URI. Check if the requested
- // keyword was already associated, in such a case we will need to notify about
- // the change.
- nsAutoCString oldSpec;
- nsCOMPtr<nsIURI> oldUri;
- {
- nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
- "SELECT url "
- "FROM moz_keywords "
- "JOIN moz_places h ON h.id = place_id "
- "WHERE keyword = :keyword"
- );
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
- rv = stmt->BindStringByName(NS_LITERAL_CSTRING("keyword"), keyword);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool hasMore;
- if (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore) {
- rv = stmt->GetUTF8String(0, oldSpec);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = NS_NewURI(getter_AddRefs(oldUri), oldSpec);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // If another uri is using the new keyword, we must update the keyword entry.
- // Note we cannot use INSERT OR REPLACE cause it wouldn't invoke the delete
- // trigger.
- nsCOMPtr<mozIStorageStatement> stmt;
- if (oldUri) {
- // In both cases, notify about the change.
- nsTArray<BookmarkData> bookmarks;
- rv = GetBookmarksForURI(oldUri, bookmarks);
- NS_ENSURE_SUCCESS(rv, rv);
- for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
- NOTIFY_OBSERVERS(mCanNotify, mObservers, nsINavBookmarkObserver,
- OnItemChanged(bookmarks[i].id,
- NS_LITERAL_CSTRING("keyword"),
- false,
- EmptyCString(),
- bookmarks[i].lastModified,
- TYPE_BOOKMARK,
- bookmarks[i].parentId,
- bookmarks[i].guid,
- bookmarks[i].parentGuid,
- // Abusing oldVal to pass out the url.
- oldSpec,
- aSource));
- }
-
- stmt = mDB->GetStatement(
- "UPDATE moz_keywords SET place_id = :place_id WHERE keyword = :keyword"
- );
- NS_ENSURE_STATE(stmt);
- }
- else {
- stmt = mDB->GetStatement(
- "INSERT INTO moz_keywords (keyword, place_id, post_data) "
- "VALUES (:keyword, :place_id, '')"
- );
- }
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
-
- rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("place_id"), bookmark.placeId);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = stmt->BindStringByName(NS_LITERAL_CSTRING("keyword"), keyword);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = stmt->Execute();
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsTArray<BookmarkData> bookmarks;
- rv = GetBookmarksForURI(uri, bookmarks);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (syncChangeDelta && !bookmarks.IsEmpty()) {
- // Build a query to update all bookmarks in a single statement.
- nsAutoCString changedIds;
- changedIds.AppendInt(bookmarks[0].id);
- for (uint32_t i = 1; i < bookmarks.Length(); ++i) {
- changedIds.Append(',');
- changedIds.AppendInt(bookmarks[i].id);
- }
- // Update the sync change counter for all bookmarks with the new keyword.
- nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
- NS_LITERAL_CSTRING(
- "UPDATE moz_bookmarks SET "
- "syncChangeCounter = syncChangeCounter + :delta "
- "WHERE id IN (") + changedIds + NS_LITERAL_CSTRING(")")
- );
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
-
- rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("delta"), syncChangeDelta);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = stmt->Execute();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = transaction.Commit();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // In both cases, notify about the change.
- for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
- NOTIFY_OBSERVERS(mCanNotify, mObservers, nsINavBookmarkObserver,
- OnItemChanged(bookmarks[i].id,
- NS_LITERAL_CSTRING("keyword"),
- false,
- NS_ConvertUTF16toUTF8(keyword),
- bookmarks[i].lastModified,
- TYPE_BOOKMARK,
- bookmarks[i].parentId,
- bookmarks[i].guid,
- bookmarks[i].parentGuid,
- // Abusing oldVal to pass out the url.
- bookmark.url,
- aSource));
- }
-
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
nsNavBookmarks::GetKeywordForBookmark(int64_t aBookmarkId, nsAString& aKeyword)
{
NS_ENSURE_ARG_MIN(aBookmarkId, 1);
aKeyword.Truncate(0);
// We can have multiple keywords for the same uri, here we'll just return the
// last created one.
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(NS_LITERAL_CSTRING(
--- a/toolkit/components/places/tests/bookmarks/test_keywords.js
+++ b/toolkit/components/places/tests/bookmarks/test_keywords.js
@@ -74,20 +74,16 @@ function expectNotifications() {
return observer;
}
add_task(function test_invalid_input() {
Assert.throws(() => PlacesUtils.bookmarks.getKeywordForBookmark(null),
/NS_ERROR_ILLEGAL_VALUE/);
Assert.throws(() => PlacesUtils.bookmarks.getKeywordForBookmark(0),
/NS_ERROR_ILLEGAL_VALUE/);
- Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(null, "k"),
- /NS_ERROR_ILLEGAL_VALUE/);
- Assert.throws(() => PlacesUtils.bookmarks.setKeywordForBookmark(0, "k"),
- /NS_ERROR_ILLEGAL_VALUE/);
});
add_task(async function test_addBookmarkAndKeyword() {
let timerPrecision = Preferences.get("privacy.reduceTimerPrecision");
Preferences.set("privacy.reduceTimerPrecision", false);
registerCleanupFunction(function() {
Preferences.set("privacy.reduceTimerPrecision", timerPrecision);
@@ -549,18 +545,16 @@ add_task(async function test_invalidatio
info("Remove bookmark with keyword");
await PlacesUtils.bookmarks.remove(tb.guid);
ok(!(await PlacesUtils.keywords.fetch({ url: "http://getthunderbird.com" })),
"Should not return keywords for removed bookmark URL");
ok(!(await PlacesUtils.keywords.fetch({ keyword: "tb" })),
"Should not return URL for removed bookmark keyword");
-
- await PlacesTestUtils.promiseAsyncUpdates();
await check_orphans();
await PlacesUtils.bookmarks.eraseEverything();
});
add_task(async function test_eraseAllBookmarks() {
info("Insert bookmarks");
let fx = await PlacesUtils.bookmarks.insert({
--- a/toolkit/components/places/tests/bookmarks/test_sync_fields.js
+++ b/toolkit/components/places/tests/bookmarks/test_sync_fields.js
@@ -112,23 +112,26 @@ class TestCases {
info(`Set anno on ${guid}`);
await checkSyncFields(guid, { syncChangeCounter: 3 });
// Tagging a bookmark should update its change counter.
await this.tagURI(testUri, ["test-tag"]);
info(`Tagged bookmark ${guid}`);
await checkSyncFields(guid, { syncChangeCounter: 4 });
- await this.setKeyword(guid, "keyword");
- info(`Set keyword for bookmark ${guid}`);
- await checkSyncFields(guid, { syncChangeCounter: 5 });
-
- await this.removeKeyword(guid, "keyword");
- info(`Removed keyword from bookmark ${guid}`);
- await checkSyncFields(guid, { syncChangeCounter: 6 });
+ if ("setKeyword" in this) {
+ await this.setKeyword(guid, "keyword");
+ info(`Set keyword for bookmark ${guid}`);
+ await checkSyncFields(guid, { syncChangeCounter: 5 });
+ }
+ if ("removeKeyword" in this) {
+ await this.removeKeyword(guid, "keyword");
+ info(`Removed keyword from bookmark ${guid}`);
+ await checkSyncFields(guid, { syncChangeCounter: 6 });
+ }
}
async testSeparators() {
let insertSyncedBookmark = uri => {
return this.insertBookmark(PlacesUtils.bookmarks.unfiledGuid,
NetUtil.newURI(uri),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"A bookmark name");
@@ -279,29 +282,16 @@ class SyncTestCases extends TestCases {
PlacesUtils.bookmarks.removeItem(id);
}
async setTitle(guid, title) {
let id = await PlacesUtils.promiseItemId(guid);
PlacesUtils.bookmarks.setItemTitle(id, title);
}
- async setKeyword(guid, keyword) {
- let id = await PlacesUtils.promiseItemId(guid);
- PlacesUtils.bookmarks.setKeywordForBookmark(id, keyword);
- }
-
- async removeKeyword(guid, keyword) {
- let id = await PlacesUtils.promiseItemId(guid);
- if (PlacesUtils.bookmarks.getKeywordForBookmark(id) != keyword) {
- throw new Error(`Keyword ${keyword} not set for bookmark ${guid}`);
- }
- PlacesUtils.bookmarks.setKeywordForBookmark(id, "");
- }
-
async tagURI(uri, tags) {
PlacesUtils.tagging.tagURI(uri, tags);
}
async reorder(parentGuid, childGuids) {
let parentId = await PlacesUtils.promiseItemId(parentGuid);
for (let index = 0; index < childGuids.length; ++index) {
let id = await PlacesUtils.promiseItemId(childGuids[index]);