Bug 1125116 - Remove keywords support from Bookmarks.jsm. r=ttaubert

This commit is contained in:
Marco Bonardo 2015-02-09 17:10:19 +01:00
parent bfde97e97c
commit a80de46c11
7 changed files with 23 additions and 387 deletions

View File

@ -46,8 +46,6 @@
* contain an URL object.
* An URL cannot be longer than DB_URL_LENGTH_MAX, methods will throw if a
* longer value is provided.
* - keyword (string)
* The associated keyword, if any.
*
* Each successful operation notifies through the nsINavBookmarksObserver
* interface. To listen to such notifications you must register using
@ -147,9 +145,6 @@ let Bookmarks = Object.freeze({
, url: { requiredIf: b => b.type == this.TYPE_BOOKMARK
, validIf: b => b.type == this.TYPE_BOOKMARK }
, parentGuid: { required: true }
, keyword: { validIf: b => b.keyword &&
b.keyword.length > 0 &&
b.type == this.TYPE_BOOKMARK }
, title: { validIf: b => [ this.TYPE_BOOKMARK
, this.TYPE_FOLDER ].indexOf(b.type) != -1 }
, dateAdded: { defaultValue: time
@ -185,15 +180,6 @@ let Bookmarks = Object.freeze({
toPRTime(item.dateAdded), item.guid,
item.parentGuid ]);
// If a keyword is defined, notify onItemChanged for it.
if (item.keyword) {
notify(observers, "onItemChanged", [ itemId, "keyword", false,
item.keyword,
toPRTime(item.lastModified),
item.type, parent._id, item.guid,
item.parentGuid ]);
}
// If it's a tag, notify OnItemChanged to all bookmarks for this URL.
let isTagging = parent._parentId == PlacesUtils.tagsFolderId;
if (isTagging) {
@ -217,8 +203,6 @@ let Bookmarks = Object.freeze({
* won't be taken into account).
* Moreover, the item's type or dateAdded cannot be changed, since they are
* immutable after creation. Trying to change them will reject.
* Passing an empty string as keyword clears any keyword associated with
* this bookmark.
*
* Note that any known properties that don't apply to the specific item type
* cause an exception.
@ -268,7 +252,6 @@ let Bookmarks = Object.freeze({
let time = (updateInfo && updateInfo.dateAdded) || new Date();
updateInfo = validateBookmarkObject(updateInfo,
{ url: { validIf: () => item.type == this.TYPE_BOOKMARK }
, keyword: { validIf: () => item.type == this.TYPE_BOOKMARK }
, title: { validIf: () => [ this.TYPE_BOOKMARK
, this.TYPE_FOLDER ].indexOf(item.type) != -1 }
, lastModified: { defaultValue: new Date()
@ -361,18 +344,6 @@ let Bookmarks = Object.freeze({
updatedItem.guid,
updatedItem.parentGuid ]);
}
if (updateInfo.hasOwnProperty("keyword")) {
// If the keyword is unset, updatedItem won't have it set.
let keyword = updatedItem.hasOwnProperty("keyword") ?
updatedItem.keyword : "";
notify(observers, "onItemChanged", [ updatedItem._id, "keyword",
false, keyword,
toPRTime(updatedItem.lastModified),
updatedItem.type,
updatedItem._parentId,
updatedItem.guid,
updatedItem.parentGuid ]);
}
// If the item was moved, notify onItemMoved.
if (item.parentGuid != updatedItem.parentGuid ||
item.index != updatedItem.index) {
@ -474,7 +445,7 @@ let Bookmarks = Object.freeze({
*
* REMARK: any successful call to this method resolves to a single
* bookmark-item (or null), even when multiple bookmarks may exist
* (fetching by url or keyword,). If you wish to retrieve all of the
* (e.g. fetching by url). If you wish to retrieve all of the
* bookmarks for a given match, use the callback instead.
*
* Input can be either a guid or an object with one, and only one, of these
@ -487,10 +458,6 @@ let Bookmarks = Object.freeze({
* retrieves the most recent bookmark having the given URL.
* To retrieve ALL of the bookmarks for that URL, you must pass in an
* onResult callback, that will be invoked once for each found bookmark.
* - keyword
* retrieves an array of items having the given keyword.
* To retrieve ALL of the bookmarks for that keyword, you must pass in an
* onResult callback, that will be invoked once for each found bookmark.
*
* @param guidOrInfo
* The globally unique identifier of the item to fetch, or an
@ -521,8 +488,7 @@ let Bookmarks = Object.freeze({
let conditionsCount = [
v => v.hasOwnProperty("guid"),
v => v.hasOwnProperty("parentGuid") && v.hasOwnProperty("index"),
v => v.hasOwnProperty("url"),
v => v.hasOwnProperty("keyword")
v => v.hasOwnProperty("url")
].reduce((old, fn) => old + fn(info)|0, 0);
if (conditionsCount != 1)
throw new Error(`Unexpected number of conditions provided: ${conditionsCount}`);
@ -534,8 +500,6 @@ let Bookmarks = Object.freeze({
, index: { requiredIf: b => b.hasOwnProperty("parentGuid")
, validIf: b => typeof(b.index) == "number" &&
b.index >= 0 || b.index == this.DEFAULT_INDEX }
, keyword: { validIf: b => typeof(b.keyword) == "string" &&
b.keyword.length > 0 }
});
return Task.spawn(function* () {
@ -546,8 +510,6 @@ let Bookmarks = Object.freeze({
results = yield fetchBookmarkByPosition(fetchInfo);
else if (fetchInfo.hasOwnProperty("url"))
results = yield fetchBookmarksByURL(fetchInfo);
else if (fetchInfo.hasOwnProperty("keyword"))
results = yield fetchBookmarksByKeyword(fetchInfo);
if (!results)
return null;
@ -739,17 +701,6 @@ function* updateBookmark(info, item, newParent) {
tuples.set("title", { value: info.title });
yield db.executeTransaction(function* () {
if (info.hasOwnProperty("keyword")) {
if (info.keyword.length > 0) {
yield maybeCreateKeyword(db, info.keyword);
tuples.set("keyword",
{ value: info.keyword
, fragment: "keyword_id = (SELECT id FROM moz_keywords WHERE keyword = :keyword)" });
} else {
tuples.set("keyword_id", { value: null });
}
}
if (info.hasOwnProperty("url")) {
// Ensure a page exists in moz_places for this URL.
yield db.executeCached(
@ -804,10 +755,6 @@ function* updateBookmark(info, item, newParent) {
WHERE guid = :guid
`, Object.assign({ guid: info.guid },
[...tuples.entries()].reduce((p, c) => { p[c[0]] = c[1].value; return p; }, {})));
if (info.hasOwnProperty("keyword") && info.keyword === "")
yield removeOrphanKeywords(db);
});
// If the parent changed, update related non-enumerable properties.
@ -821,11 +768,9 @@ function* updateBookmark(info, item, newParent) {
let updatedItem = mergeIntoNewObject(item, info, additionalParentInfo);
// Don't return an empty title or keyword to the caller.
// Don't return an empty title to the caller.
if (updatedItem.hasOwnProperty("title") && updatedItem.title === null)
delete updatedItem.title;
if (updatedItem.hasOwnProperty("keyword") && updatedItem.keyword === "")
delete updatedItem.keyword;
return updatedItem;
}
@ -858,22 +803,16 @@ function* insertBookmark(item, parent) {
AND position >= :index
`, { parent: parent._id, index: item.index });
// If a keyword was provided, add it.
if (item.hasOwnProperty("keyword"))
yield maybeCreateKeyword(db, item.keyword);
// Insert the bookmark into the database.
yield db.executeCached(
`INSERT INTO moz_bookmarks (fk, type, parent, position, title,
dateAdded, lastModified, guid, keyword_id)
dateAdded, lastModified, guid)
VALUES ((SELECT id FROM moz_places WHERE url = :url), :type, :parent,
:index, :title, :date_added, :last_modified, :guid,
(SELECT id FROM moz_keywords WHERE keyword = :keyword))
:index, :title, :date_added, :last_modified, :guid)
`, { url: item.hasOwnProperty("url") ? item.url.href : "nonexistent",
type: item.type, parent: parent._id, index: item.index,
title: item.title, date_added: toPRTime(item.dateAdded),
last_modified: toPRTime(item.lastModified), guid: item.guid,
keyword: item.keyword || "" });
last_modified: toPRTime(item.lastModified), guid: item.guid });
yield setAncestorsLastModified(db, item.parentGuid, item.dateAdded);
});
@ -900,12 +839,11 @@ function* fetchBookmark(info) {
let rows = yield db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
keyword, b.id AS _id, b.parent AS _parentId,
b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId
FROM moz_bookmarks b
LEFT JOIN moz_bookmarks p ON p.id = b.parent
LEFT JOIN moz_keywords k ON k.id = b.keyword_id
LEFT JOIN moz_places h ON h.id = b.fk
WHERE b.guid = :guid
`, { guid: info.guid });
@ -920,12 +858,11 @@ function* fetchBookmarkByPosition(info) {
let rows = yield db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
keyword, b.id AS _id, b.parent AS _parentId,
b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId
FROM moz_bookmarks b
LEFT JOIN moz_bookmarks p ON p.id = b.parent
LEFT JOIN moz_keywords k ON k.id = b.keyword_id
LEFT JOIN moz_places h ON h.id = b.fk
WHERE p.guid = :parentGuid
AND b.position = IFNULL(:index, (SELECT count(*) - 1
@ -942,12 +879,11 @@ function* fetchBookmarksByURL(info) {
let rows = yield db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
keyword, b.id AS _id, b.parent AS _parentId,
b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId
FROM moz_bookmarks b
LEFT JOIN moz_bookmarks p ON p.id = b.parent
LEFT JOIN moz_keywords k ON k.id = b.keyword_id
LEFT JOIN moz_places h ON h.id = b.fk
WHERE h.url = :url
AND _grandParentId <> :tags_folder
@ -958,38 +894,17 @@ function* fetchBookmarksByURL(info) {
return rows.length ? rowsToItemsArray(rows) : null;
}
function* fetchBookmarksByKeyword(info) {
let db = yield DBConnPromised;
let rows = yield db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
keyword, b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId
FROM moz_bookmarks b
LEFT JOIN moz_bookmarks p ON p.id = b.parent
LEFT JOIN moz_keywords k ON k.id = b.keyword_id
LEFT JOIN moz_places h ON h.id = b.fk
WHERE keyword = :keyword
ORDER BY b.lastModified DESC
`, { keyword: info.keyword });
return rows.length ? rowsToItemsArray(rows) : null;
}
function* fetchBookmarksByParent(info) {
let db = yield DBConnPromised;
let rows = yield db.executeCached(
`SELECT b.guid, IFNULL(p.guid, "") AS parentGuid, b.position AS 'index',
b.dateAdded, b.lastModified, b.type, b.title, h.url AS url,
keyword, b.id AS _id, b.parent AS _parentId,
b.id AS _id, b.parent AS _parentId,
(SELECT count(*) FROM moz_bookmarks WHERE parent = b.id) AS _childCount,
p.parent AS _grandParentId
FROM moz_bookmarks b
LEFT JOIN moz_bookmarks p ON p.id = b.parent
LEFT JOIN moz_keywords k ON k.id = b.keyword_id
LEFT JOIN moz_places h ON h.id = b.fk
WHERE p.guid = :parentGuid
ORDER BY b.position ASC
@ -1030,10 +945,6 @@ function* removeBookmark(item) {
`, { parentId: item._parentId, index: item.index });
yield setAncestorsLastModified(db, item.parentGuid, new Date());
// If the bookmark had a keyword, it might now be an orphan.
if (item.keyword)
removeOrphanKeywords(db);
});
// If not a tag recalculate frecency...
@ -1157,10 +1068,6 @@ function removeSameValueProperties(dest, src) {
case "url":
remove = src.hasOwnProperty(prop) && dest[prop].href == src[prop].href;
break;
case "keyword":
remove = (dest.keyword == "" && !src.hasOwnProperty("keyword")) ||
dest[prop] == src[prop];
break;
default:
remove = dest[prop] == src[prop];
}
@ -1212,7 +1119,7 @@ function rowsToItemsArray(rows) {
for (let prop of ["dateAdded", "lastModified"]) {
item[prop] = toDate(row.getResultByName(prop));
}
for (let prop of ["title", "keyword", "parentGuid", "url" ]) {
for (let prop of ["title", "parentGuid", "url" ]) {
let val = row.getResultByName(prop);
if (val)
item[prop] = prop === "url" ? new URL(val) : val;
@ -1283,12 +1190,6 @@ const VALIDATORS = Object.freeze({
if (v instanceof Ci.nsIURI)
return new URL(v.spec);
return v;
},
keyword: v => {
simpleValidateFunc(val => typeof(val) == "string" && /^\S*$/.test(val))
.call(this, v);
// Keywords are handled as case-insensitive.
return v.toLowerCase();
}
});
@ -1372,34 +1273,6 @@ let updateFrecency = Task.async(function* (db, urls) {
`);
});
/**
* Creates a keyword entry, if it's missing.
*
* @param db
* the Sqlite.jsm connection handle.
* @param keyword
* the keyword string to create.
*/
let maybeCreateKeyword = Task.async(function* (db, keyword) {
yield db.executeCached(
`INSERT OR IGNORE INTO moz_keywords (keyword)
VALUES (:keyword)
`, { keyword: keyword });
});
/**
* Removes any orphan keyword entries.
*
* @param db
* the Sqlite.jsm connection handle.
*/
let removeOrphanKeywords = Task.async(function* (db) {
yield db.executeCached(
`DELETE FROM moz_keywords
WHERE NOT EXISTS(SELECT 1 FROM moz_bookmarks
WHERE keyword_id = moz_keywords.id)`);
});
/**
* Removes any orphan annotation entries.
*
@ -1496,7 +1369,7 @@ Task.async(function* (db, folderGuids) {
SELECT b.id AS _id, b.parent AS _parentId, b.position AS 'index',
b.type, url, b.guid, p.guid AS parentGuid, b.dateAdded,
b.lastModified, b.title, p.parent AS _grandParentId,
NULL AS _childCount, NULL AS keyword
NULL AS _childCount
FROM moz_bookmarks b
JOIN moz_bookmarks p ON p.id = b.parent
LEFT JOIN moz_places h ON b.fk = h.id
@ -1519,7 +1392,6 @@ Task.async(function* (db, folderGuids) {
// Cleanup orphans.
yield removeOrphanAnnotations(db);
yield removeOrphanKeywords(db);
// TODO (Bug 1087576): this may leave orphan tags behind.

View File

@ -13,8 +13,7 @@ add_task(function* test_eraseEverything() {
checkBookmarkObject(unfiledFolder);
let unfiledBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://example.com/",
keyword: "kw1" });
url: "http://example.com/" });
checkBookmarkObject(unfiledBookmark);
let unfiledBookmarkInFolder =
yield PlacesUtils.bookmarks.insert({ parentGuid: unfiledFolder.guid,
@ -29,8 +28,7 @@ add_task(function* test_eraseEverything() {
checkBookmarkObject(menuFolder);
let menuBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://example.com/",
keyword: "kw2" });
url: "http://example.com/" });
checkBookmarkObject(unfiledBookmark);
let menuBookmarkInFolder =
yield PlacesUtils.bookmarks.insert({ parentGuid: menuFolder.guid,
@ -45,8 +43,7 @@ add_task(function* test_eraseEverything() {
checkBookmarkObject(toolbarFolder);
let toolbarBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://example.com/",
keyword: "kw3" });
url: "http://example.com/" });
checkBookmarkObject(toolbarBookmark);
let toolbarBookmarkInFolder =
yield PlacesUtils.bookmarks.insert({ parentGuid: toolbarFolder.guid,
@ -65,11 +62,9 @@ add_task(function* test_eraseEverything() {
Assert.equal(frecencyForUrl("http://example.com/"), frecencyForExample);
Assert.equal(frecencyForUrl("http://example.com/"), frecencyForMozilla);
// Check there are no orphan keywords or annotations.
// Check there are no orphan annotations.
let conn = yield PlacesUtils.promiseDBConnection();
let rows = yield conn.execute(`SELECT * FROM moz_keywords`);
Assert.equal(rows.length, 0);
rows = yield conn.execute(`SELECT * FROM moz_items_annos`);
let rows = yield conn.execute(`SELECT * FROM moz_items_annos`);
Assert.equal(rows.length, 0);
rows = yield conn.execute(`SELECT * FROM moz_anno_attributes`);
Assert.equal(rows.length, 0);

View File

@ -31,10 +31,6 @@ add_task(function* invalid_input_throws() {
url: "http://example.com"}),
/Unexpected number of conditions provided: 2/);
Assert.throws(() => PlacesUtils.bookmarks.fetch({ keyword: "test",
url: "http://example.com"}),
/Unexpected number of conditions provided: 2/);
Assert.throws(() => PlacesUtils.bookmarks.fetch("test"),
/Invalid value for property 'guid'/);
Assert.throws(() => PlacesUtils.bookmarks.fetch(123),
@ -74,15 +70,6 @@ add_task(function* invalid_input_throws() {
Assert.throws(() => PlacesUtils.bookmarks.fetch({ url: -10 }),
/Invalid value for property 'url'/);
Assert.throws(() => PlacesUtils.bookmarks.fetch({ keyword: "te st" }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.fetch({ keyword: null }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.fetch({ keyword: "" }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.fetch({ keyword: 5 }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.fetch("123456789012", "test"),
/onResult callback must be a valid function/);
Assert.throws(() => PlacesUtils.bookmarks.fetch("123456789012", {}),
@ -117,7 +104,6 @@ add_task(function* fetch_bookmark() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm2.url.href, "http://example.com/");
Assert.equal(bm2.title, "a bookmark");
Assert.ok(!("keyword" in bm2));
yield PlacesUtils.bookmarks.remove(bm1.guid);
});
@ -135,7 +121,6 @@ add_task(function* fetch_bookmar_empty_title() {
Assert.deepEqual(bm1, bm2);
Assert.equal(bm2.index, 0);
Assert.ok(!("title" in bm2));
Assert.ok(!("keyword" in bm2));
yield PlacesUtils.bookmarks.remove(bm1.guid);
});
@ -156,7 +141,6 @@ add_task(function* fetch_folder() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_FOLDER);
Assert.equal(bm2.title, "a folder");
Assert.ok(!("url" in bm2));
Assert.ok(!("keyword" in bm2));
yield PlacesUtils.bookmarks.remove(bm1.guid);
});
@ -192,7 +176,6 @@ add_task(function* fetch_separator() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
Assert.ok(!("url" in bm2));
Assert.ok(!("title" in bm2));
Assert.ok(!("keyword" in bm2));
yield PlacesUtils.bookmarks.remove(bm1.guid);
});
@ -235,7 +218,6 @@ add_task(function* fetch_byposition() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm2.url.href, "http://example.com/");
Assert.equal(bm2.title, "a bookmark");
Assert.ok(!("keyword" in bm2));
});
add_task(function* fetch_byposition_default_index() {
@ -260,7 +242,6 @@ add_task(function* fetch_byposition_default_index() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm2.url.href, "http://example.com/last");
Assert.equal(bm2.title, "last child");
Assert.ok(!("keyword" in bm2));
yield PlacesUtils.bookmarks.remove(bm1.guid);
});
@ -295,7 +276,6 @@ add_task(function* fetch_byurl() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm2.url.href, "http://byurl.com/");
Assert.equal(bm2.title, "a bookmark");
Assert.ok(!("keyword" in bm2));
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
@ -325,70 +305,6 @@ add_task(function* fetch_byurl() {
PlacesUtils.tagging.untagURI(uri(bm1.url.href), ["Test Tag"]);
});
add_task(function* fetch_bykeyword_nonexisting() {
let bm = yield PlacesUtils.bookmarks.fetch({ keyword: "nonexisting" },
gAccumulator.callback);
Assert.equal(bm, null);
Assert.equal(gAccumulator.results.length, 0);
});
add_task(function* fetch_bykeyword() {
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://bykeyword1.com/",
keyword: "bykeyword" });
checkBookmarkObject(bm1);
let bm2 = yield PlacesUtils.bookmarks.fetch({ keyword: "bykeyword" },
gAccumulator.callback);
checkBookmarkObject(bm2);
Assert.equal(gAccumulator.results.length, 1);
checkBookmarkObject(gAccumulator.results[0]);
Assert.deepEqual(gAccumulator.results[0], bm1);
Assert.deepEqual(bm1, bm2);
Assert.equal(bm2.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.deepEqual(bm2.dateAdded, bm2.lastModified);
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm2.url.href, "http://bykeyword1.com/");
Assert.equal(bm2.keyword, "bykeyword");
// Add a second url using the same keyword.
let bm3 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://bykeyword2.com/",
keyword: "bykeyword" });
let bm4 = yield PlacesUtils.bookmarks.fetch({ keyword: "bykeyword" },
gAccumulator.callback);
checkBookmarkObject(bm4);
Assert.deepEqual(bm3, bm4);
Assert.equal(gAccumulator.results.length, 2);
gAccumulator.results.forEach(checkBookmarkObject);
Assert.deepEqual(gAccumulator.results[0], bm4);
// After an update the returned bookmark should change.
yield PlacesUtils.bookmarks.update({ guid: bm1.guid, title: "new title" });
let bm5 = yield PlacesUtils.bookmarks.fetch({ keyword: "bykeyword" },
gAccumulator.callback);
checkBookmarkObject(bm5);
// Cannot use deepEqual cause lastModified changed.
Assert.equal(bm1.guid, bm5.guid);
Assert.ok(bm5.lastModified > bm1.lastModified);
Assert.equal(gAccumulator.results.length, 2);
gAccumulator.results.forEach(checkBookmarkObject);
Assert.deepEqual(gAccumulator.results[0], bm5);
// Check fetching by keyword is case-insensitive.
let bm6 = yield PlacesUtils.bookmarks.fetch({ keyword: "ByKeYwOrD" },
gAccumulator.callback);
checkBookmarkObject(bm6);
// Cannot use deepEqual cause lastModified changed.
Assert.equal(bm1.guid, bm6.guid);
Assert.equal(gAccumulator.results.length, 2);
gAccumulator.results.forEach(checkBookmarkObject);
Assert.deepEqual(gAccumulator.results[0], bm6);
});
function run_test() {
run_next_test();
}

View File

@ -80,16 +80,6 @@ add_task(function* invalid_input_throws() {
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "te st" }),
/Invalid value for property 'url'/);
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
keyword: 10 }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
keyword: null }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
keyword: "" }),
/Invalid value for property 'keyword'/);
});
add_task(function* invalid_properties_for_bookmark_type() {
@ -102,12 +92,6 @@ add_task(function* invalid_properties_for_bookmark_type() {
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
title: "test" }),
/Invalid value for property 'title'/);
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
keyword: "test" }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
keyword: "test" }),
/Invalid value for property 'keyword'/);
});
add_task(function* long_title_trim() {
@ -125,7 +109,6 @@ add_task(function* long_title_trim() {
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_FOLDER);
Assert.equal(bm.title.length, 4096, "title should have been trimmed");
Assert.ok(!("url" in bm), "url should not be set");
Assert.ok(!("keyword" in bm), "keyword should not be set");
});
add_task(function* create_separator() {
@ -243,28 +226,12 @@ add_task(function* create_bookmark() {
let parent = yield PlacesUtils.bookmarks.fetch({ guid: bm.parentGuid });
Assert.deepEqual(parent.lastModified, bm.dateAdded);
// While here, also check keywords are case-insensitive.
bm = yield PlacesUtils.bookmarks.insert({ parentGuid: parentGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: NetUtil.newURI("http://example.com/"),
keyword: "tEsT" });
checkBookmarkObject(bm);
Assert.equal(bm.parentGuid, parentGuid);
Assert.equal(bm.index, 1);
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm.url.href, "http://example.com/");
Assert.equal(bm.keyword, "test");
// Check parent lastModified.
parent = yield PlacesUtils.bookmarks.fetch({ guid: bm.parentGuid });
Assert.deepEqual(parent.lastModified, bm.dateAdded);
bm = yield PlacesUtils.bookmarks.insert({ parentGuid: parentGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: new URL("http://example.com/") });
checkBookmarkObject(bm);
Assert.equal(bm.parentGuid, parentGuid);
Assert.equal(bm.index, 2);
Assert.equal(bm.index, 1);
Assert.equal(bm.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm.url.href, "http://example.com/");
Assert.ok(!("title" in bm), "title should not be set");

View File

@ -70,27 +70,6 @@ add_task(function* insert_bookmark_notitle_notification() {
]);
});
add_task(function* insert_bookmark_keyword_notification() {
let observer = expectNotifications();
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: new URL("http://example.com/"),
keyword: "Kw" });
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
// Keywords are case-insensitive.
Assert.equal(bm.keyword, "kw");
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
bm.url, null, bm.dateAdded,
bm.guid, bm.parentGuid ] },
{ name: "onItemChanged",
arguments: [ itemId, "keyword", false, bm.keyword,
bm.lastModified, bm.type, parentId,
bm.guid, bm.parentGuid ] }
]);
});
add_task(function* insert_bookmark_tag_notification() {
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
@ -170,32 +149,6 @@ add_task(function* update_bookmark_uri() {
]);
});
add_task(function* update_bookmark_keyword() {
let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: new URL("http://keyword.example.com/") });
let observer = expectNotifications();
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid, keyword: "kW" });
// Keywords are case-insensitive.
Assert.equal(bm.keyword, "kw");
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
let parentId = yield PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemChanged",
arguments: [ itemId, "keyword", false, bm.keyword,
bm.lastModified, bm.type, parentId, bm.guid,
bm.parentGuid ] }
]);
observer = expectNotifications();
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid, keyword: "" });
observer.check([ { name: "onItemChanged",
arguments: [ itemId, "keyword", false, "",
bm.lastModified, bm.type, parentId, bm.guid,
bm.parentGuid ] }
]);
});
add_task(function* update_move_same_folder() {
// Ensure there are at least two items in place (others test do so for us,
// but we don't have to depend on that).

View File

@ -81,7 +81,6 @@ add_task(function* remove_bookmark() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_BOOKMARK);
Assert.equal(bm2.url.href, "http://example.com/");
Assert.equal(bm2.title, "a bookmark");
Assert.ok(!("keyword" in bm2));
});
@ -89,27 +88,20 @@ add_task(function* remove_bookmark_orphans() {
let bm1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://example.com/",
title: "a bookmark",
keyword: "tEsT"});
title: "a bookmark" });
checkBookmarkObject(bm1);
PlacesUtils.annotations.setItemAnnotation((yield PlacesUtils.promiseItemId(bm1.guid)),
"testanno", "testvalue", 0, 0);
let bm2 = yield PlacesUtils.bookmarks.remove(bm1.guid);
checkBookmarkObject(bm2);
// Keywords are case-insensitive.
Assert.equal(bm2.keyword, "test");
// Check there are no orphan keywords or annotations.
// Check there are no orphan annotations.
let conn = yield PlacesUtils.promiseDBConnection();
let rows = yield conn.execute(`SELECT * FROM moz_keywords`);
let rows = yield conn.execute(`SELECT * FROM moz_items_annos`);
Assert.equal(rows.length, 0);
rows = yield conn.execute(`SELECT * FROM moz_items_annos`);
rows = yield conn.execute(`SELECT * FROM moz_anno_attributes`);
Assert.equal(rows.length, 0);
// removeItemAnnotations doesn't remove orphan annotations, cause it likely
// relies on expiration to do so.
//rows = yield conn.execute(`SELECT * FROM moz_anno_attributes`);
//Assert.equal(rows.length, 0);
});
add_task(function* remove_bookmark_empty_title() {
@ -125,7 +117,6 @@ add_task(function* remove_bookmark_empty_title() {
Assert.deepEqual(bm1, bm2);
Assert.equal(bm2.index, 0);
Assert.ok(!("title" in bm2));
Assert.ok(!("keyword" in bm2));
});
add_task(function* remove_folder() {
@ -144,7 +135,6 @@ add_task(function* remove_folder() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_FOLDER);
Assert.equal(bm2.title, "a folder");
Assert.ok(!("url" in bm2));
Assert.ok(!("keyword" in bm2));
});
add_task(function* test_nested_contents_removed() {
@ -190,7 +180,6 @@ add_task(function* remove_separator() {
Assert.equal(bm2.type, PlacesUtils.bookmarks.TYPE_SEPARATOR);
Assert.ok(!("url" in bm2));
Assert.ok(!("title" in bm2));
Assert.ok(!("keyword" in bm2));
});
function run_test() {

View File

@ -70,11 +70,6 @@ add_task(function* invalid_input_throws() {
Assert.throws(() => PlacesUtils.bookmarks.insert({ title: undefined }),
/Invalid value for property 'title'/);
Assert.throws(() => PlacesUtils.bookmarks.update({ keyword: 10 }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.update({ keyword: null }),
/Invalid value for property 'keyword'/);
Assert.throws(() => PlacesUtils.bookmarks.update({ guid: "123456789012" }),
/Not enough properties to update/);
@ -152,13 +147,6 @@ add_task(function* invalid_properties_for_existing_bookmark() {
} catch (ex) {
Assert.ok(/Invalid value for property 'url'/.test(ex));
}
try {
yield PlacesUtils.bookmarks.update({ guid: folder.guid,
keyword: "test" });
Assert.ok(false, "Should have thrown");
} catch (ex) {
Assert.ok(/Invalid value for property 'keyword'/.test(ex));
}
let separator = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
@ -169,13 +157,6 @@ add_task(function* invalid_properties_for_existing_bookmark() {
} catch (ex) {
Assert.ok(/Invalid value for property 'url'/.test(ex));
}
try {
yield PlacesUtils.bookmarks.update({ guid: separator.guid,
keyword: "test" });
Assert.ok(false, "Should have thrown");
} catch (ex) {
Assert.ok(/Invalid value for property 'keyword'/.test(ex));
}
try {
yield PlacesUtils.bookmarks.update({ guid: separator.guid,
title: "test" });
@ -238,48 +219,11 @@ add_task(function* update_lastModified() {
Assert.ok(!("title" in bm));
});
add_task(function* update_keyword() {
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://example.com/",
title: "title",
keyword: "kw" });
checkBookmarkObject(bm);
let lastModified = bm.lastModified;
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
keyword: "KW2" });
checkBookmarkObject(bm);
Assert.ok(bm.lastModified >= lastModified);
// Keywords are case-insensitive.
Assert.equal(bm.keyword, "kw2");
bm = yield PlacesUtils.bookmarks.fetch(bm.guid);
// Keywords are case-insensitive.
Assert.equal(bm.keyword, "kw2");
lastModified = bm.lastModified;
bm = yield PlacesUtils.bookmarks.update({ guid: bm.guid,
keyword: "" });
Assert.ok(!("keyword" in bm));
bm = yield PlacesUtils.bookmarks.fetch(bm.guid);
Assert.ok(!("keyword" in bm));
Assert.ok(bm.lastModified >= lastModified);
// Check orphan keyword has been removed from the database.
let conn = yield PlacesUtils.promiseDBConnection();
let rows = yield conn.executeCached(
`SELECT id from moz_keywords WHERE keyword >= :keyword`, { keyword: "kw" });
Assert.equal(rows.length, 0);
});
add_task(function* update_url() {
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
url: "http://example.com/",
title: "title",
keyword: "kw" });
title: "title" });
checkBookmarkObject(bm);
let lastModified = bm.lastModified;
let frecency = frecencyForUrl(bm.url);