Bug 1426245 - Test changes r=mak

MozReview-Commit-ID: 4fhhzspxLJZ

Depends on D4606

Differential Revision: https://phabricator.services.mozilla.com/D5162

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Doug Thayer 2018-10-09 14:47:31 +00:00
parent 218843ef6a
commit 0fd7f560d6
39 changed files with 651 additions and 437 deletions

View File

@ -1462,7 +1462,7 @@ var BookmarkingUI = {
return;
}
// It's possible that onItemAdded gets called before the async statement
// It's possible that "bookmark-added" gets called before the async statement
// calls back. For such an edge case, retain all unique entries from the
// array.
if (this._itemGuids.size > 0) {

View File

@ -78,8 +78,9 @@ async function checkBookmark(url, expected_title) {
Assert.equal(gBrowser.selectedBrowser.currentURI.spec, url,
"Trying to bookmark the expected uri");
let promiseBookmark = PlacesTestUtils.waitForNotification("onItemAdded",
(id, parentId, index, type, itemUrl) => itemUrl.equals(gBrowser.selectedBrowser.currentURI));
let promiseBookmark = PlacesTestUtils.waitForNotification("bookmark-added",
(events) => events.some(({url: eventUrl}) => eventUrl == gBrowser.selectedBrowser.currentURI.spec),
"places");
PlacesCommandHook.bookmarkPage();
await promiseBookmark;

View File

@ -465,28 +465,18 @@ function promiseNotificationShown(notification) {
*/
function promiseOnBookmarkItemAdded(aExpectedURI) {
return new Promise((resolve, reject) => {
let bookmarksObserver = {
onItemAdded(aItemId, aFolderId, aIndex, aItemType, aURI) {
info("Added a bookmark to " + aURI.spec);
PlacesUtils.bookmarks.removeObserver(bookmarksObserver);
if (aURI.equals(aExpectedURI)) {
resolve();
} else {
reject(new Error("Added an unexpected bookmark"));
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
QueryInterface: ChromeUtils.generateQI([
Ci.nsINavBookmarkObserver,
]),
let listener = events => {
is(events.length, 1, "Should only receive one event.");
info("Added a bookmark to " + events[0].url);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
if (events[0].url == aExpectedURI.spec) {
resolve();
} else {
reject(new Error("Added an unexpected bookmark"));
}
};
info("Waiting for a bookmark to be added");
PlacesUtils.bookmarks.addObserver(bookmarksObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
});
}

View File

@ -69,19 +69,21 @@ function findBookmarkInPolicy(bookmark) {
async function promiseAllChangesMade({itemsToAdd, itemsToRemove}) {
return new Promise(resolve => {
let listener = events => {
is(events.length, 1, "Should only have 1 event.");
itemsToAdd--;
if (itemsToAdd == 0 && itemsToRemove == 0) {
PlacesUtils.bookmarks.removeObserver(bmObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
resolve();
}
};
let bmObserver = {
onItemAdded() {
itemsToAdd--;
if (itemsToAdd == 0 && itemsToRemove == 0) {
PlacesUtils.bookmarks.removeObserver(bmObserver);
resolve();
}
},
onItemRemoved() {
itemsToRemove--;
if (itemsToAdd == 0 && itemsToRemove == 0) {
PlacesUtils.bookmarks.removeObserver(bmObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
resolve();
}
},
@ -93,6 +95,7 @@ async function promiseAllChangesMade({itemsToAdd, itemsToRemove}) {
onItemMoved() {},
};
PlacesUtils.bookmarks.addObserver(bmObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
});
}

View File

@ -21,33 +21,27 @@ add_task(async function() {
let itemCount = 0;
let gotFolder = false;
let bmObserver = {
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) {
if (aTitle != label) {
let listener = events => {
for (let event of events) {
if (event.title != label) {
itemCount++;
}
if (aItemType == PlacesUtils.bookmarks.TYPE_FOLDER && aTitle == "360 \u76f8\u5173") {
if (event.itemType == PlacesUtils.bookmarks.TYPE_FOLDER && event.title == "360 \u76f8\u5173") {
gotFolder = true;
}
if (expectedParents.length > 0 && aTitle == label) {
let index = expectedParents.indexOf(aParentId);
if (expectedParents.length > 0 && event.title == label) {
let index = expectedParents.indexOf(event.parentId);
Assert.ok(index != -1, "Found expected parent");
expectedParents.splice(index, 1);
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
}
};
PlacesUtils.bookmarks.addObserver(bmObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
await promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS, {
id: "default",
});
PlacesUtils.bookmarks.removeObserver(bmObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
// Check the bookmarks have been imported to all the expected parents.
Assert.ok(!expectedParents.length, "No more expected parents");

View File

@ -77,27 +77,21 @@ add_task(async function() {
Assert.ok(await migrator.isSourceAvailable());
let itemsSeen = {bookmarks: 0, folders: 0};
let bmObserver = {
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) {
if (!aTitle.includes("Chrome")) {
itemsSeen[aItemType == PlacesUtils.bookmarks.TYPE_FOLDER ? "folders" : "bookmarks"]++;
let listener = events => {
for (let event of events) {
if (!event.title.includes("Chrome")) {
itemsSeen[event.itemType == PlacesUtils.bookmarks.TYPE_FOLDER ? "folders" : "bookmarks"]++;
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
}
};
PlacesUtils.bookmarks.addObserver(bmObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
const PROFILE = {
id: "Default",
name: "Default",
};
await promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS, PROFILE);
PlacesUtils.bookmarks.removeObserver(bmObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
Assert.equal(itemsSeen.bookmarks, 200, "Should have seen 200 bookmarks.");
Assert.equal(itemsSeen.folders, 10, "Should have seen 10 folders.");

View File

@ -423,28 +423,33 @@ add_task(async function() {
let sourceLabel = MigrationUtils.getLocalizedString("importedBookmarksFolder", [source]);
let seenBookmarks = [];
let bookmarkObserver = {
onItemAdded(itemId, parentId, index, itemType, url, title, dateAdded, itemGuid, parentGuid) {
let listener = events => {
for (let event of events) {
let {
id,
itemType,
url,
title,
dateAdded,
guid,
index,
parentGuid,
parentId,
} = event;
if (title.startsWith("Deleted")) {
ok(false, "Should not see deleted items being bookmarked!");
}
seenBookmarks.push({itemId, parentId, index, itemType, url, title, dateAdded, itemGuid, parentGuid});
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
seenBookmarks.push({id, parentId, index, itemType, url, title, dateAdded, guid, parentGuid});
}
};
PlacesUtils.bookmarks.addObserver(bookmarkObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let migrateResult = await new Promise(resolve => bookmarksMigrator.migrate(resolve)).catch(ex => {
Cu.reportError(ex);
Assert.ok(false, "Got an exception trying to migrate data! " + ex);
return false;
});
PlacesUtils.bookmarks.removeObserver(bookmarkObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
Assert.ok(migrateResult, "Migration should succeed");
Assert.equal(seenBookmarks.length, 7, "Should have seen 7 items being bookmarked.");
Assert.equal(seenBookmarks.filter(bm => bm.title != sourceLabel).length,
@ -455,8 +460,8 @@ add_task(async function() {
Assert.equal(menuParents.length, 1, "Should have a single folder added to the menu");
let toolbarParents = seenBookmarks.filter(item => item.parentGuid == PlacesUtils.bookmarks.toolbarGuid);
Assert.equal(toolbarParents.length, 1, "Should have a single item added to the toolbar");
let menuParentGuid = menuParents[0].itemGuid;
let toolbarParentGuid = toolbarParents[0].itemGuid;
let menuParentGuid = menuParents[0].guid;
let toolbarParentGuid = toolbarParents[0].guid;
let expectedTitlesInMenu = bookmarkReferenceItems.filter(item => item.ParentId == kEdgeMenuParent).map(item => item.Title);
// Hacky, but seems like much the simplest way:
@ -481,39 +486,44 @@ add_task(async function() {
Assert.equal(bookmark.parentGuid, menuParentGuid, "Item '" + bookmark.title + "' should be in menu");
} else if (shouldBeInToolbar) {
Assert.equal(bookmark.parentGuid, toolbarParentGuid, "Item '" + bookmark.title + "' should be in toolbar");
} else if (bookmark.itemGuid == menuParentGuid || bookmark.itemGuid == toolbarParentGuid) {
} else if (bookmark.guid == menuParentGuid || bookmark.guid == toolbarParentGuid) {
Assert.ok(true, "Expect toolbar and menu folders to not be in menu or toolbar");
} else {
// Bit hacky, but we do need to check this.
Assert.equal(bookmark.title, "Item in folder", "Subfoldered item shouldn't be in menu or toolbar");
let parent = seenBookmarks.find(maybeParent => maybeParent.itemGuid == bookmark.parentGuid);
let parent = seenBookmarks.find(maybeParent => maybeParent.guid == bookmark.parentGuid);
Assert.equal(parent && parent.title, "Folder", "Subfoldered item should be in subfolder labeled 'Folder'");
}
let dbItem = bookmarkReferenceItems.find(someItem => bookmark.title == someItem.Title);
if (!dbItem) {
Assert.equal(bookmark.title, importParentFolderName, "Only the extra layer of folders isn't in the input we stuck in the DB.");
Assert.ok([menuParentGuid, toolbarParentGuid].includes(bookmark.itemGuid), "This item should be one of the containers");
Assert.ok([menuParentGuid, toolbarParentGuid].includes(bookmark.guid), "This item should be one of the containers");
} else {
Assert.equal(dbItem.URL || null, bookmark.url && bookmark.url.spec, "URL is correct");
Assert.equal(dbItem.DateUpdated.valueOf(), (new Date(bookmark.dateAdded / 1000)).valueOf(), "Date added is correct");
Assert.equal(dbItem.URL || "", bookmark.url, "URL is correct");
Assert.equal(dbItem.DateUpdated.valueOf(), (new Date(bookmark.dateAdded)).valueOf(), "Date added is correct");
}
}
MigrationUtils._importQuantities.bookmarks = 0;
seenBookmarks = [];
bookmarkObserver = {
onItemAdded(itemId, parentId, index, itemType, url, title, dateAdded, itemGuid, parentGuid) {
seenBookmarks.push({itemId, parentId, index, itemType, url, title, dateAdded, itemGuid, parentGuid});
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
listener = events => {
for (let event of events) {
let {
id,
itemType,
url,
title,
dateAdded,
guid,
index,
parentGuid,
parentId,
} = event;
seenBookmarks.push({id, parentId, index, itemType, url, title, dateAdded, guid, parentGuid});
}
};
PlacesUtils.bookmarks.addObserver(bookmarkObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let readingListMigrator = migrator.wrappedJSObject.getReadingListMigratorForTesting(db);
Assert.ok(readingListMigrator.exists, "Should recognize db we just created");
@ -522,7 +532,7 @@ add_task(async function() {
Assert.ok(false, "Got an exception trying to migrate data! " + ex);
return false;
});
PlacesUtils.bookmarks.removeObserver(bookmarkObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
Assert.ok(migrateResult, "Migration should succeed");
Assert.equal(seenBookmarks.length, 3, "Should have seen 3 items being bookmarked (2 items + 1 folder).");
Assert.equal(seenBookmarks.filter(bm => bm.title != sourceLabel).length,
@ -536,7 +546,7 @@ add_task(async function() {
}
let referenceItem = readingListReferenceItems.find(item => item.Title == bookmark.title);
Assert.ok(referenceItem, "Should have imported what we expected");
Assert.equal(referenceItem.URL, bookmark.url.spec, "Should have the right URL");
Assert.equal(referenceItem.URL, bookmark.url, "Should have the right URL");
readingListReferenceItems.splice(readingListReferenceItems.findIndex(item => item.Title == bookmark.title), 1);
}
Assert.ok(!readingListReferenceItems.length, "Should have seen all expected items.");

View File

@ -14,28 +14,22 @@ add_task(async function() {
PlacesUtils.toolbarFolderId ];
let itemCount = 0;
let bmObserver = {
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) {
if (aTitle != label) {
let listener = events => {
for (let event of events) {
if (event.title != label) {
itemCount++;
}
if (expectedParents.length > 0 && aTitle == label) {
let index = expectedParents.indexOf(aParentId);
if (expectedParents.length > 0 && event.title == label) {
let index = expectedParents.indexOf(event.parentId);
Assert.notEqual(index, -1);
expectedParents.splice(index, 1);
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
}
};
PlacesUtils.bookmarks.addObserver(bmObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
await promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS);
PlacesUtils.bookmarks.removeObserver(bmObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
Assert.equal(MigrationUtils._importQuantities.bookmarks, itemCount,
"Ensure telemetry matches actual number of imported items.");

View File

@ -16,31 +16,25 @@ add_task(async function() {
let itemCount = 0;
let gotFolder = false;
let bmObserver = {
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) {
if (aTitle != label) {
let listener = events => {
for (let event of events) {
if (event.title != label) {
itemCount++;
}
if (aItemType == PlacesUtils.bookmarks.TYPE_FOLDER && aTitle == "Stuff") {
if (event.itemType == PlacesUtils.bookmarks.TYPE_FOLDER && event.title == "Stuff") {
gotFolder = true;
}
if (expectedParents.length > 0 && aTitle == label) {
let index = expectedParents.indexOf(aParentId);
if (expectedParents.length > 0 && event.title == label) {
let index = expectedParents.indexOf(event.parentId);
Assert.ok(index != -1, "Found expected parent");
expectedParents.splice(index, 1);
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
}
};
PlacesUtils.bookmarks.addObserver(bmObserver);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
await promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS);
PlacesUtils.bookmarks.removeObserver(bmObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
// Check the bookmarks have been imported to all the expected parents.
Assert.ok(!expectedParents.length, "No more expected parents");

View File

@ -124,10 +124,10 @@ class BookmarksObserver extends Observer {
class PlacesObserver extends Observer {
constructor(dispatch) {
super(dispatch, Ci.nsINavBookmarkObserver);
this.handlePlacesEvent = this.handlePlacesEvent.bind(this);
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
}
handlePlacesEvent(events) {
handlePlacesEvents(events) {
for (let {itemType, source, dateAdded, guid, title, url, isTagging} of events) {
// Skips items that are not bookmarks (like folders), about:* pages or
// default bookmarks, added when the profile is created.
@ -173,7 +173,7 @@ class PlacesFeed {
.getService(Ci.nsINavBookmarksService)
.addObserver(this.bookmarksObserver, true);
PlacesUtils.observers.addListener(["bookmark-added"],
this.placesObserver.handlePlacesEvent);
this.placesObserver.handlePlacesEvents);
Services.obs.addObserver(this, LINK_BLOCKED_EVENT);
}
@ -215,7 +215,7 @@ class PlacesFeed {
PlacesUtils.history.removeObserver(this.historyObserver);
PlacesUtils.bookmarks.removeObserver(this.bookmarksObserver);
PlacesUtils.observers.removeListener(["bookmark-added"],
this.placesObserver.handlePlacesEvent);
this.placesObserver.handlePlacesEvents);
Services.obs.removeObserver(this, LINK_BLOCKED_EVENT);
}

View File

@ -344,14 +344,18 @@ describe("PlacesFeed", () => {
describe("Custom dispatch", () => {
it("should only dispatch 1 PLACES_LINKS_CHANGED action if many onItemAdded notifications happened at once", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "http"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.DEFAULT];
await feed.bookmarksObserver.onItemAdded(...args);
await feed.bookmarksObserver.onItemAdded(...args);
await feed.bookmarksObserver.onItemAdded(...args);
await feed.bookmarksObserver.onItemAdded(...args);
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "https://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.DEFAULT,
};
await feed.placesObserver.handlePlacesEvents([args]);
await feed.placesObserver.handlePlacesEvents([args]);
await feed.placesObserver.handlePlacesEvents([args]);
assert.calledOnce(feed.store.dispatch.withArgs(ac.OnlyToMain({type: at.PLACES_LINKS_CHANGED})));
});
it("should only dispatch 1 PLACES_LINKS_CHANGED action if many onItemRemoved notifications happened at once", async () => {
@ -372,6 +376,132 @@ describe("PlacesFeed", () => {
});
});
describe("PlacesObserver", () => {
let dispatch;
let observer;
beforeEach(() => {
dispatch = sandbox.spy();
observer = new PlacesObserver(dispatch);
});
describe("#handlePlacesEvents", () => {
beforeEach(() => {
});
it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - http", async () => {
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "http://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.DEFAULT,
};
await observer.handlePlacesEvents([args]);
assert.calledWith(dispatch, {type: at.PLACES_BOOKMARK_ADDED, data: FAKE_BOOKMARK});
});
it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - https", async () => {
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "https://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.DEFAULT,
};
await observer.handlePlacesEvents([args]);
assert.calledWith(dispatch, {type: at.PLACES_BOOKMARK_ADDED, data: FAKE_BOOKMARK});
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - not http/https", async () => {
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "places://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.DEFAULT,
};
await observer.handlePlacesEvents([args]);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has IMPORT source", async () => {
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "http://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.IMPORT,
};
await observer.handlePlacesEvents([args]);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has RESTORE source", async () => {
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "http://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.RESTORE,
};
await observer.handlePlacesEvents([args]);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has RESTORE_ON_STARTUP source", async () => {
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "http://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.RESTORE_ON_STARTUP,
};
await observer.handlePlacesEvents([args]);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has SYNC source", async () => {
const args = {
type: "bookmark-added",
itemType: TYPE_BOOKMARK,
url: "http://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.SYNC,
};
await observer.handlePlacesEvents([args]);
assert.notCalled(dispatch);
});
it("should ignore events that are not of TYPE_BOOKMARK", async () => {
const args = {
type: "bookmark-added",
itemType: "nottypebookmark",
url: "http://" + FAKE_BOOKMARK.url,
title: FAKE_BOOKMARK.bookmarkTitle,
dateAdded: FAKE_BOOKMARK.dateAdded,
guid: FAKE_BOOKMARK.bookmarkGuid,
source: SOURCES.SYNC,
};
await observer.handlePlacesEvents([args]);
assert.notCalled(dispatch);
});
});
});
describe("BookmarksObserver", () => {
let dispatch;
let observer;
@ -382,78 +512,6 @@ describe("PlacesFeed", () => {
it("should have a QueryInterface property", () => {
assert.property(observer, "QueryInterface");
});
describe("#onItemAdded", () => {
beforeEach(() => {
});
it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - http", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "http"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.DEFAULT];
await observer.onItemAdded(...args);
assert.calledWith(dispatch, {type: at.PLACES_BOOKMARK_ADDED, data: FAKE_BOOKMARK});
});
it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - https", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "https"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.DEFAULT];
await observer.onItemAdded(...args);
assert.calledWith(dispatch, {type: at.PLACES_BOOKMARK_ADDED, data: FAKE_BOOKMARK});
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - not http/https", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "places"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.DEFAULT];
await observer.onItemAdded(...args);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has IMPORT source", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "http"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.IMPORT];
await observer.onItemAdded(...args);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has RESTORE source", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "http"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.RESTORE];
await observer.onItemAdded(...args);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has RESTORE_ON_STARTUP source", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "http"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.RESTORE_ON_STARTUP];
await observer.onItemAdded(...args);
assert.notCalled(dispatch);
});
it("should not dispatch a PLACES_BOOKMARK_ADDED action - has SYNC source", async () => {
// Yes, onItemAdded has at least 8 arguments. See function definition for docs.
const args = [null, null, null, TYPE_BOOKMARK,
{spec: FAKE_BOOKMARK.url, scheme: "http"}, FAKE_BOOKMARK.bookmarkTitle,
FAKE_BOOKMARK.dateAdded, FAKE_BOOKMARK.bookmarkGuid, "", SOURCES.SYNC];
await observer.onItemAdded(...args);
assert.notCalled(dispatch);
});
it("should ignore events that are not of TYPE_BOOKMARK", async () => {
const args = [null, null, null, "nottypebookmark"];
await observer.onItemAdded(...args);
assert.notCalled(dispatch);
});
});
describe("#onItemRemoved", () => {
it("should ignore events that are not of TYPE_BOOKMARK", async () => {
await observer.onItemRemoved(null, null, null, "nottypebookmark", null, "123foo", "", SOURCES.DEFAULT);

View File

@ -43,11 +43,17 @@ add_task(async function test_newFolder() {
newFolderButton.click();
let newFolderGuid;
let newFolderObserver = PlacesTestUtils.waitForNotification("onItemAdded",
(id, parentId, index, type, uri, title, dateAdded, guid) => {
newFolderGuid = guid;
return type == PlacesUtils.bookmarks.TYPE_FOLDER;
});
let newFolderObserver =
PlacesTestUtils.waitForNotification("bookmark-added",
events => {
for (let {guid, itemType} of events) {
newFolderGuid = guid;
if (itemType == PlacesUtils.bookmarks.TYPE_FOLDER) {
return true;
}
}
return false;
}, "places");
let menulist = document.getElementById("editBMPanel_folderMenuList");

View File

@ -50,12 +50,10 @@ add_task(async function test_add_bookmark_tags_from_bookmarkProperties() {
// Click the bookmark star again to add tags.
await clickBookmarkStar();
Assert.equal(bookmarkPanelTitle.value, gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle"), "Bookmark title is correct");
let promiseNotification = PlacesTestUtils.waitForNotification("onItemAdded", (id, parentId, index, type, itemUrl) => {
if (itemUrl !== null) {
return itemUrl.equals(Services.io.newURI(TEST_URL));
}
return true;
});
let promiseNotification =
PlacesTestUtils.waitForNotification("bookmark-added",
events => events.some(({url}) => !url || url == TEST_URL),
"places");
await fillBookmarkTextField("editBMPanel_tagsField", "tag1", window);
await promiseNotification;
let bookmarks = [];

View File

@ -125,10 +125,10 @@ add_task(async function test_import_json() {
await BrowserTestUtils.promiseAlertDialogOpen("accept");
let restored = 0;
let promiseBookmarksRestored = PlacesTestUtils.waitForNotification("onItemAdded", () => {
restored++;
return restored === actualBookmarks.length;
});
let promiseBookmarksRestored =
PlacesTestUtils.waitForNotification("bookmark-added",
events => events.some(() => ++restored == actualBookmarks.length),
"places");
await promiseBookmarksRestored;
await validateImportedBookmarks(PLACES);

View File

@ -269,7 +269,7 @@ gTests.push({
// Add a visit.
await PlacesTestUtils.addVisits(TEST_URL);
this._addObserver = PlacesTestUtils.waitForNotification("onItemAdded");
this._addObserver = PlacesTestUtils.waitForNotification("bookmark-added", null, "places");
},
selectNode(tree) {

View File

@ -8,7 +8,6 @@ add_task(async function() {
PlacesUtils.bookmarks.addObserver({
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemAdded() {},
onItemRemoved() {},
onItemVisited() {},
onItemMoved() {},

View File

@ -33,8 +33,10 @@ add_task(async function test() {
*/
let simulateDragDrop = async function(aEffect, aMimeType) {
const url = "http://www.mozilla.org/D1995729-A152-4e30-8329-469B01F30AA7";
let promiseItemAddedNotification = PlacesTestUtils.waitForNotification(
"onItemAdded", (itemId, parentId, index, type, uri, guid) => uri.spec == url);
let promiseItemAddedNotification =
PlacesTestUtils.waitForNotification("bookmark-added",
events => events.some(({url: eventUrl}) => eventUrl == url),
"places");
// We use the toolbar as the drag source, as we just need almost any node
// to simulate the drag. The actual data for the drop is passed via the
@ -79,8 +81,10 @@ add_task(async function test() {
else
data = urls.join("\n");
let promiseItemAddedNotification = PlacesTestUtils.waitForNotification(
"onItemAdded", (itemId, parentId, index, type, uri, guid) => uri.spec == urls[2]);
let promiseItemAddedNotification =
PlacesTestUtils.waitForNotification("bookmark-added",
events => events.some(({url}) => url == urls[2]),
"places");
// See notes for EventUtils.synthesizeDrop in simulateDragDrop().
EventUtils.synthesizeDrop(toolbar,

View File

@ -97,7 +97,9 @@ add_task(async function test() {
// Open bookmarks sidebar.
await withSidebarTree("bookmarks", async () => {
// Add observers.
bookmarksObserver.handlePlacesEvents = bookmarksObserver.handlePlacesEvents.bind(bookmarksObserver);
PlacesUtils.bookmarks.addObserver(bookmarksObserver);
PlacesUtils.observers.addListener(["bookmark-added"], bookmarksObserver.handlePlacesEvents);
var addedBookmarks = [];
// MENU
@ -124,6 +126,7 @@ add_task(async function test() {
// Remove observers.
PlacesUtils.bookmarks.removeObserver(bookmarksObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], bookmarksObserver.handlePlacesEvents);
});
// Collapse the personal toolbar if needed.
@ -143,10 +146,10 @@ var bookmarksObserver = {
Ci.nsINavBookmarkObserver,
]),
// nsINavBookmarkObserver
onItemAdded(itemId, folderId, index, itemType, uri, title, dataAdded, guid,
parentGuid) {
this._notifications.push(["assertItemAdded", parentGuid, guid, index]);
handlePlacesEvents(events) {
for (let {parentGuid, guid, index} of events) {
this._notifications.push(["assertItemAdded", parentGuid, guid, index]);
}
},
onItemRemoved(itemId, folderId, index, itemType, uri, guid, parentGuid) {

View File

@ -337,6 +337,7 @@ PlacesObservers::NotifyListeners(const Sequence<OwningNonNull<PlacesEvent>>& aEv
RemoveListener(listener.flags, *listener.value);
}
}
listenersToRemove.Clear();
auto& weakListenersToRemove = *WeakJSListeners::GetListenersToRemove();
if (weakListenersToRemove.Length() > 0) {
@ -344,6 +345,7 @@ PlacesObservers::NotifyListeners(const Sequence<OwningNonNull<PlacesEvent>>& aEv
RemoveListener(listener.flags, *listener.value.get());
}
}
weakListenersToRemove.Clear();
auto& nativeListenersToRemove = *WeakNativeListeners::GetListenersToRemove();
if (nativeListenersToRemove.Length() > 0) {
@ -351,6 +353,7 @@ PlacesObservers::NotifyListeners(const Sequence<OwningNonNull<PlacesEvent>>& aEv
RemoveListener(listener.flags, listener.value.get());
}
}
nativeListenersToRemove.Clear();
gCallingListeners = false;
}

View File

@ -277,7 +277,7 @@ add_task(async function test_tracker_sql_batching() {
await cleanup();
});
add_task(async function test_onItemAdded() {
add_task(async function test_bookmarkAdded() {
_("Items inserted via the synchronous bookmarks API should be tracked");
try {
@ -312,7 +312,7 @@ add_task(async function test_onItemAdded() {
}
});
add_task(async function test_async_onItemAdded() {
add_task(async function test_async_bookmarkAdded() {
_("Items inserted via the asynchronous bookmarks API should be tracked");
try {
@ -713,7 +713,7 @@ add_task(async function test_async_onItemKeywordDeleted() {
}
});
add_task(async function test_onItemAdded_filtered_root() {
add_task(async function test_bookmarkAdded_filtered_root() {
_("Items outside the change roots should not be tracked");
try {

View File

@ -316,11 +316,11 @@ var PlacesTestUtils = Object.freeze({
}));
},
waitForNotification(notification, conditionFn = () => true, type = "bookmarks") {
waitForNotification(notification, conditionFn, type = "bookmarks") {
if (type == "places") {
return new Promise(resolve => {
function listener(events) {
if (conditionFn(events)) {
if (!conditionFn || conditionFn(events)) {
PlacesObservers.removeListener([notification], listener);
resolve();
}
@ -338,7 +338,7 @@ var PlacesTestUtils = Object.freeze({
return ChromeUtils.generateQI([iface]);
if (name == notification)
return (...args) => {
if (conditionFn.apply(this, args)) {
if (!conditionFn || conditionFn.apply(this, args)) {
PlacesUtils[type].removeObserver(proxifiedObserver);
resolve();
}

View File

@ -54,3 +54,32 @@ function expectNotifications(skipDescendants, checkAllArgs) {
PlacesUtils.bookmarks.addObserver(observer);
return observer;
}
function expectPlacesObserverNotifications(types, checkAllArgs) {
let notifications = [];
let listener = (events) => {
for (let event of events) {
notifications.push({
type: event.type,
id: event.id,
itemType: event.itemType,
parentId: event.parentId,
index: event.index,
url: event.url || undefined,
title: event.title,
dateAdded: new Date(event.dateAdded),
guid: event.guid,
parentGuid: event.parentGuid,
source: event.source,
isTagging: event.isTagging,
});
}
};
PlacesUtils.observers.addListener(types, listener);
return {
check(expectedNotifications) {
PlacesUtils.observers.removeListener(types, listener);
Assert.deepEqual(notifications, expectedNotifications);
},
};
}

View File

@ -7,10 +7,11 @@
var observer = {
__proto__: NavBookmarkObserver.prototype,
onItemAdded(id, folder, index) {
this._itemAddedId = id;
this._itemAddedParent = folder;
this._itemAddedIndex = index;
handlePlacesEvents(events) {
Assert.equal(events.length, 1, "Should only be 1 event.");
this._itemAddedId = events[0].id;
this._itemAddedParent = events[0].parentId;
this._itemAddedIndex = events[0].index;
},
onItemChanged(id, property, isAnnotationProperty, value) {
this._itemChangedId = id;
@ -20,9 +21,12 @@ var observer = {
},
};
PlacesUtils.bookmarks.addObserver(observer);
observer.handlePlacesEvents = observer.handlePlacesEvents.bind(observer);
PlacesUtils.observers.addListener(["bookmark-added"], observer.handlePlacesEvents);
registerCleanupFunction(function() {
PlacesUtils.bookmarks.removeObserver(observer);
PlacesUtils.observers.removeListener(["bookmark-added"], observer.handlePlacesEvents);
});
// Returns do_check_eq with .getTime() added onto parameters

View File

@ -210,13 +210,13 @@ add_task(async function tree_where_separator_or_folder_has_kids() {
add_task(async function create_hierarchy() {
let obsInvoked = 0;
let obs = {
onItemAdded(itemId, parentId, index, type, uri, title, dateAdded, guid, parentGuid) {
let listener = events => {
for (let event of events) {
obsInvoked++;
Assert.greater(itemId, 0, "Should have a valid itemId");
},
Assert.greater(event.id, 0, "Should have a valid itemId");
}
};
PlacesUtils.bookmarks.addObserver(obs);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let bms = await PlacesUtils.bookmarks.insertTree({children: [{
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: "Root item",
@ -246,7 +246,7 @@ add_task(async function create_hierarchy() {
],
}], guid: PlacesUtils.bookmarks.unfiledGuid});
await PlacesTestUtils.promiseAsyncUpdates();
PlacesUtils.bookmarks.removeObserver(obs);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
let parentFolder = null, subFolder = null;
let prevBM = null;
for (let bm of bms) {
@ -277,13 +277,13 @@ add_task(async function create_hierarchy() {
add_task(async function insert_many_non_nested() {
let obsInvoked = 0;
let obs = {
onItemAdded(itemId, parentId, index, type, uri, title, dateAdded, guid, parentGuid) {
let listener = events => {
for (let event of events) {
obsInvoked++;
Assert.greater(itemId, 0, "Should have a valid itemId");
},
Assert.greater(event.id, 0, "Should have a valid itemId");
}
};
PlacesUtils.bookmarks.addObserver(obs);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let bms = await PlacesUtils.bookmarks.insertTree({children: [{
url: "http://www.example.com/1",
title: "Item 1",
@ -309,7 +309,7 @@ add_task(async function insert_many_non_nested() {
},
], guid: PlacesUtils.bookmarks.unfiledGuid});
await PlacesTestUtils.promiseAsyncUpdates();
PlacesUtils.bookmarks.removeObserver(obs);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
let startIndex = -1;
for (let bm of bms) {
checkBookmarkObject(bm);
@ -336,12 +336,19 @@ add_task(async function create_in_folder() {
});
let notifications = [];
let obs = {
onItemAdded(itemId, parentId, index, type, uri, title, dateAdded, guid, parentGuid) {
notifications.push({ itemId, parentId, index, title, guid, parentGuid });
},
let listener = events => {
for (let event of events) {
notifications.push({
itemId: event.id,
parentId: event.parentId,
index: event.index,
title: event.title,
guid: event.guid,
parentGuid: event.parentGuid,
});
}
};
PlacesUtils.bookmarks.addObserver(obs);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
let bms = await PlacesUtils.bookmarks.insertTree({children: [{
url: "http://getfirefox.com",
@ -362,7 +369,7 @@ add_task(async function create_in_folder() {
}], guid: mozFolder.guid});
await PlacesTestUtils.promiseAsyncUpdates();
PlacesUtils.bookmarks.removeObserver(obs);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
let mozFolderId = await PlacesUtils.promiseItemId(mozFolder.guid);
let commFolderId = await PlacesUtils.promiseItemId(bms[1].guid);

View File

@ -5,79 +5,119 @@ ChromeUtils.defineModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
add_task(async function insert_separator_notification() {
let observer = expectNotifications();
let observer = expectPlacesObserverNotifications(["bookmark-added"]);
let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
parentGuid: PlacesUtils.bookmarks.unfiledGuid});
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
null, "", PlacesUtils.toPRTime(bm.dateAdded),
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
]);
observer.check([{
type: "bookmark-added",
id: itemId,
itemType: PlacesUtils.bookmarks.TYPE_SEPARATOR,
parentId,
index: bm.index,
url: bm.url,
title: bm.title,
dateAdded: bm.dateAdded,
guid: bm.guid,
parentGuid: bm.parentGuid,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: false,
}]);
});
add_task(async function insert_folder_notification() {
let observer = expectNotifications();
let observer = expectPlacesObserverNotifications(["bookmark-added"]);
let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
title: "a folder" });
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
null, bm.title, PlacesUtils.toPRTime(bm.dateAdded),
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
]);
observer.check([{
type: "bookmark-added",
id: itemId,
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
parentId,
index: bm.index,
url: bm.url,
title: bm.title,
dateAdded: bm.dateAdded,
guid: bm.guid,
parentGuid: bm.parentGuid,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: false,
}]);
});
add_task(async function insert_folder_notitle_notification() {
let observer = expectNotifications();
let observer = expectPlacesObserverNotifications(["bookmark-added"]);
let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
strictEqual(bm.title, "", "Should return empty string for untitled folder");
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
null, "", PlacesUtils.toPRTime(bm.dateAdded),
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
]);
observer.check([{
type: "bookmark-added",
id: itemId,
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
parentId,
index: bm.index,
url: bm.url,
title: bm.title,
dateAdded: bm.dateAdded,
guid: bm.guid,
parentGuid: bm.parentGuid,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: false,
}]);
});
add_task(async function insert_bookmark_notification() {
let observer = expectNotifications();
let observer = expectPlacesObserverNotifications(["bookmark-added"]);
let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: new URL("http://example.com/"),
title: "a bookmark" });
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
bm.url, bm.title, PlacesUtils.toPRTime(bm.dateAdded),
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
]);
observer.check([{
type: "bookmark-added",
id: itemId,
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentId,
index: bm.index,
url: bm.url,
title: bm.title,
dateAdded: bm.dateAdded,
guid: bm.guid,
parentGuid: bm.parentGuid,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: false,
}]);
});
add_task(async function insert_bookmark_notitle_notification() {
let observer = expectNotifications();
let observer = expectPlacesObserverNotifications(["bookmark-added"]);
let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: new URL("http://example.com/") });
strictEqual(bm.title, "", "Should return empty string for untitled bookmark");
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ itemId, parentId, bm.index, bm.type,
bm.url, "", PlacesUtils.toPRTime(bm.dateAdded),
bm.guid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
]);
observer.check([{
type: "bookmark-added",
id: itemId,
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentId,
index: bm.index,
url: bm.url,
title: bm.title,
dateAdded: bm.dateAdded,
guid: bm.guid,
parentGuid: bm.parentGuid,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: false,
}]);
});
add_task(async function insert_bookmark_tag_notification() {
@ -90,24 +130,35 @@ add_task(async function insert_bookmark_tag_notification() {
let tagFolder = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentGuid: PlacesUtils.bookmarks.tagsGuid,
title: "tag" });
let observer = expectNotifications();
let placesObserver = expectPlacesObserverNotifications(["bookmark-added"]);
let bookmarksObserver = expectNotifications();
let tag = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: tagFolder.guid,
url: new URL("http://tag.example.com/") });
let tagId = await PlacesUtils.promiseItemId(tag.guid);
let tagParentId = await PlacesUtils.promiseItemId(tag.parentGuid);
observer.check([ { name: "onItemAdded",
arguments: [ tagId, tagParentId, tag.index, tag.type,
tag.url, "", PlacesUtils.toPRTime(tag.dateAdded),
tag.guid, tag.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
{ name: "onItemChanged",
arguments: [ itemId, "tags", false, "",
PlacesUtils.toPRTime(bm.lastModified),
bm.type, parentId, bm.guid, bm.parentGuid, "",
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
]);
placesObserver.check([{
type: "bookmark-added",
id: tagId,
parentId: tagParentId,
index: tag.index,
itemType: tag.type,
url: tag.url,
title: "",
dateAdded: tag.dateAdded,
guid: tag.guid,
parentGuid: tag.parentGuid,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: true,
}]);
bookmarksObserver.check([ { name: "onItemChanged",
arguments: [ itemId, "tags", false, "",
PlacesUtils.toPRTime(bm.lastModified),
bm.type, parentId, bm.guid, bm.parentGuid, "",
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] },
]);
});
add_task(async function update_bookmark_lastModified() {

View File

@ -14,19 +14,21 @@ add_task(async function() {
let obs = {
count: 0,
lastIndex: 0,
onItemAdded(itemId, parentId, index, type, uri, title, dateAdded, itemGuid, parentGuid) {
this.count++;
let lastIndex = this.lastIndex;
this.lastIndex = index;
if (type == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
Assert.equal(uri.spec, url, "Found the expected url");
handlePlacesEvent(events) {
for (let event of events) {
obs.count++;
let lastIndex = obs.lastIndex;
obs.lastIndex = event.index;
if (event.itemType == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
Assert.equal(event.url, url, "Found the expected url");
}
Assert.ok(event.index == 0 || event.index == lastIndex + 1, "Consecutive indices");
Assert.ok(event.dateAdded >= now, "Found a valid dateAdded");
Assert.ok(PlacesUtils.isValidGuid(event.guid), "guid is valid");
}
Assert.ok(index == 0 || index == lastIndex + 1, "Consecutive indices");
Assert.ok(dateAdded >= PlacesUtils.toPRTime(now), "Found a valid dateAdded");
Assert.ok(PlacesUtils.isValidGuid(itemGuid), "guid is valid");
},
};
PlacesUtils.bookmarks.addObserver(obs);
PlacesUtils.observers.addListener(["bookmark-added"], obs.handlePlacesEvent);
let tree = {
guid,
@ -86,5 +88,7 @@ add_task(async function() {
}
Assert.equal(bms.length, 5);
Assert.equal(obs.count, bms.length);
PlacesUtils.observers.removeListener(["bookmark-added"], obs.handlePlacesEvent);
});

View File

@ -12,6 +12,26 @@ var gBookmarksObserver = {
this.deferred = PromiseUtils.defer();
return this.deferred.promise;
},
// Even though this isn't technically testing nsINavBookmarkObserver,
// this is the simplest place to keep this. Once all of the notifications
// are converted, we can just rename the file.
validateEvents(events) {
Assert.greaterOrEqual(this.expected.length, events.length);
for (let event of events) {
let expected = this.expected.shift();
Assert.equal(expected.eventType, event.type);
let args = expected.args;
for (let i = 0; i < args.length; i++) {
Assert.ok(args[i].check(event[args[i].name]), event.type + "(args[" + i + "]: " + args[i].name + ")");
}
}
if (this.expected.length === 0) {
this.deferred.resolve();
}
},
validate(aMethodName, aArguments) {
Assert.equal(this.expected[0].name, aMethodName);
@ -26,6 +46,10 @@ var gBookmarksObserver = {
}
},
handlePlacesEvents(events) {
this.validateEvents(events);
},
// nsINavBookmarkObserver
onBeginUpdateBatch() {
return this.validate("onBeginUpdateBatch", arguments);
@ -33,9 +57,6 @@ var gBookmarksObserver = {
onEndUpdateBatch() {
return this.validate("onEndUpdateBatch", arguments);
},
onItemAdded() {
return this.validate("onItemAdded", arguments);
},
onItemRemoved() {
return this.validate("onItemRemoved", arguments);
},
@ -63,6 +84,20 @@ var gBookmarkSkipObserver = {
this.deferred = PromiseUtils.defer();
return this.deferred.promise;
},
validateEvents(events) {
events = events.filter(e => !e.isTagging);
Assert.greaterOrEqual(this.expected.length, events.length);
for (let event of events) {
let expectedEventType = this.expected.shift();
Assert.equal(expectedEventType, event.type);
}
if (this.expected.length === 0) {
this.deferred.resolve();
}
},
validate(aMethodName) {
Assert.equal(this.expected.shift(), aMethodName);
if (this.expected.length === 0) {
@ -70,6 +105,10 @@ var gBookmarkSkipObserver = {
}
},
handlePlacesEvents(events) {
this.validateEvents(events);
},
// nsINavBookmarkObserver
onBeginUpdateBatch() {
return this.validate("onBeginUpdateBatch", arguments);
@ -77,9 +116,6 @@ var gBookmarkSkipObserver = {
onEndUpdateBatch() {
return this.validate("onEndUpdateBatch", arguments);
},
onItemAdded() {
return this.validate("onItemAdded", arguments);
},
onItemRemoved() {
return this.validate("onItemRemoved", arguments);
},
@ -101,25 +137,30 @@ var gBookmarkSkipObserver = {
add_task(async function setup() {
PlacesUtils.bookmarks.addObserver(gBookmarksObserver);
PlacesUtils.bookmarks.addObserver(gBookmarkSkipObserver);
gUnfiledFolderId = await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
gBookmarksObserver.handlePlacesEvents =
gBookmarksObserver.handlePlacesEvents.bind(gBookmarksObserver);
gBookmarkSkipObserver.handlePlacesEvents =
gBookmarkSkipObserver.handlePlacesEvents.bind(gBookmarkSkipObserver);
PlacesUtils.observers.addListener(["bookmark-added"], gBookmarksObserver.handlePlacesEvents);
PlacesUtils.observers.addListener(["bookmark-added"], gBookmarkSkipObserver.handlePlacesEvents);
});
add_task(async function onItemAdded_bookmark() {
add_task(async function bookmarkItemAdded_bookmark() {
const title = "Bookmark 1";
let uri = Services.io.newURI("http://1.mozilla.org/");
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemAdded",
"bookmark-added",
]),
gBookmarksObserver.setup([
{ name: "onItemAdded",
{ eventType: "bookmark-added",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "url", check: v => v == uri.spec },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
@ -135,19 +176,19 @@ add_task(async function onItemAdded_bookmark() {
await promise;
});
add_task(async function onItemAdded_separator() {
add_task(async function bookmarkItemAdded_separator() {
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemAdded",
"bookmark-added",
]),
gBookmarksObserver.setup([
{ name: "onItemAdded",
{ eventType: "bookmark-added",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 1 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR },
{ name: "uri", check: v => v === null },
{ name: "url", check: v => v === "" },
{ name: "title", check: v => v === "" },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
@ -162,20 +203,20 @@ add_task(async function onItemAdded_separator() {
await promise;
});
add_task(async function onItemAdded_folder() {
add_task(async function bookmarkItemAdded_folder() {
const title = "Folder 1";
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemAdded",
"bookmark-added",
]),
gBookmarksObserver.setup([
{ name: "onItemAdded",
{ eventType: "bookmark-added",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 2 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "url", check: v => v === "" },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
@ -233,26 +274,26 @@ add_task(async function onItemChanged_tags_bookmark() {
"onItemChanged", "onItemChanged",
]),
gBookmarksObserver.setup([
{ name: "onItemAdded", // This is the tag folder.
{ eventType: "bookmark-added", // This is the tag folder.
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === PlacesUtils.tagsFolderId },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "url", check: v => v === "" },
{ name: "title", check: v => v === TAG },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded", // This is the tag.
{ eventType: "bookmark-added", // This is the tag.
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "url", check: v => v == uri.spec },
{ name: "title", check: v => v === "" },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
@ -479,56 +520,56 @@ add_task(async function onItemRemoved_folder_recursive() {
let uri = Services.io.newURI("http://1.mozilla.org/");
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemAdded", "onItemAdded", "onItemAdded", "onItemAdded",
"bookmark-added", "bookmark-added", "bookmark-added", "bookmark-added",
"onItemRemoved",
]),
gBookmarksObserver.setup([
{ name: "onItemAdded",
{ eventType: "bookmark-added",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "url", check: v => v === "" },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded",
{ eventType: "bookmark-added",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "url", check: v => v == uri.spec },
{ name: "title", check: v => v === BMTITLE },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded",
{ eventType: "bookmark-added",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
{ name: "index", check: v => v === 1 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "url", check: v => v === "" },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded",
{ eventType: "bookmark-added",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "id", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => typeof(v) == "number" && v > 0 },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "url", check: v => v == uri.spec },
{ name: "title", check: v => v === BMTITLE },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
@ -608,4 +649,6 @@ add_task(async function onItemRemoved_folder_recursive() {
add_task(function cleanup() {
PlacesUtils.bookmarks.removeObserver(gBookmarksObserver);
PlacesUtils.bookmarks.removeObserver(gBookmarkSkipObserver);
PlacesUtils.observers.removeListener(["bookmark-added"], gBookmarksObserver.handlePlacesEvents);
PlacesUtils.observers.removeListener(["bookmark-added"], gBookmarkSkipObserver.handlePlacesEvents);
});

View File

@ -28,19 +28,26 @@ add_task(async function test_removeFolderTransaction_reinsert() {
notifications.length = 0;
}
let listener = events => {
for (let event of events) {
notifications.push(["bookmark-added",
event.id,
event.parentId,
event.guid,
event.parentGuid]);
}
};
let observer = {
__proto__: NavBookmarkObserver.prototype,
onItemAdded(itemId, parentId, index, type, uri, title, dateAdded, guid,
parentGuid) {
notifications.push(["onItemAdded", itemId, parentId, guid, parentGuid]);
},
onItemRemoved(itemId, parentId, index, type, uri, guid, parentGuid) {
notifications.push(["onItemRemoved", itemId, parentId, guid, parentGuid]);
},
};
PlacesUtils.bookmarks.addObserver(observer);
PlacesUtils.observers.addListener(["bookmark-added"], listener);
PlacesUtils.registerShutdownFunction(function() {
PlacesUtils.bookmarks.removeObserver(observer);
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
});
let transaction = PlacesTransactions.Remove({guid: folder.guid});
@ -65,10 +72,10 @@ add_task(async function test_removeFolderTransaction_reinsert() {
tbId = await PlacesUtils.promiseItemId(tb.guid);
checkNotifications([
["onItemAdded", folderId, PlacesUtils.bookmarksMenuFolderId, folder.guid,
["bookmark-added", folderId, PlacesUtils.bookmarksMenuFolderId, folder.guid,
PlacesUtils.bookmarks.menuGuid],
["onItemAdded", fxId, folderId, fx.guid, folder.guid],
["onItemAdded", tbId, folderId, tb.guid, folder.guid],
["bookmark-added", fxId, folderId, fx.guid, folder.guid],
["bookmark-added", tbId, folderId, tb.guid, folder.guid],
], "Undo should reinsert folder with different id but same GUID");
await PlacesTransactions.redo();

View File

@ -27,7 +27,6 @@ function promiseOnItemChanged() {
PlacesUtils.bookmarks.addObserver({
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemAdded() {},
onItemRemoved() {},
onItemVisited() {},
onItemMoved() {},

View File

@ -695,7 +695,6 @@ function NavBookmarkObserver() {}
NavBookmarkObserver.prototype = {
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemAdded() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},

View File

@ -6,23 +6,19 @@
var bs = PlacesUtils.bookmarks;
var hs = PlacesUtils.history;
var os = PlacesUtils.observers;
var anno = PlacesUtils.annotations;
var bookmarksObserver = {
onBeginUpdateBatch() {
this._beginUpdateBatch = true;
},
onEndUpdateBatch() {
this._endUpdateBatch = true;
},
onItemAdded(id, folder, index, itemType, uri, title, dateAdded,
guid) {
this._itemAddedId = id;
this._itemAddedParent = folder;
this._itemAddedIndex = index;
this._itemAddedURI = uri;
this._itemAddedTitle = title;
handlePlacesEvents(events) {
Assert.equal(events.length, 1);
let event = events[0];
bookmarksObserver._itemAddedId = event.id;
bookmarksObserver._itemAddedParent = event.parentId;
bookmarksObserver._itemAddedIndex = event.index;
bookmarksObserver._itemAddedURI = event.url ? Services.io.newURI(event.url) : null;
bookmarksObserver._itemAddedTitle = event.title;
// Ensure that we've created a guid for this item.
let stmt = DBConn().createStatement(
@ -30,13 +26,20 @@ var bookmarksObserver = {
FROM moz_bookmarks
WHERE id = :item_id`
);
stmt.params.item_id = id;
stmt.params.item_id = event.id;
Assert.ok(stmt.executeStep());
Assert.ok(!stmt.getIsNull(0));
do_check_valid_places_guid(stmt.row.guid);
Assert.equal(stmt.row.guid, guid);
Assert.equal(stmt.row.guid, event.guid);
stmt.finalize();
},
onBeginUpdateBatch() {
this._beginUpdateBatch = true;
},
onEndUpdateBatch() {
this._endUpdateBatch = true;
},
onItemRemoved(id, folder, index, itemType) {
this._itemRemovedId = id;
this._itemRemovedFolder = folder;
@ -77,6 +80,7 @@ var bmStartIndex = 0;
add_task(async function test_bookmarks() {
bs.addObserver(bookmarksObserver);
os.addListener(["bookmark-added"], bookmarksObserver.handlePlacesEvents);
// test special folders
Assert.ok(bs.placesRoot > 0);

View File

@ -217,21 +217,34 @@ function BookmarkObserver({ ignoreDates = true, skipTags = false } = {}) {
this.notifications = [];
this.ignoreDates = ignoreDates;
this.skipTags = skipTags;
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
}
BookmarkObserver.prototype = {
handlePlacesEvents(events) {
for (let event of events) {
if (this.skipTags && event.isTagging) {
continue;
}
let params = {
itemId: event.id,
parentId: event.parentId,
index: event.index,
type: event.itemType,
urlHref: event.url,
title: event.title,
guid: event.guid,
parentGuid: event.parentGuid,
source: event.source,
};
if (!this.ignoreDates) {
params.dateAdded = event.dateAdded * 1000;
}
this.notifications.push({ name: "bookmark-added", params });
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemAdded(itemId, parentId, index, type, uri, title, dateAdded, guid,
parentGuid, source) {
let urlHref = uri ? uri.spec : null;
let params = { itemId, parentId, index, type, urlHref, title, guid,
parentGuid, source };
if (!this.ignoreDates) {
params.dateAdded = dateAdded;
}
this.notifications.push({ name: "onItemAdded", params });
},
onItemRemoved(itemId, parentId, index, type, uri, guid, parentGuid, source) {
let urlHref = uri ? uri.spec : null;
this.notifications.push({
@ -265,6 +278,7 @@ BookmarkObserver.prototype = {
check(expectedNotifications) {
PlacesUtils.bookmarks.removeObserver(this);
PlacesUtils.observers.removeListener(["bookmark-added"], this.handlePlacesEvents);
if (!ObjectUtils.deepEqual(this.notifications, expectedNotifications)) {
info(`Expected notifications: ${JSON.stringify(expectedNotifications)}`);
info(`Actual notifications: ${JSON.stringify(this.notifications)}`);
@ -279,6 +293,7 @@ BookmarkObserver.prototype = {
function expectBookmarkChangeNotifications(options) {
let observer = new BookmarkObserver(options);
PlacesUtils.bookmarks.addObserver(observer);
PlacesUtils.observers.addListener(["bookmark-added"], observer.handlePlacesEvents);
return observer;
}

View File

@ -258,18 +258,18 @@ add_task(async function test_livemarks() {
parentGuid: "toolbar_____", oldValue: "livemarkBBBB",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: livemarkC.id, parentId: PlacesUtils.toolbarFolderId,
index: 0, type: PlacesUtils.bookmarks.TYPE_FOLDER,
urlHref: null, title: "C (remote)", guid: "livemarkCCCC",
urlHref: "", title: "C (remote)", guid: "livemarkCCCC",
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: livemarkE.id,
parentId: unfiledFolderId,
index: 0, type: PlacesUtils.bookmarks.TYPE_FOLDER,
urlHref: null, title: "E", guid: "livemarkEEEE",
urlHref: "", title: "E", guid: "livemarkEEEE",
parentGuid: "unfiled_____",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {

View File

@ -320,7 +320,7 @@ add_task(async function test_apply_then_revert() {
oldValue: "bookmarkEEE1",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("bookmarkFFFF"),
parentId: PlacesUtils.bookmarksMenuFolderId, index: 1,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,

View File

@ -506,11 +506,11 @@ add_task(async function test_move_into_parent_sibling() {
let localItemIds = await PlacesUtils.promiseManyItemIds(["folderCCCCCC",
"bookmarkBBBB", "folderAAAAAA"]);
observer.check([{
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("folderCCCCCC"),
parentId: PlacesUtils.bookmarksMenuFolderId, index: 1,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
urlHref: null, title: "C",
urlHref: "", title: "C",
guid: "folderCCCCCC",
parentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
@ -661,7 +661,7 @@ add_task(async function test_complex_move_with_additions() {
let localItemIds = await PlacesUtils.promiseManyItemIds(["bookmarkEEEE",
"folderAAAAAA", "bookmarkCCCC"]);
observer.check([{
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("bookmarkEEEE"),
parentId: localItemIds.get("folderAAAAAA"), index: 1,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,

View File

@ -119,7 +119,7 @@ add_task(async function test_value_combo() {
let localItemIds = await PlacesUtils.promiseManyItemIds(["fxBmk_______",
"tFolder_____", "tbBmk_______", "bzBmk_______", "mozBmk______"]);
observer.check([{
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("fxBmk_______"),
parentId: PlacesUtils.toolbarFolderId, index: 0,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
@ -128,15 +128,15 @@ add_task(async function test_value_combo() {
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("tFolder_____"),
parentId: PlacesUtils.toolbarFolderId,
index: 1, type: PlacesUtils.bookmarks.TYPE_FOLDER,
urlHref: null, title: "Mail", guid: "tFolder_____",
urlHref: "", title: "Mail", guid: "tFolder_____",
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("tbBmk_______"),
parentId: localItemIds.get("tFolder_____"), index: 0,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
@ -676,7 +676,7 @@ add_task(async function test_keywords_complex() {
"bookmarkAAA1", "bookmarkBBB1", "bookmarkBBBB", "bookmarkCCCC",
"bookmarkDDDD", "bookmarkEEEE"]);
let expectedNotifications = [{
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("bookmarkAAAA"),
parentId: PlacesUtils.bookmarksMenuFolderId, index: 0,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
@ -685,7 +685,7 @@ add_task(async function test_keywords_complex() {
parentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("bookmarkAAA1"),
parentId: PlacesUtils.bookmarksMenuFolderId, index: 1,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
@ -694,7 +694,7 @@ add_task(async function test_keywords_complex() {
parentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
}, {
name: "onItemAdded",
name: "bookmark-added",
params: { itemId: localItemIds.get("bookmarkBBB1"),
parentId: unfiledFolderId, index: 0,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const bmsvc = PlacesUtils.bookmarks;
const obsvc = PlacesUtils.observers;
const tagssvc = PlacesUtils.tagging;
const annosvc = PlacesUtils.annotations;
const PT = PlacesTransactions;
@ -30,6 +31,23 @@ var observer = {
this.endUpdateBatch = false;
},
handlePlacesEvents(events) {
for (let event of events) {
// Ignore tag items.
if (event.isTagging) {
this.tagRelatedGuids.add(event.guid);
return;
}
this.itemsAdded.set(event.guid, { itemId: event.id,
parentGuid: event.parentGuid,
index: event.index,
itemType: event.itemType,
title: event.title,
url: event.url });
}
},
onBeginUpdateBatch() {
this.beginUpdateBatch = true;
},
@ -38,24 +56,6 @@ var observer = {
this.endUpdateBatch = true;
},
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle, aDateAdded,
aGuid, aParentGuid) {
// Ignore tag items.
if (aParentId == PlacesUtils.tagsFolderId ||
(aParentId != PlacesUtils.placesRootId &&
bmsvc.getFolderIdForItem(aParentId) == PlacesUtils.tagsFolderId)) {
this.tagRelatedGuids.add(aGuid);
return;
}
this.itemsAdded.set(aGuid, { itemId: aItemId,
parentGuid: aParentGuid,
index: aIndex,
itemType: aItemType,
title: aTitle,
url: aURI });
},
onItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI, aGuid, aParentGuid) {
if (this.tagRelatedGuids.has(aGuid))
return;
@ -108,8 +108,11 @@ var bmStartIndex = 0;
function run_test() {
bmsvc.addObserver(observer);
observer.handlePlacesEvents = observer.handlePlacesEvents.bind(observer);
obsvc.addListener(["bookmark-added"], observer.handlePlacesEvents);
registerCleanupFunction(function() {
bmsvc.removeObserver(observer);
obsvc.removeListener(["bookmark-added"], observer.handlePlacesEvents);
});
run_next_test();
@ -180,7 +183,7 @@ function ensureItemsAdded(...items) {
Assert.equal(info[propName], item[propName]);
}
if ("url" in item)
Assert.ok(info.url.equals(Services.io.newURI(item.url)),
Assert.ok(Services.io.newURI(info.url).equals(Services.io.newURI(item.url)),
"Should have the correct url");
}
@ -1610,7 +1613,7 @@ add_task(async function test_livemark_txns() {
ensureItemsAdded({ guid: livemark_info.guid,
title: livemark_info.title,
parentGuid: livemark_info.parentGuid,
itemType: bmsvc.TYPE_FOLDER });
itemType: PlacesUtils.bookmarks.TYPE_FOLDER });
let annos = [{ name: PlacesUtils.LMANNO_FEEDURI,
value: livemark_info.feedUrl }];
if ("siteUrl" in livemark_info) {

View File

@ -159,18 +159,17 @@ add_task(async function test_addLivemark_badGuid_throws() {
add_task(async function test_addLivemark_parentId_succeeds() {
let onItemAddedCalled = false;
PlacesUtils.bookmarks.addObserver({
__proto__: NavBookmarkObserver.prototype,
onItemAdded: function onItemAdded(aItemId, aParentId, aIndex, aItemType,
aURI, aTitle) {
onItemAddedCalled = true;
PlacesUtils.bookmarks.removeObserver(this);
Assert.equal(aParentId, unfiledFolderId);
Assert.equal(aIndex, 0);
Assert.equal(aItemType, Ci.nsINavBookmarksService.TYPE_FOLDER);
Assert.equal(aTitle, "test");
},
});
let listener = events => {
Assert.equal(events.length, 1);
let event = events[0];
onItemAddedCalled = true;
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
Assert.equal(event.parentId, unfiledFolderId);
Assert.equal(event.index, 0);
Assert.equal(event.itemType, PlacesUtils.bookmarks.TYPE_FOLDER);
Assert.equal(event.title, "test");
};
PlacesUtils.observers.addListener(["bookmark-added"], listener);
await PlacesUtils.livemarks.addLivemark(
{ title: "test",

View File

@ -39,7 +39,6 @@ add_task(async function run_test() {
}
},
onItemAdded() {},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemVisited() {},