зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1511700 - Use the new notification system (PlacesObserver) for bookmark removed notifications. r=Standard8,mak
Phasing out the old notification system for OnItemRemoved events. Differential Revision: https://phabricator.services.mozilla.com/D17753 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
4469780b7b
Коммит
676ce0d13c
|
@ -1602,7 +1602,7 @@ var BookmarkingUI = {
|
||||||
if (this._hasBookmarksObserver) {
|
if (this._hasBookmarksObserver) {
|
||||||
PlacesUtils.bookmarks.removeObserver(this);
|
PlacesUtils.bookmarks.removeObserver(this);
|
||||||
PlacesUtils.observers.removeListener(
|
PlacesUtils.observers.removeListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this.handlePlacesEvents
|
this.handlePlacesEvents
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1653,7 +1653,7 @@ var BookmarkingUI = {
|
||||||
PlacesUtils.bookmarks.addObserver(this);
|
PlacesUtils.bookmarks.addObserver(this);
|
||||||
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
|
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this.handlePlacesEvents
|
this.handlePlacesEvents
|
||||||
);
|
);
|
||||||
this._hasBookmarksObserver = true;
|
this._hasBookmarksObserver = true;
|
||||||
|
@ -1946,30 +1946,32 @@ var BookmarkingUI = {
|
||||||
},
|
},
|
||||||
|
|
||||||
handlePlacesEvents(aEvents) {
|
handlePlacesEvents(aEvents) {
|
||||||
|
for (let ev of aEvents) {
|
||||||
|
switch (ev.type) {
|
||||||
|
case "bookmark-added":
|
||||||
// Only need to update the UI if it wasn't marked as starred before:
|
// Only need to update the UI if it wasn't marked as starred before:
|
||||||
if (this._itemGuids.size == 0) {
|
if (this._itemGuids.size == 0) {
|
||||||
for (let { url, guid } of aEvents) {
|
if (ev.url && ev.url == this._uri.spec) {
|
||||||
if (url && url == this._uri.spec) {
|
|
||||||
// If a new bookmark has been added to the tracked uri, register it.
|
// If a new bookmark has been added to the tracked uri, register it.
|
||||||
if (!this._itemGuids.has(guid)) {
|
if (!this._itemGuids.has(ev.guid)) {
|
||||||
this._itemGuids.add(guid);
|
this._itemGuids.add(ev.guid);
|
||||||
this._updateStar();
|
this._updateStar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
},
|
case "bookmark-removed":
|
||||||
|
|
||||||
// nsINavBookmarkObserver
|
|
||||||
onItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI, aGuid) {
|
|
||||||
// If one of the tracked bookmarks has been removed, unregister it.
|
// If one of the tracked bookmarks has been removed, unregister it.
|
||||||
if (this._itemGuids.has(aGuid)) {
|
if (this._itemGuids.has(ev.guid)) {
|
||||||
this._itemGuids.delete(aGuid);
|
this._itemGuids.delete(ev.guid);
|
||||||
// Only need to update the UI if the page is no longer starred
|
// Only need to update the UI if the page is no longer starred
|
||||||
if (this._itemGuids.size == 0) {
|
if (this._itemGuids.size == 0) {
|
||||||
this._updateStar();
|
this._updateStar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onItemChanged(
|
onItemChanged(
|
||||||
|
|
|
@ -55,8 +55,9 @@ add_task(async function test_remove_bookmark_with_tag_via_edit_bookmark() {
|
||||||
);
|
);
|
||||||
|
|
||||||
let removeNotification = PlacesTestUtils.waitForNotification(
|
let removeNotification = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(id, parentId, index, type, itemUrl) => testURL == unescape(itemUrl.spec)
|
events => events.some(event => unescape(event.url) == testURL),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
|
|
||||||
let removeButton = document.getElementById("editBookmarkPanelRemoveButton");
|
let removeButton = document.getElementById("editBookmarkPanelRemoveButton");
|
||||||
|
|
|
@ -97,8 +97,9 @@ add_task(async function bookmark() {
|
||||||
});
|
});
|
||||||
|
|
||||||
let onItemRemovedPromise = PlacesTestUtils.waitForNotification(
|
let onItemRemovedPromise = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(id, parentId, index, type, itemUrl) => url == itemUrl.spec
|
events => events.some(event => event.url == url),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Click the remove-bookmark button in the panel.
|
// Click the remove-bookmark button in the panel.
|
||||||
|
|
|
@ -84,23 +84,32 @@ async function promiseAllChangesMade({ itemsToAdd, itemsToRemove }) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let listener = events => {
|
let listener = events => {
|
||||||
is(events.length, 1, "Should only have 1 event.");
|
is(events.length, 1, "Should only have 1 event.");
|
||||||
|
switch (events[0].type) {
|
||||||
|
case "bookmark-added":
|
||||||
itemsToAdd--;
|
itemsToAdd--;
|
||||||
if (itemsToAdd == 0 && itemsToRemove == 0) {
|
if (itemsToAdd == 0 && itemsToRemove == 0) {
|
||||||
PlacesUtils.bookmarks.removeObserver(bmObserver);
|
PlacesUtils.bookmarks.removeObserver(bmObserver);
|
||||||
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
|
PlacesUtils.observers.removeListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
listener
|
||||||
|
);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
};
|
break;
|
||||||
let bmObserver = {
|
case "bookmark-removed":
|
||||||
onItemRemoved() {
|
|
||||||
itemsToRemove--;
|
itemsToRemove--;
|
||||||
if (itemsToAdd == 0 && itemsToRemove == 0) {
|
if (itemsToAdd == 0 && itemsToRemove == 0) {
|
||||||
PlacesUtils.bookmarks.removeObserver(bmObserver);
|
PlacesUtils.bookmarks.removeObserver(bmObserver);
|
||||||
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
|
PlacesUtils.observers.removeListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
listener
|
||||||
|
);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let bmObserver = {
|
||||||
onBeginUpdateBatch() {},
|
onBeginUpdateBatch() {},
|
||||||
onEndUpdateBatch() {},
|
onEndUpdateBatch() {},
|
||||||
onItemChanged() {},
|
onItemChanged() {},
|
||||||
|
@ -108,7 +117,10 @@ async function promiseAllChangesMade({ itemsToAdd, itemsToRemove }) {
|
||||||
onItemMoved() {},
|
onItemMoved() {},
|
||||||
};
|
};
|
||||||
PlacesUtils.bookmarks.addObserver(bmObserver);
|
PlacesUtils.bookmarks.addObserver(bmObserver);
|
||||||
PlacesUtils.observers.addListener(["bookmark-added"], listener);
|
PlacesUtils.observers.addListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
listener
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,6 @@ let observer = new (class extends EventEmitter {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.skipTags = true;
|
this.skipTags = true;
|
||||||
this.skipDescendantsOnItemRemoval = true;
|
|
||||||
|
|
||||||
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
|
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -132,6 +131,8 @@ let observer = new (class extends EventEmitter {
|
||||||
|
|
||||||
handlePlacesEvents(events) {
|
handlePlacesEvents(events) {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added":
|
||||||
if (event.isTagging) {
|
if (event.isTagging) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -150,6 +151,24 @@ let observer = new (class extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit("created", bookmark);
|
this.emit("created", bookmark);
|
||||||
|
break;
|
||||||
|
case "bookmark-removed":
|
||||||
|
if (event.isTagging || event.isDescendantRemoval) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let node = {
|
||||||
|
id: event.guid,
|
||||||
|
parentId: event.parentGuid,
|
||||||
|
index: event.index,
|
||||||
|
type: BOOKMARKS_TYPES_TO_API_TYPES_MAP.get(event.itemType),
|
||||||
|
url: getUrl(event.itemType, event.url),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.emit("removed", {
|
||||||
|
guid: event.guid,
|
||||||
|
info: { parentId: event.parentGuid, index: event.index, node },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,18 +195,6 @@ let observer = new (class extends EventEmitter {
|
||||||
this.emit("moved", { guid, info });
|
this.emit("moved", { guid, info });
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemRemoved(id, parentId, index, itemType, uri, guid, parentGuid, source) {
|
|
||||||
let node = {
|
|
||||||
id: guid,
|
|
||||||
parentId: parentGuid,
|
|
||||||
index,
|
|
||||||
type: BOOKMARKS_TYPES_TO_API_TYPES_MAP.get(itemType),
|
|
||||||
url: getUrl(itemType, uri && uri.spec),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.emit("removed", { guid, info: { parentId: parentGuid, index, node } });
|
|
||||||
}
|
|
||||||
|
|
||||||
onItemChanged(
|
onItemChanged(
|
||||||
id,
|
id,
|
||||||
prop,
|
prop,
|
||||||
|
@ -220,7 +227,7 @@ const decrementListeners = () => {
|
||||||
if (!listenerCount) {
|
if (!listenerCount) {
|
||||||
PlacesUtils.bookmarks.removeObserver(observer);
|
PlacesUtils.bookmarks.removeObserver(observer);
|
||||||
PlacesUtils.observers.removeListener(
|
PlacesUtils.observers.removeListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
observer.handlePlacesEvents
|
observer.handlePlacesEvents
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -231,7 +238,7 @@ const incrementListeners = () => {
|
||||||
if (listenerCount == 1) {
|
if (listenerCount == 1) {
|
||||||
PlacesUtils.bookmarks.addObserver(observer);
|
PlacesUtils.bookmarks.addObserver(observer);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
observer.handlePlacesEvents
|
observer.handlePlacesEvents
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,34 +95,6 @@ class BookmarksObserver extends Observer {
|
||||||
this.skipTags = true;
|
this.skipTags = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* onItemRemoved - Called when a bookmark is removed
|
|
||||||
*
|
|
||||||
* @param {str} id
|
|
||||||
* @param {str} folderId
|
|
||||||
* @param {int} index
|
|
||||||
* @param {int} type Indicates if the bookmark is an actual bookmark,
|
|
||||||
* a folder, or a separator.
|
|
||||||
* @param {str} uri
|
|
||||||
* @param {str} guid The unique id of the bookmark
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line max-params
|
|
||||||
onItemRemoved(id, folderId, index, type, uri, guid, parentGuid, source) {
|
|
||||||
if (
|
|
||||||
type === PlacesUtils.bookmarks.TYPE_BOOKMARK &&
|
|
||||||
source !== PlacesUtils.bookmarks.SOURCES.IMPORT &&
|
|
||||||
source !== PlacesUtils.bookmarks.SOURCES.RESTORE &&
|
|
||||||
source !== PlacesUtils.bookmarks.SOURCES.RESTORE_ON_STARTUP &&
|
|
||||||
source !== PlacesUtils.bookmarks.SOURCES.SYNC
|
|
||||||
) {
|
|
||||||
this.dispatch({ type: at.PLACES_LINKS_CHANGED });
|
|
||||||
this.dispatch({
|
|
||||||
type: at.PLACES_BOOKMARK_REMOVED,
|
|
||||||
data: { url: uri.spec, bookmarkGuid: guid },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty functions to make xpconnect happy
|
// Empty functions to make xpconnect happy
|
||||||
onBeginUpdateBatch() {}
|
onBeginUpdateBatch() {}
|
||||||
|
|
||||||
|
@ -155,7 +127,10 @@ class PlacesObserver extends Observer {
|
||||||
title,
|
title,
|
||||||
url,
|
url,
|
||||||
isTagging,
|
isTagging,
|
||||||
|
type,
|
||||||
} of events) {
|
} of events) {
|
||||||
|
switch (type) {
|
||||||
|
case "bookmark-added":
|
||||||
// Skips items that are not bookmarks (like folders), about:* pages or
|
// Skips items that are not bookmarks (like folders), about:* pages or
|
||||||
// default bookmarks, added when the profile is created.
|
// default bookmarks, added when the profile is created.
|
||||||
if (
|
if (
|
||||||
|
@ -180,6 +155,24 @@ class PlacesObserver extends Observer {
|
||||||
url,
|
url,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case "bookmark-removed":
|
||||||
|
if (
|
||||||
|
isTagging ||
|
||||||
|
(itemType === PlacesUtils.bookmarks.TYPE_BOOKMARK &&
|
||||||
|
source !== PlacesUtils.bookmarks.SOURCES.IMPORT &&
|
||||||
|
source !== PlacesUtils.bookmarks.SOURCES.RESTORE &&
|
||||||
|
source !== PlacesUtils.bookmarks.SOURCES.RESTORE_ON_STARTUP &&
|
||||||
|
source !== PlacesUtils.bookmarks.SOURCES.SYNC)
|
||||||
|
) {
|
||||||
|
this.dispatch({ type: at.PLACES_LINKS_CHANGED });
|
||||||
|
this.dispatch({
|
||||||
|
type: at.PLACES_BOOKMARK_REMOVED,
|
||||||
|
data: { url, bookmarkGuid: guid },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,7 +195,7 @@ class PlacesFeed {
|
||||||
.getService(Ci.nsINavBookmarksService)
|
.getService(Ci.nsINavBookmarksService)
|
||||||
.addObserver(this.bookmarksObserver, true);
|
.addObserver(this.bookmarksObserver, true);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this.placesObserver.handlePlacesEvent
|
this.placesObserver.handlePlacesEvent
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -246,7 +239,7 @@ class PlacesFeed {
|
||||||
PlacesUtils.history.removeObserver(this.historyObserver);
|
PlacesUtils.history.removeObserver(this.historyObserver);
|
||||||
PlacesUtils.bookmarks.removeObserver(this.bookmarksObserver);
|
PlacesUtils.bookmarks.removeObserver(this.bookmarksObserver);
|
||||||
PlacesUtils.observers.removeListener(
|
PlacesUtils.observers.removeListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this.placesObserver.handlePlacesEvent
|
this.placesObserver.handlePlacesEvent
|
||||||
);
|
);
|
||||||
Services.obs.removeObserver(this, LINK_BLOCKED_EVENT);
|
Services.obs.removeObserver(this, LINK_BLOCKED_EVENT);
|
||||||
|
|
|
@ -111,7 +111,7 @@ describe("PlacesFeed", () => {
|
||||||
);
|
);
|
||||||
assert.calledWith(
|
assert.calledWith(
|
||||||
global.PlacesUtils.observers.addListener,
|
global.PlacesUtils.observers.addListener,
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
feed.placesObserver.handlePlacesEvent
|
feed.placesObserver.handlePlacesEvent
|
||||||
);
|
);
|
||||||
assert.calledWith(global.Services.obs.addObserver, feed, BLOCKED_EVENT);
|
assert.calledWith(global.Services.obs.addObserver, feed, BLOCKED_EVENT);
|
||||||
|
@ -133,7 +133,7 @@ describe("PlacesFeed", () => {
|
||||||
);
|
);
|
||||||
assert.calledWith(
|
assert.calledWith(
|
||||||
global.PlacesUtils.observers.removeListener,
|
global.PlacesUtils.observers.removeListener,
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
feed.placesObserver.handlePlacesEvent
|
feed.placesObserver.handlePlacesEvent
|
||||||
);
|
);
|
||||||
assert.calledWith(
|
assert.calledWith(
|
||||||
|
@ -685,6 +685,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "https://www.foo.com",
|
url: "https://www.foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await feed.placesObserver.handlePlacesEvent(args);
|
await feed.placesObserver.handlePlacesEvent(args);
|
||||||
|
@ -699,19 +700,22 @@ describe("PlacesFeed", () => {
|
||||||
});
|
});
|
||||||
it("should only dispatch 1 PLACES_LINKS_CHANGED action if many onItemRemoved notifications happened at once", async () => {
|
it("should only dispatch 1 PLACES_LINKS_CHANGED action if many onItemRemoved notifications happened at once", async () => {
|
||||||
const args = [
|
const args = [
|
||||||
null,
|
{
|
||||||
null,
|
id: null,
|
||||||
null,
|
parentId: null,
|
||||||
TYPE_BOOKMARK,
|
index: null,
|
||||||
{ spec: "foo.com" },
|
itemType: TYPE_BOOKMARK,
|
||||||
"123foo",
|
url: "foo.com",
|
||||||
"",
|
guid: "123foo",
|
||||||
SOURCES.DEFAULT,
|
parentGuid: "",
|
||||||
|
source: SOURCES.DEFAULT,
|
||||||
|
type: "bookmark-removed",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
await feed.bookmarksObserver.onItemRemoved(...args);
|
await feed.placesObserver.handlePlacesEvent(args);
|
||||||
await feed.bookmarksObserver.onItemRemoved(...args);
|
await feed.placesObserver.handlePlacesEvent(args);
|
||||||
await feed.bookmarksObserver.onItemRemoved(...args);
|
await feed.placesObserver.handlePlacesEvent(args);
|
||||||
await feed.bookmarksObserver.onItemRemoved(...args);
|
await feed.placesObserver.handlePlacesEvent(args);
|
||||||
|
|
||||||
assert.calledOnce(
|
assert.calledOnce(
|
||||||
feed.store.dispatch.withArgs(
|
feed.store.dispatch.withArgs(
|
||||||
|
@ -733,13 +737,13 @@ describe("PlacesFeed", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("PlacesObserver", () => {
|
describe("PlacesObserver", () => {
|
||||||
describe("#bookmark-added", () => {
|
|
||||||
let dispatch;
|
let dispatch;
|
||||||
let observer;
|
let observer;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
dispatch = sandbox.spy();
|
dispatch = sandbox.spy();
|
||||||
observer = new PlacesObserver(dispatch);
|
observer = new PlacesObserver(dispatch);
|
||||||
});
|
});
|
||||||
|
describe("#bookmark-added", () => {
|
||||||
it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - http", async () => {
|
it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - http", async () => {
|
||||||
const args = [
|
const args = [
|
||||||
{
|
{
|
||||||
|
@ -750,6 +754,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "http://www.foo.com",
|
url: "http://www.foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -774,6 +779,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "https://www.foo.com",
|
url: "https://www.foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -798,6 +804,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "foo.com",
|
url: "foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -814,6 +821,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "foo.com",
|
url: "foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -830,6 +838,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "foo.com",
|
url: "foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -846,6 +855,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "foo.com",
|
url: "foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -862,6 +872,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "foo.com",
|
url: "foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -878,6 +889,7 @@ describe("PlacesFeed", () => {
|
||||||
title: FAKE_BOOKMARK.bookmarkTitle,
|
title: FAKE_BOOKMARK.bookmarkTitle,
|
||||||
url: "https://www.foo.com",
|
url: "https://www.foo.com",
|
||||||
isTagging: false,
|
isTagging: false,
|
||||||
|
type: "bookmark-added",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await observer.handlePlacesEvent(args);
|
await observer.handlePlacesEvent(args);
|
||||||
|
@ -885,6 +897,117 @@ describe("PlacesFeed", () => {
|
||||||
assert.notCalled(dispatch);
|
assert.notCalled(dispatch);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe("#bookmark-removed", () => {
|
||||||
|
it("should ignore events that are not of TYPE_BOOKMARK", async () => {
|
||||||
|
const args = [
|
||||||
|
{
|
||||||
|
id: null,
|
||||||
|
parentId: null,
|
||||||
|
index: null,
|
||||||
|
itemType: "nottypebookmark",
|
||||||
|
url: null,
|
||||||
|
guid: "123foo",
|
||||||
|
parentGuid: "",
|
||||||
|
source: SOURCES.DEFAULT,
|
||||||
|
type: "bookmark-removed",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await observer.handlePlacesEvent(args);
|
||||||
|
assert.notCalled(dispatch);
|
||||||
|
});
|
||||||
|
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has SYNC source", async () => {
|
||||||
|
const args = [
|
||||||
|
{
|
||||||
|
id: null,
|
||||||
|
parentId: null,
|
||||||
|
index: null,
|
||||||
|
itemType: TYPE_BOOKMARK,
|
||||||
|
url: "foo.com",
|
||||||
|
guid: "123foo",
|
||||||
|
parentGuid: "",
|
||||||
|
source: SOURCES.SYNC,
|
||||||
|
type: "bookmark-removed",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await observer.handlePlacesEvent(args);
|
||||||
|
|
||||||
|
assert.notCalled(dispatch);
|
||||||
|
});
|
||||||
|
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has IMPORT source", async () => {
|
||||||
|
const args = [
|
||||||
|
{
|
||||||
|
id: null,
|
||||||
|
parentId: null,
|
||||||
|
index: null,
|
||||||
|
itemType: TYPE_BOOKMARK,
|
||||||
|
url: "foo.com",
|
||||||
|
guid: "123foo",
|
||||||
|
parentGuid: "",
|
||||||
|
source: SOURCES.IMPORT,
|
||||||
|
type: "bookmark-removed",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await observer.handlePlacesEvent(args);
|
||||||
|
|
||||||
|
assert.notCalled(dispatch);
|
||||||
|
});
|
||||||
|
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has RESTORE source", async () => {
|
||||||
|
const args = [
|
||||||
|
{
|
||||||
|
id: null,
|
||||||
|
parentId: null,
|
||||||
|
index: null,
|
||||||
|
itemType: TYPE_BOOKMARK,
|
||||||
|
url: "foo.com",
|
||||||
|
guid: "123foo",
|
||||||
|
parentGuid: "",
|
||||||
|
source: SOURCES.RESTORE,
|
||||||
|
type: "bookmark-removed",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await observer.handlePlacesEvent(args);
|
||||||
|
|
||||||
|
assert.notCalled(dispatch);
|
||||||
|
});
|
||||||
|
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has RESTORE_ON_STARTUP source", async () => {
|
||||||
|
const args = [
|
||||||
|
{
|
||||||
|
id: null,
|
||||||
|
parentId: null,
|
||||||
|
index: null,
|
||||||
|
itemType: TYPE_BOOKMARK,
|
||||||
|
url: "foo.com",
|
||||||
|
guid: "123foo",
|
||||||
|
parentGuid: "",
|
||||||
|
source: SOURCES.RESTORE_ON_STARTUP,
|
||||||
|
type: "bookmark-removed",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await observer.handlePlacesEvent(args);
|
||||||
|
|
||||||
|
assert.notCalled(dispatch);
|
||||||
|
});
|
||||||
|
it("should dispatch a PLACES_BOOKMARK_REMOVED action with the right URL and bookmarkGuid", async () => {
|
||||||
|
const args = [
|
||||||
|
{
|
||||||
|
id: null,
|
||||||
|
parentId: null,
|
||||||
|
index: null,
|
||||||
|
itemType: TYPE_BOOKMARK,
|
||||||
|
url: "foo.com",
|
||||||
|
guid: "123foo",
|
||||||
|
parentGuid: "",
|
||||||
|
source: SOURCES.DEFAULT,
|
||||||
|
type: "bookmark-removed",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await observer.handlePlacesEvent(args);
|
||||||
|
assert.calledWith(dispatch, {
|
||||||
|
type: at.PLACES_BOOKMARK_REMOVED,
|
||||||
|
data: { bookmarkGuid: "123foo", url: "foo.com" },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("BookmarksObserver", () => {
|
describe("BookmarksObserver", () => {
|
||||||
|
@ -897,97 +1020,6 @@ describe("PlacesFeed", () => {
|
||||||
it("should have a QueryInterface property", () => {
|
it("should have a QueryInterface property", () => {
|
||||||
assert.property(observer, "QueryInterface");
|
assert.property(observer, "QueryInterface");
|
||||||
});
|
});
|
||||||
describe("#onItemRemoved", () => {
|
|
||||||
it("should ignore events that are not of TYPE_BOOKMARK", async () => {
|
|
||||||
await observer.onItemRemoved(
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
"nottypebookmark",
|
|
||||||
null,
|
|
||||||
"123foo",
|
|
||||||
"",
|
|
||||||
SOURCES.DEFAULT
|
|
||||||
);
|
|
||||||
assert.notCalled(dispatch);
|
|
||||||
});
|
|
||||||
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has SYNC source", async () => {
|
|
||||||
const args = [
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
TYPE_BOOKMARK,
|
|
||||||
{ spec: "foo.com" },
|
|
||||||
"123foo",
|
|
||||||
"",
|
|
||||||
SOURCES.SYNC,
|
|
||||||
];
|
|
||||||
await observer.onItemRemoved(...args);
|
|
||||||
|
|
||||||
assert.notCalled(dispatch);
|
|
||||||
});
|
|
||||||
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has IMPORT source", async () => {
|
|
||||||
const args = [
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
TYPE_BOOKMARK,
|
|
||||||
{ spec: "foo.com" },
|
|
||||||
"123foo",
|
|
||||||
"",
|
|
||||||
SOURCES.IMPORT,
|
|
||||||
];
|
|
||||||
await observer.onItemRemoved(...args);
|
|
||||||
|
|
||||||
assert.notCalled(dispatch);
|
|
||||||
});
|
|
||||||
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has RESTORE source", async () => {
|
|
||||||
const args = [
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
TYPE_BOOKMARK,
|
|
||||||
{ spec: "foo.com" },
|
|
||||||
"123foo",
|
|
||||||
"",
|
|
||||||
SOURCES.RESTORE,
|
|
||||||
];
|
|
||||||
await observer.onItemRemoved(...args);
|
|
||||||
|
|
||||||
assert.notCalled(dispatch);
|
|
||||||
});
|
|
||||||
it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has RESTORE_ON_STARTUP source", async () => {
|
|
||||||
const args = [
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
TYPE_BOOKMARK,
|
|
||||||
{ spec: "foo.com" },
|
|
||||||
"123foo",
|
|
||||||
"",
|
|
||||||
SOURCES.RESTORE_ON_STARTUP,
|
|
||||||
];
|
|
||||||
await observer.onItemRemoved(...args);
|
|
||||||
|
|
||||||
assert.notCalled(dispatch);
|
|
||||||
});
|
|
||||||
it("should dispatch a PLACES_BOOKMARK_REMOVED action with the right URL and bookmarkGuid", () => {
|
|
||||||
observer.onItemRemoved(
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
TYPE_BOOKMARK,
|
|
||||||
{ spec: "foo.com" },
|
|
||||||
"123foo",
|
|
||||||
"",
|
|
||||||
SOURCES.DEFAULT
|
|
||||||
);
|
|
||||||
assert.calledWith(dispatch, {
|
|
||||||
type: at.PLACES_BOOKMARK_REMOVED,
|
|
||||||
data: { bookmarkGuid: "123foo", url: "foo.com" },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("Other empty methods (to keep code coverage happy)", () => {
|
describe("Other empty methods (to keep code coverage happy)", () => {
|
||||||
it("should have a various empty functions for xpconnect happiness", () => {
|
it("should have a various empty functions for xpconnect happiness", () => {
|
||||||
observer.onBeginUpdateBatch();
|
observer.onBeginUpdateBatch();
|
||||||
|
|
|
@ -1240,7 +1240,6 @@ var gEditItemOverlay = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onItemRemoved() {},
|
|
||||||
onBeginUpdateBatch() {},
|
onBeginUpdateBatch() {},
|
||||||
onEndUpdateBatch() {},
|
onEndUpdateBatch() {},
|
||||||
onItemVisited() {},
|
onItemVisited() {},
|
||||||
|
|
|
@ -6,8 +6,9 @@ const TEST_URL =
|
||||||
function closeHandler(dialogWin) {
|
function closeHandler(dialogWin) {
|
||||||
let savedItemId = dialogWin.gEditItemOverlay.itemId;
|
let savedItemId = dialogWin.gEditItemOverlay.itemId;
|
||||||
return PlacesTestUtils.waitForNotification(
|
return PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
itemId => itemId === savedItemId
|
events => events.some(event => event.id === savedItemId),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,9 @@ add_task(async function() {
|
||||||
let savedItemId = dialog.gEditItemOverlay.itemId;
|
let savedItemId = dialog.gEditItemOverlay.itemId;
|
||||||
Assert.greater(savedItemId, 0, "Found the itemId");
|
Assert.greater(savedItemId, 0, "Found the itemId");
|
||||||
return PlacesTestUtils.waitForNotification(
|
return PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
id => id === savedItemId
|
events => events.some(event => event.id === savedItemId),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -67,9 +67,22 @@ add_task(async function() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let promiseTagRemoveNotification = PlacesTestUtils.waitForNotification(
|
||||||
|
"bookmark-removed",
|
||||||
|
events =>
|
||||||
|
events.some(
|
||||||
|
event => event.parentGuid == PlacesUtils.bookmarks.tagsGuid
|
||||||
|
),
|
||||||
|
"places"
|
||||||
|
);
|
||||||
fillBookmarkTextField("editBMPanel_namePicker", "tag2", dialogWin);
|
fillBookmarkTextField("editBMPanel_namePicker", "tag2", dialogWin);
|
||||||
|
|
||||||
await promiseTagChangeNotification;
|
await promiseTagChangeNotification;
|
||||||
|
await promiseTagRemoveNotification;
|
||||||
|
|
||||||
|
// Although we have received the expected notifications, we need
|
||||||
|
// to let everything resolve to ensure the UI is updated.
|
||||||
|
await new Promise(resolve => Services.tm.dispatchToMainThread(resolve));
|
||||||
|
|
||||||
Assert.equal(
|
Assert.equal(
|
||||||
namepicker.value,
|
namepicker.value,
|
||||||
|
|
|
@ -126,13 +126,17 @@ async function test_bookmarks_popup({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let onItemRemovedPromise = Promise.resolve();
|
let bookmarkRemovedPromise = Promise.resolve();
|
||||||
if (isBookmarkRemoved) {
|
if (isBookmarkRemoved) {
|
||||||
onItemRemovedPromise = PlacesTestUtils.waitForNotification(
|
bookmarkRemovedPromise = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(id, parentId, index, type, uri, guid, parentGuid) =>
|
events =>
|
||||||
parentGuid == PlacesUtils.bookmarks.unfiledGuid &&
|
events.some(
|
||||||
TEST_URL == uri.spec
|
event =>
|
||||||
|
event.parentGuid == PlacesUtils.bookmarks.unfiledGuid &&
|
||||||
|
TEST_URL == event.url
|
||||||
|
),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +144,7 @@ async function test_bookmarks_popup({
|
||||||
if (popupHideFn) {
|
if (popupHideFn) {
|
||||||
await popupHideFn();
|
await popupHideFn();
|
||||||
}
|
}
|
||||||
await Promise.all([hiddenPromise, onItemRemovedPromise]);
|
await Promise.all([hiddenPromise, bookmarkRemovedPromise]);
|
||||||
|
|
||||||
Assert.equal(
|
Assert.equal(
|
||||||
bookmarkStar.hasAttribute("starred"),
|
bookmarkStar.hasAttribute("starred"),
|
||||||
|
|
|
@ -401,9 +401,9 @@ gTests.push({
|
||||||
|
|
||||||
self._cleanShutdown = true;
|
self._cleanShutdown = true;
|
||||||
self._removeObserver = PlacesTestUtils.waitForNotification(
|
self._removeObserver = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(itemId, parentId, index, type, uri, guid) =>
|
events => events.some(eve => eve.guid == self._bookmarkGuid),
|
||||||
guid == self._bookmarkGuid
|
"places"
|
||||||
);
|
);
|
||||||
|
|
||||||
self.window.document
|
self.window.document
|
||||||
|
|
|
@ -119,6 +119,9 @@ add_task(async function() {
|
||||||
// Remove the second bookmark, then nuke some of the tags.
|
// Remove the second bookmark, then nuke some of the tags.
|
||||||
await PlacesUtils.bookmarks.remove(bm2);
|
await PlacesUtils.bookmarks.remove(bm2);
|
||||||
|
|
||||||
|
// Allow the tag updates to complete
|
||||||
|
await PlacesTestUtils.promiseAsyncUpdates();
|
||||||
|
|
||||||
// Doing this backwords tests more interesting paths.
|
// Doing this backwords tests more interesting paths.
|
||||||
for (let i = tags.length - 1; i >= 0; i -= 2) {
|
for (let i = tags.length - 1; i >= 0; i -= 2) {
|
||||||
tagsSelector.selectedIndex = i;
|
tagsSelector.selectedIndex = i;
|
||||||
|
|
|
@ -8,7 +8,6 @@ add_task(async function() {
|
||||||
PlacesUtils.bookmarks.addObserver({
|
PlacesUtils.bookmarks.addObserver({
|
||||||
onBeginUpdateBatch() {},
|
onBeginUpdateBatch() {},
|
||||||
onEndUpdateBatch() {},
|
onEndUpdateBatch() {},
|
||||||
onItemRemoved() {},
|
|
||||||
onItemVisited() {},
|
onItemVisited() {},
|
||||||
onItemMoved() {},
|
onItemMoved() {},
|
||||||
onItemChanged(id, property, isAnno, value) {
|
onItemChanged(id, property, isAnno, value) {
|
||||||
|
|
|
@ -177,8 +177,9 @@ add_task(async function test_query_on_toolbar() {
|
||||||
|
|
||||||
// Execute the delete command and check bookmark has been removed.
|
// Execute the delete command and check bookmark has been removed.
|
||||||
let promiseItemRemoved = PlacesTestUtils.waitForNotification(
|
let promiseItemRemoved = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(...args) => query.guid == args[5]
|
events => events.some(event => query.guid == event.guid),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
PO._places.controller.doCommand("cmd_delete");
|
PO._places.controller.doCommand("cmd_delete");
|
||||||
await promiseItemRemoved;
|
await promiseItemRemoved;
|
||||||
|
|
|
@ -69,9 +69,9 @@ add_task(async function test_create_and_remove_bookmarks() {
|
||||||
"Delete command is enabled"
|
"Delete command is enabled"
|
||||||
);
|
);
|
||||||
let promiseItemRemovedNotification = PlacesTestUtils.waitForNotification(
|
let promiseItemRemovedNotification = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(itemId, parentId, index, type, uri, guid) =>
|
events => events.some(event => event.guid == folderNode.bookmarkGuid),
|
||||||
guid == folderNode.bookmarkGuid
|
"places"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Execute the delete command and check bookmark has been removed.
|
// Execute the delete command and check bookmark has been removed.
|
||||||
|
|
|
@ -54,8 +54,9 @@ add_task(async function test_remove_bookmark_from_toolbar() {
|
||||||
let contextMenuDeleteItem = document.getElementById("placesContext_delete");
|
let contextMenuDeleteItem = document.getElementById("placesContext_delete");
|
||||||
|
|
||||||
let removePromise = PlacesTestUtils.waitForNotification(
|
let removePromise = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(itemId, parentId, index, type, uri, guid) => uri.spec == TEST_URL
|
events => events.some(event => event.url == TEST_URL),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
|
|
||||||
EventUtils.synthesizeMouseAtCenter(contextMenuDeleteItem, {});
|
EventUtils.synthesizeMouseAtCenter(contextMenuDeleteItem, {});
|
||||||
|
@ -138,8 +139,9 @@ add_task(async function test_remove_bookmark_from_library() {
|
||||||
);
|
);
|
||||||
|
|
||||||
let removePromise = PlacesTestUtils.waitForNotification(
|
let removePromise = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(itemId, parentId, index, type, uri, guid) => uri.spec == uris[0]
|
events => events.some(event => event.url == uris[0]),
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
EventUtils.synthesizeMouseAtCenter(contextMenuDeleteItem, {}, library);
|
EventUtils.synthesizeMouseAtCenter(contextMenuDeleteItem, {}, library);
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ add_task(async function test() {
|
||||||
);
|
);
|
||||||
PlacesUtils.bookmarks.addObserver(bookmarksObserver);
|
PlacesUtils.bookmarks.addObserver(bookmarksObserver);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
bookmarksObserver.handlePlacesEvents
|
bookmarksObserver.handlePlacesEvents
|
||||||
);
|
);
|
||||||
var addedBookmarks = [];
|
var addedBookmarks = [];
|
||||||
|
@ -152,7 +152,7 @@ add_task(async function test() {
|
||||||
// Remove observers.
|
// Remove observers.
|
||||||
PlacesUtils.bookmarks.removeObserver(bookmarksObserver);
|
PlacesUtils.bookmarks.removeObserver(bookmarksObserver);
|
||||||
PlacesUtils.observers.removeListener(
|
PlacesUtils.observers.removeListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
bookmarksObserver.handlePlacesEvents
|
bookmarksObserver.handlePlacesEvents
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -173,13 +173,21 @@ var bookmarksObserver = {
|
||||||
QueryInterface: ChromeUtils.generateQI([Ci.nsINavBookmarkObserver]),
|
QueryInterface: ChromeUtils.generateQI([Ci.nsINavBookmarkObserver]),
|
||||||
|
|
||||||
handlePlacesEvents(events) {
|
handlePlacesEvents(events) {
|
||||||
for (let { parentGuid, guid, index } of events) {
|
for (let { type, parentGuid, guid, index } of events) {
|
||||||
this._notifications.push(["assertItemAdded", parentGuid, guid, index]);
|
switch (type) {
|
||||||
}
|
case "bookmark-added":
|
||||||
},
|
this._notifications.push([
|
||||||
|
"assertItemAdded",
|
||||||
onItemRemoved(itemId, folderId, index, itemType, uri, guid, parentGuid) {
|
parentGuid,
|
||||||
|
guid,
|
||||||
|
index,
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case "bookmark-removed":
|
||||||
this._notifications.push(["assertItemRemoved", parentGuid, guid]);
|
this._notifications.push(["assertItemRemoved", parentGuid, guid]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onItemMoved(
|
onItemMoved(
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_PlacesBookmarkRemoved_h
|
||||||
|
#define mozilla_dom_PlacesBookmarkRemoved_h
|
||||||
|
|
||||||
|
#include "mozilla/dom/PlacesBookmark.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
class PlacesBookmarkRemoved final : public PlacesBookmark {
|
||||||
|
public:
|
||||||
|
explicit PlacesBookmarkRemoved()
|
||||||
|
: PlacesBookmark(PlacesEventType::Bookmark_removed) {}
|
||||||
|
|
||||||
|
static already_AddRefed<PlacesBookmarkRemoved> Constructor(
|
||||||
|
const GlobalObject& aGlobal, const PlacesBookmarkRemovedInit& aInitDict) {
|
||||||
|
RefPtr<PlacesBookmarkRemoved> event = new PlacesBookmarkRemoved();
|
||||||
|
event->mItemType = aInitDict.mItemType;
|
||||||
|
event->mId = aInitDict.mId;
|
||||||
|
event->mParentId = aInitDict.mParentId;
|
||||||
|
event->mIndex = aInitDict.mIndex;
|
||||||
|
event->mUrl = aInitDict.mUrl;
|
||||||
|
event->mGuid = aInitDict.mGuid;
|
||||||
|
event->mParentGuid = aInitDict.mParentGuid;
|
||||||
|
event->mSource = aInitDict.mSource;
|
||||||
|
event->mIsTagging = aInitDict.mIsTagging;
|
||||||
|
event->mIsDescendantRemoval = aInitDict.mIsDescendantRemoval;
|
||||||
|
return event.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject* WrapObject(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> aGivenProto) override {
|
||||||
|
return PlacesBookmarkRemoved_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
|
}
|
||||||
|
|
||||||
|
const PlacesBookmarkRemoved* AsPlacesBookmarkRemoved() const override {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Index() { return mIndex; }
|
||||||
|
bool IsDescendantRemoval() { return mIsDescendantRemoval; }
|
||||||
|
|
||||||
|
int32_t mIndex;
|
||||||
|
bool mIsDescendantRemoval;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~PlacesBookmarkRemoved() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
|
@ -37,6 +37,9 @@ class PlacesEvent : public nsWrapperCache {
|
||||||
virtual const PlacesBookmarkAddition* AsPlacesBookmarkAddition() const {
|
virtual const PlacesBookmarkAddition* AsPlacesBookmarkAddition() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
virtual const PlacesBookmarkRemoved* AsPlacesBookmarkRemoved() const {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~PlacesEvent() = default;
|
virtual ~PlacesEvent() = default;
|
||||||
|
|
|
@ -211,6 +211,7 @@ EXPORTS.mozilla.dom += [
|
||||||
'ParentProcessMessageManager.h',
|
'ParentProcessMessageManager.h',
|
||||||
'PlacesBookmark.h',
|
'PlacesBookmark.h',
|
||||||
'PlacesBookmarkAddition.h',
|
'PlacesBookmarkAddition.h',
|
||||||
|
'PlacesBookmarkRemoved.h',
|
||||||
'PlacesEvent.h',
|
'PlacesEvent.h',
|
||||||
'PlacesObservers.h',
|
'PlacesObservers.h',
|
||||||
'PlacesVisit.h',
|
'PlacesVisit.h',
|
||||||
|
|
|
@ -10,6 +10,11 @@ enum PlacesEventType {
|
||||||
* (or a bookmark folder/separator) is created.
|
* (or a bookmark folder/separator) is created.
|
||||||
*/
|
*/
|
||||||
"bookmark-added",
|
"bookmark-added",
|
||||||
|
/**
|
||||||
|
* data: PlacesBookmarkRemoved. Fired whenever a bookmark
|
||||||
|
* (or a bookmark folder/separator) is created.
|
||||||
|
*/
|
||||||
|
"bookmark-removed",
|
||||||
};
|
};
|
||||||
|
|
||||||
[ChromeOnly, Exposed=Window]
|
[ChromeOnly, Exposed=Window]
|
||||||
|
@ -154,3 +159,30 @@ interface PlacesBookmarkAddition : PlacesBookmark {
|
||||||
*/
|
*/
|
||||||
readonly attribute unsigned long long dateAdded;
|
readonly attribute unsigned long long dateAdded;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dictionary PlacesBookmarkRemovedInit {
|
||||||
|
required long long id;
|
||||||
|
required long long parentId;
|
||||||
|
required unsigned short itemType;
|
||||||
|
required DOMString url;
|
||||||
|
required ByteString guid;
|
||||||
|
required ByteString parentGuid;
|
||||||
|
required unsigned short source;
|
||||||
|
required long index;
|
||||||
|
required boolean isTagging;
|
||||||
|
boolean isDescendantRemoval = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
[ChromeOnly, Exposed=Window]
|
||||||
|
interface PlacesBookmarkRemoved : PlacesBookmark {
|
||||||
|
constructor(PlacesBookmarkRemovedInit initDict);
|
||||||
|
/**
|
||||||
|
* The item's index in the folder.
|
||||||
|
*/
|
||||||
|
readonly attribute long index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item is a descendant of an item whose notification has been sent out.
|
||||||
|
*/
|
||||||
|
readonly attribute boolean isDescendantRemoval;
|
||||||
|
};
|
||||||
|
|
|
@ -1400,7 +1400,10 @@ BookmarksTracker.prototype = {
|
||||||
this._placesListener = new PlacesWeakCallbackWrapper(
|
this._placesListener = new PlacesWeakCallbackWrapper(
|
||||||
this.handlePlacesEvents.bind(this)
|
this.handlePlacesEvents.bind(this)
|
||||||
);
|
);
|
||||||
PlacesUtils.observers.addListener(["bookmark-added"], this._placesListener);
|
PlacesUtils.observers.addListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
this._placesListener
|
||||||
|
);
|
||||||
Svc.Obs.add("bookmarks-restore-begin", this);
|
Svc.Obs.add("bookmarks-restore-begin", this);
|
||||||
Svc.Obs.add("bookmarks-restore-success", this);
|
Svc.Obs.add("bookmarks-restore-success", this);
|
||||||
Svc.Obs.add("bookmarks-restore-failed", this);
|
Svc.Obs.add("bookmarks-restore-failed", this);
|
||||||
|
@ -1409,7 +1412,7 @@ BookmarksTracker.prototype = {
|
||||||
onStop() {
|
onStop() {
|
||||||
PlacesUtils.bookmarks.removeObserver(this);
|
PlacesUtils.bookmarks.removeObserver(this);
|
||||||
PlacesUtils.observers.removeListener(
|
PlacesUtils.observers.removeListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this._placesListener
|
this._placesListener
|
||||||
);
|
);
|
||||||
Svc.Obs.remove("bookmarks-restore-begin", this);
|
Svc.Obs.remove("bookmarks-restore-begin", this);
|
||||||
|
@ -1483,22 +1486,25 @@ BookmarksTracker.prototype = {
|
||||||
|
|
||||||
handlePlacesEvents(events) {
|
handlePlacesEvents(events) {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added":
|
||||||
if (IGNORED_SOURCES.includes(event.source)) {
|
if (IGNORED_SOURCES.includes(event.source)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._log.trace("'bookmark-added': " + event.id);
|
this._log.trace("'bookmark-added': " + event.id);
|
||||||
this._upScore();
|
this._upScore();
|
||||||
}
|
break;
|
||||||
},
|
case "bookmark-removed":
|
||||||
|
if (IGNORED_SOURCES.includes(event.source)) {
|
||||||
onItemRemoved(itemId, parentId, index, type, uri, guid, parentGuid, source) {
|
continue;
|
||||||
if (IGNORED_SOURCES.includes(source)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._log.trace("onItemRemoved: " + itemId);
|
this._log.trace("'bookmark-removed': " + event.id);
|
||||||
this._upScore();
|
this._upScore();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// This method is oddly structured, but the idea is to return as quickly as
|
// This method is oddly structured, but the idea is to return as quickly as
|
||||||
|
|
|
@ -1287,26 +1287,24 @@ var Bookmarks = Object.freeze({
|
||||||
// Notify onItemRemoved to listeners.
|
// Notify onItemRemoved to listeners.
|
||||||
for (let item of removeItems) {
|
for (let item of removeItems) {
|
||||||
let observers = PlacesUtils.bookmarks.getObservers();
|
let observers = PlacesUtils.bookmarks.getObservers();
|
||||||
let uri = item.hasOwnProperty("url")
|
|
||||||
? PlacesUtils.toURI(item.url)
|
|
||||||
: null;
|
|
||||||
let isUntagging = item._grandParentId == PlacesUtils.tagsFolderId;
|
let isUntagging = item._grandParentId == PlacesUtils.tagsFolderId;
|
||||||
notify(
|
let url = "";
|
||||||
observers,
|
if (item.type == Bookmarks.TYPE_BOOKMARK) {
|
||||||
"onItemRemoved",
|
url = item.hasOwnProperty("url") ? item.url.href : null;
|
||||||
[
|
}
|
||||||
item._id,
|
let notification = new PlacesBookmarkRemoved({
|
||||||
item._parentId,
|
id: item._id,
|
||||||
item.index,
|
url,
|
||||||
item.type,
|
itemType: item.type,
|
||||||
uri,
|
parentId: item._parentId,
|
||||||
item.guid,
|
index: item.index,
|
||||||
item.parentGuid,
|
guid: item.guid,
|
||||||
options.source,
|
parentGuid: item.parentGuid,
|
||||||
],
|
source: options.source,
|
||||||
{ isTagging: isUntagging }
|
isTagging: isUntagging,
|
||||||
);
|
isDescendantRemoval: false,
|
||||||
|
});
|
||||||
|
PlacesObservers.notifyListeners([notification]);
|
||||||
if (isUntagging) {
|
if (isUntagging) {
|
||||||
for (let entry of await fetchBookmarksByURL(item, {
|
for (let entry of await fetchBookmarksByURL(item, {
|
||||||
concurrent: true,
|
concurrent: true,
|
||||||
|
@ -1823,7 +1821,6 @@ function notify(observers, notification, args = [], information = {}) {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
information.isDescendantRemoval &&
|
information.isDescendantRemoval &&
|
||||||
observer.skipDescendantsOnItemRemoval &&
|
|
||||||
!PlacesUtils.bookmarks.userContentRoots.includes(information.parentGuid)
|
!PlacesUtils.bookmarks.userContentRoots.includes(information.parentGuid)
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -3217,30 +3214,28 @@ var removeFoldersContents = async function(db, folderGuids, options) {
|
||||||
// Notify listeners in reverse order to serve children before parents.
|
// Notify listeners in reverse order to serve children before parents.
|
||||||
let { source = Bookmarks.SOURCES.DEFAULT } = options;
|
let { source = Bookmarks.SOURCES.DEFAULT } = options;
|
||||||
let observers = PlacesUtils.bookmarks.getObservers();
|
let observers = PlacesUtils.bookmarks.getObservers();
|
||||||
|
let notification = [];
|
||||||
for (let item of itemsRemoved.reverse()) {
|
for (let item of itemsRemoved.reverse()) {
|
||||||
let uri = item.hasOwnProperty("url") ? PlacesUtils.toURI(item.url) : null;
|
|
||||||
notify(
|
|
||||||
observers,
|
|
||||||
"onItemRemoved",
|
|
||||||
[
|
|
||||||
item._id,
|
|
||||||
item._parentId,
|
|
||||||
item.index,
|
|
||||||
item.type,
|
|
||||||
uri,
|
|
||||||
item.guid,
|
|
||||||
item.parentGuid,
|
|
||||||
source,
|
|
||||||
],
|
|
||||||
// Notify observers that this item is being
|
|
||||||
// removed as a descendent.
|
|
||||||
{
|
|
||||||
isDescendantRemoval: true,
|
|
||||||
parentGuid: item.parentGuid,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let isUntagging = item._grandParentId == PlacesUtils.tagsFolderId;
|
let isUntagging = item._grandParentId == PlacesUtils.tagsFolderId;
|
||||||
|
let url = "";
|
||||||
|
if (item.type == Bookmarks.TYPE_BOOKMARK) {
|
||||||
|
url = item.hasOwnProperty("url") ? item.url.href : null;
|
||||||
|
}
|
||||||
|
notification = new PlacesBookmarkRemoved({
|
||||||
|
id: item._id,
|
||||||
|
url,
|
||||||
|
parentId: item._parentId,
|
||||||
|
index: item.index,
|
||||||
|
itemType: item.type,
|
||||||
|
guid: item.guid,
|
||||||
|
parentGuid: item.parentGuid,
|
||||||
|
source,
|
||||||
|
isTagging: isUntagging,
|
||||||
|
isDescendantRemoval: !PlacesUtils.bookmarks.userContentRoots.includes(
|
||||||
|
item.parentGuid
|
||||||
|
),
|
||||||
|
});
|
||||||
|
PlacesObservers.notifyListeners([notification]);
|
||||||
if (isUntagging) {
|
if (isUntagging) {
|
||||||
for (let entry of await fetchBookmarksByURL(item, true)) {
|
for (let entry of await fetchBookmarksByURL(item, true)) {
|
||||||
notify(observers, "onItemChanged", [
|
notify(observers, "onItemChanged", [
|
||||||
|
|
|
@ -2925,7 +2925,9 @@ var GuidHelper = {
|
||||||
},
|
},
|
||||||
|
|
||||||
ensureObservingRemovedItems() {
|
ensureObservingRemovedItems() {
|
||||||
if (!("observer" in this)) {
|
if (this.addListeners) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This observers serves two purposes:
|
* This observers serves two purposes:
|
||||||
* (1) Invalidate cached id<->GUID paris on when items are removed.
|
* (1) Invalidate cached id<->GUID paris on when items are removed.
|
||||||
|
@ -2935,39 +2937,30 @@ var GuidHelper = {
|
||||||
*/
|
*/
|
||||||
let listener = events => {
|
let listener = events => {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added":
|
||||||
this.updateCache(event.id, event.guid);
|
this.updateCache(event.id, event.guid);
|
||||||
this.updateCache(event.parentId, event.parentGuid);
|
this.updateCache(event.parentId, event.parentGuid);
|
||||||
|
break;
|
||||||
|
case "bookmark-removed":
|
||||||
|
this.guidsForIds.delete(event.id);
|
||||||
|
this.idsForGuids.delete(event.guid);
|
||||||
|
this.updateCache(event.parentId, event.parentGuid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.observer = {
|
|
||||||
onItemRemoved: (
|
|
||||||
aItemId,
|
|
||||||
aParentId,
|
|
||||||
aIndex,
|
|
||||||
aItemTyep,
|
|
||||||
aURI,
|
|
||||||
aGuid,
|
|
||||||
aParentGuid
|
|
||||||
) => {
|
|
||||||
this.guidsForIds.delete(aItemId);
|
|
||||||
this.idsForGuids.delete(aGuid);
|
|
||||||
this.updateCache(aParentId, aParentGuid);
|
|
||||||
},
|
|
||||||
|
|
||||||
QueryInterface: ChromeUtils.generateQI([Ci.nsINavBookmarkObserver]),
|
this.addListeners = true;
|
||||||
|
PlacesUtils.observers.addListener(
|
||||||
onBeginUpdateBatch() {},
|
["bookmark-added", "bookmark-removed"],
|
||||||
onEndUpdateBatch() {},
|
listener
|
||||||
onItemChanged() {},
|
);
|
||||||
onItemVisited() {},
|
|
||||||
onItemMoved() {},
|
|
||||||
};
|
|
||||||
PlacesUtils.bookmarks.addObserver(this.observer);
|
|
||||||
PlacesUtils.observers.addListener(["bookmark-added"], listener);
|
|
||||||
PlacesUtils.registerShutdownFunction(() => {
|
PlacesUtils.registerShutdownFunction(() => {
|
||||||
PlacesUtils.bookmarks.removeObserver(this.observer);
|
PlacesUtils.observers.removeListener(
|
||||||
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
listener
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,7 +51,6 @@
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["SyncedBookmarksMirror"];
|
var EXPORTED_SYMBOLS = ["SyncedBookmarksMirror"];
|
||||||
|
|
||||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
||||||
const { XPCOMUtils } = ChromeUtils.import(
|
const { XPCOMUtils } = ChromeUtils.import(
|
||||||
"resource://gre/modules/XPCOMUtils.jsm"
|
"resource://gre/modules/XPCOMUtils.jsm"
|
||||||
);
|
);
|
||||||
|
@ -2077,7 +2076,6 @@ class BookmarkObserverRecorder {
|
||||||
this.notifyInStableOrder = notifyInStableOrder;
|
this.notifyInStableOrder = notifyInStableOrder;
|
||||||
this.signal = signal;
|
this.signal = signal;
|
||||||
this.placesEvents = [];
|
this.placesEvents = [];
|
||||||
this.itemRemovedNotifications = [];
|
|
||||||
this.guidChangedArgs = [];
|
this.guidChangedArgs = [];
|
||||||
this.itemMovedArgs = [];
|
this.itemMovedArgs = [];
|
||||||
this.itemChangedArgs = [];
|
this.itemChangedArgs = [];
|
||||||
|
@ -2388,20 +2386,20 @@ class BookmarkObserverRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
noteItemRemoved(info) {
|
noteItemRemoved(info) {
|
||||||
let uri = info.urlHref ? Services.io.newURI(info.urlHref) : null;
|
this.placesEvents.push(
|
||||||
this.itemRemovedNotifications.push({
|
new PlacesBookmarkRemoved({
|
||||||
|
id: info.id,
|
||||||
|
parentId: info.parentId,
|
||||||
|
index: info.position,
|
||||||
|
url: info.urlHref || "",
|
||||||
|
guid: info.guid,
|
||||||
|
parentGuid: info.parentGuid,
|
||||||
|
source: PlacesUtils.bookmarks.SOURCES.SYNC,
|
||||||
|
itemType: info.type,
|
||||||
isTagging: info.isUntagging,
|
isTagging: info.isUntagging,
|
||||||
args: [
|
isDescendantRemoval: false,
|
||||||
info.id,
|
})
|
||||||
info.parentId,
|
);
|
||||||
info.position,
|
|
||||||
info.type,
|
|
||||||
uri,
|
|
||||||
info.guid,
|
|
||||||
info.parentGuid,
|
|
||||||
PlacesUtils.bookmarks.SOURCES.SYNC,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async notifyBookmarkObservers() {
|
async notifyBookmarkObservers() {
|
||||||
|
@ -2410,18 +2408,6 @@ class BookmarkObserverRecorder {
|
||||||
for (let observer of observers) {
|
for (let observer of observers) {
|
||||||
this.notifyObserver(observer, "onBeginUpdateBatch");
|
this.notifyObserver(observer, "onBeginUpdateBatch");
|
||||||
}
|
}
|
||||||
await Async.yieldingForEach(
|
|
||||||
this.itemRemovedNotifications,
|
|
||||||
info => {
|
|
||||||
if (this.signal.aborted) {
|
|
||||||
throw new SyncedBookmarksMirror.InterruptedError(
|
|
||||||
"Interrupted while notifying observers for removed items"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.notifyObserversWithInfo(observers, "onItemRemoved", info);
|
|
||||||
},
|
|
||||||
yieldState
|
|
||||||
);
|
|
||||||
await Async.yieldingForEach(
|
await Async.yieldingForEach(
|
||||||
this.guidChangedArgs,
|
this.guidChangedArgs,
|
||||||
args => {
|
args => {
|
||||||
|
|
|
@ -22,7 +22,7 @@ function TaggingService() {
|
||||||
// Observe bookmarks changes.
|
// Observe bookmarks changes.
|
||||||
PlacesUtils.bookmarks.addObserver(this);
|
PlacesUtils.bookmarks.addObserver(this);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this.handlePlacesEvents
|
this.handlePlacesEvents
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -104,7 +104,6 @@ TaggingService.prototype = {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a proper array of tag objects like { id: number, name: string }.
|
* Makes a proper array of tag objects like { id: number, name: string }.
|
||||||
*
|
*
|
||||||
|
@ -328,7 +327,7 @@ TaggingService.prototype = {
|
||||||
if (aTopic == TOPIC_SHUTDOWN) {
|
if (aTopic == TOPIC_SHUTDOWN) {
|
||||||
PlacesUtils.bookmarks.removeObserver(this);
|
PlacesUtils.bookmarks.removeObserver(this);
|
||||||
PlacesUtils.observers.removeListener(
|
PlacesUtils.observers.removeListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this.handlePlacesEvents
|
this.handlePlacesEvents
|
||||||
);
|
);
|
||||||
Services.obs.removeObserver(this, TOPIC_SHUTDOWN);
|
Services.obs.removeObserver(this, TOPIC_SHUTDOWN);
|
||||||
|
@ -347,7 +346,7 @@ TaggingService.prototype = {
|
||||||
* @returns an array of item ids
|
* @returns an array of item ids
|
||||||
*/
|
*/
|
||||||
_getTaggedItemIdsIfUnbookmarkedURI: function TS__getTaggedItemIdsIfUnbookmarkedURI(
|
_getTaggedItemIdsIfUnbookmarkedURI: function TS__getTaggedItemIdsIfUnbookmarkedURI(
|
||||||
aURI
|
url
|
||||||
) {
|
) {
|
||||||
var itemIds = [];
|
var itemIds = [];
|
||||||
var isBookmarked = false;
|
var isBookmarked = false;
|
||||||
|
@ -360,7 +359,7 @@ TaggingService.prototype = {
|
||||||
FROM moz_bookmarks
|
FROM moz_bookmarks
|
||||||
WHERE fk = (SELECT id FROM moz_places WHERE url_hash = hash(:page_url) AND url = :page_url)`
|
WHERE fk = (SELECT id FROM moz_places WHERE url_hash = hash(:page_url) AND url = :page_url)`
|
||||||
);
|
);
|
||||||
stmt.params.page_url = aURI.spec;
|
stmt.params.page_url = url;
|
||||||
try {
|
try {
|
||||||
while (stmt.executeStep() && !isBookmarked) {
|
while (stmt.executeStep() && !isBookmarked) {
|
||||||
if (this._tagFolders[stmt.row.parent]) {
|
if (this._tagFolders[stmt.row.parent]) {
|
||||||
|
@ -380,6 +379,8 @@ TaggingService.prototype = {
|
||||||
|
|
||||||
handlePlacesEvents(events) {
|
handlePlacesEvents(events) {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added":
|
||||||
if (
|
if (
|
||||||
!event.isTagging ||
|
!event.isTagging ||
|
||||||
event.itemType != PlacesUtils.bookmarks.TYPE_FOLDER
|
event.itemType != PlacesUtils.bookmarks.TYPE_FOLDER
|
||||||
|
@ -388,37 +389,36 @@ TaggingService.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this._tagFolders[event.id] = event.title;
|
this._tagFolders[event.id] = event.title;
|
||||||
}
|
break;
|
||||||
},
|
case "bookmark-removed":
|
||||||
|
|
||||||
// nsINavBookmarkObserver
|
|
||||||
onItemRemoved: function TS_onItemRemoved(
|
|
||||||
aItemId,
|
|
||||||
aFolderId,
|
|
||||||
aIndex,
|
|
||||||
aItemType,
|
|
||||||
aURI,
|
|
||||||
aGuid,
|
|
||||||
aParentGuid,
|
|
||||||
aSource
|
|
||||||
) {
|
|
||||||
// Item is a tag folder.
|
// Item is a tag folder.
|
||||||
if (aFolderId == PlacesUtils.tagsFolderId && this._tagFolders[aItemId]) {
|
if (
|
||||||
delete this._tagFolders[aItemId];
|
event.parentId == PlacesUtils.tagsFolderId &&
|
||||||
} else if (aURI && !this._tagFolders[aFolderId]) {
|
this._tagFolders[event.id]
|
||||||
|
) {
|
||||||
|
delete this._tagFolders[event.id];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.tm.dispatchToMainThread(() => {
|
||||||
|
if (event.url && !this._tagFolders[event.parentId]) {
|
||||||
// Item is a bookmark that was removed from a non-tag folder.
|
// Item is a bookmark that was removed from a non-tag folder.
|
||||||
// If the only bookmark items now associated with the bookmark's URI are
|
// If the only bookmark items now associated with the bookmark's URI are
|
||||||
// contained in tag folders, the URI is no longer properly bookmarked, so
|
// contained in tag folders, the URI is no longer properly bookmarked, so
|
||||||
// untag it.
|
// untag it.
|
||||||
let itemIds = this._getTaggedItemIdsIfUnbookmarkedURI(aURI);
|
let itemIds = this._getTaggedItemIdsIfUnbookmarkedURI(event.url);
|
||||||
for (let i = 0; i < itemIds.length; i++) {
|
for (let i = 0; i < itemIds.length; i++) {
|
||||||
try {
|
try {
|
||||||
PlacesUtils.bookmarks.removeItem(itemIds[i], aSource);
|
PlacesUtils.bookmarks.removeItem(itemIds[i], event.source);
|
||||||
} catch (ex) {}
|
} catch (ex) {}
|
||||||
}
|
}
|
||||||
} else if (aURI && this._tagFolders[aFolderId]) {
|
} else if (event.url && this._tagFolders[event.parentId]) {
|
||||||
// Item is a tag entry. If this was the last entry for this tag, remove it.
|
// Item is a tag entry. If this was the last entry for this tag, remove it.
|
||||||
this._removeTagIfEmpty(aFolderId, aSource);
|
this._removeTagIfEmpty(event.parentId, event.source);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,6 @@ interface nsINavBookmarkObserver : nsISupports
|
||||||
*/
|
*/
|
||||||
readonly attribute boolean skipTags;
|
readonly attribute boolean skipTags;
|
||||||
|
|
||||||
/*
|
|
||||||
* This observer should not be called for descendants when the parent is removed.
|
|
||||||
* For example when revmoing a folder containing bookmarks.
|
|
||||||
*/
|
|
||||||
readonly attribute boolean skipDescendantsOnItemRemoval;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies that a batch transaction has started.
|
* Notifies that a batch transaction has started.
|
||||||
* Other notifications will be sent during the batch, but the observer is
|
* Other notifications will be sent during the batch, but the observer is
|
||||||
|
@ -42,40 +36,6 @@ interface nsINavBookmarkObserver : nsISupports
|
||||||
*/
|
*/
|
||||||
void onEndUpdateBatch();
|
void onEndUpdateBatch();
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies that an item was removed. Called after the actual remove took
|
|
||||||
* place.
|
|
||||||
* When an item is removed, all the items following it in the same folder
|
|
||||||
* will have their index shifted down, but no additional notifications will
|
|
||||||
* be sent.
|
|
||||||
*
|
|
||||||
* @param aItemId
|
|
||||||
* The id of the item that was removed.
|
|
||||||
* @param aParentId
|
|
||||||
* The id of the folder from which the item was removed.
|
|
||||||
* @param aIndex
|
|
||||||
* The bookmark's index in the folder.
|
|
||||||
* @param aItemType
|
|
||||||
* The type of the item to be removed (see TYPE_* constants below).
|
|
||||||
* @param aURI
|
|
||||||
* The URI of the added item if it was TYPE_BOOKMARK, null otherwise.
|
|
||||||
* @param aGuid
|
|
||||||
* The unique ID associated with the item.
|
|
||||||
* @param aParentGuid
|
|
||||||
* The unique ID associated with the item's parent.
|
|
||||||
* @param aSource
|
|
||||||
* A change source constant from nsINavBookmarksService::SOURCE_*,
|
|
||||||
* passed to the method that notifies the observer.
|
|
||||||
*/
|
|
||||||
void onItemRemoved(in long long aItemId,
|
|
||||||
in long long aParentId,
|
|
||||||
in long aIndex,
|
|
||||||
in unsigned short aItemType,
|
|
||||||
in nsIURI aURI,
|
|
||||||
in ACString aGuid,
|
|
||||||
in ACString aParentGuid,
|
|
||||||
in unsigned short aSource);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies that an item's information has changed. This will be called
|
* Notifies that an item's information has changed. This will be called
|
||||||
* whenever any attributes like "title" are changed.
|
* whenever any attributes like "title" are changed.
|
||||||
|
@ -359,6 +319,7 @@ interface nsINavBookmarksService : nsISupports
|
||||||
* The change source, forwarded to all bookmark observers. Defaults
|
* The change source, forwarded to all bookmark observers. Defaults
|
||||||
* to SOURCE_DEFAULT.
|
* to SOURCE_DEFAULT.
|
||||||
*/
|
*/
|
||||||
|
[can_run_script]
|
||||||
void removeItem(in long long aItemId, [optional] in unsigned short aSource);
|
void removeItem(in long long aItemId, [optional] in unsigned short aSource);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/storage.h"
|
#include "mozilla/storage.h"
|
||||||
#include "mozilla/dom/PlacesBookmarkAddition.h"
|
#include "mozilla/dom/PlacesBookmarkAddition.h"
|
||||||
|
#include "mozilla/dom/PlacesBookmarkRemoved.h"
|
||||||
#include "mozilla/dom/PlacesObservers.h"
|
#include "mozilla/dom/PlacesObservers.h"
|
||||||
#include "mozilla/dom/PlacesVisit.h"
|
#include "mozilla/dom/PlacesVisit.h"
|
||||||
|
|
||||||
|
@ -59,11 +60,6 @@ bool SkipTags(nsCOMPtr<nsINavBookmarkObserver> obs) {
|
||||||
(void)obs->GetSkipTags(&skipTags);
|
(void)obs->GetSkipTags(&skipTags);
|
||||||
return skipTags;
|
return skipTags;
|
||||||
}
|
}
|
||||||
bool SkipDescendants(nsCOMPtr<nsINavBookmarkObserver> obs) {
|
|
||||||
bool skipDescendantsOnItemRemoval = false;
|
|
||||||
(void)obs->GetSkipDescendantsOnItemRemoval(&skipDescendantsOnItemRemoval);
|
|
||||||
return skipDescendantsOnItemRemoval;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Method, typename DataType>
|
template <typename Method, typename DataType>
|
||||||
class AsyncGetBookmarksForURI : public AsyncStatementCallback {
|
class AsyncGetBookmarksForURI : public AsyncStatementCallback {
|
||||||
|
@ -643,14 +639,27 @@ nsNavBookmarks::RemoveItem(int64_t aItemId, uint16_t aSource) {
|
||||||
NS_WARNING_ASSERTION(uri, "Invalid URI in RemoveItem");
|
NS_WARNING_ASSERTION(uri, "Invalid URI in RemoveItem");
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTIFY_BOOKMARKS_OBSERVERS(
|
if (mCanNotify) {
|
||||||
mCanNotify, mObservers,
|
Sequence<OwningNonNull<PlacesEvent>> events;
|
||||||
SKIP_TAGS(bookmark.parentId == tagsRootId ||
|
RefPtr<PlacesBookmarkRemoved> bookmarkRef = new PlacesBookmarkRemoved();
|
||||||
bookmark.grandParentId == tagsRootId),
|
bookmarkRef->mItemType = bookmark.type;
|
||||||
OnItemRemoved(bookmark.id, bookmark.parentId, bookmark.position,
|
bookmarkRef->mId = bookmark.id;
|
||||||
bookmark.type, uri, bookmark.guid, bookmark.parentGuid,
|
bookmarkRef->mParentId = bookmark.parentId;
|
||||||
aSource));
|
bookmarkRef->mIndex = bookmark.position;
|
||||||
|
if (bookmark.type == TYPE_BOOKMARK) {
|
||||||
|
bookmarkRef->mUrl.Assign(NS_ConvertUTF8toUTF16(bookmark.url));
|
||||||
|
}
|
||||||
|
bookmarkRef->mGuid.Assign(bookmark.guid);
|
||||||
|
bookmarkRef->mParentGuid.Assign(bookmark.parentGuid);
|
||||||
|
bookmarkRef->mSource = aSource;
|
||||||
|
bookmarkRef->mIsTagging =
|
||||||
|
bookmark.parentId == tagsRootId || bookmark.grandParentId == tagsRootId;
|
||||||
|
bookmarkRef->mIsDescendantRemoval = false;
|
||||||
|
bool success = !!events.AppendElement(bookmarkRef.forget(), fallible);
|
||||||
|
MOZ_RELEASE_ASSERT(success);
|
||||||
|
|
||||||
|
PlacesObservers::NotifyListeners(events);
|
||||||
|
}
|
||||||
if (bookmark.type == TYPE_BOOKMARK && bookmark.grandParentId == tagsRootId &&
|
if (bookmark.type == TYPE_BOOKMARK && bookmark.grandParentId == tagsRootId &&
|
||||||
uri) {
|
uri) {
|
||||||
// If the removed bookmark was child of a tag container, notify a tags
|
// If the removed bookmark was child of a tag container, notify a tags
|
||||||
|
@ -930,12 +939,24 @@ nsresult nsNavBookmarks::RemoveFolderChildren(int64_t aFolderId,
|
||||||
NS_WARNING_ASSERTION(uri, "Invalid URI in RemoveFolderChildren");
|
NS_WARNING_ASSERTION(uri, "Invalid URI in RemoveFolderChildren");
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTIFY_BOOKMARKS_OBSERVERS(
|
if (mCanNotify) {
|
||||||
mCanNotify, mObservers,
|
Sequence<OwningNonNull<PlacesEvent>> events;
|
||||||
((child.grandParentId == tagsRootId) ? SkipTags : SkipDescendants),
|
RefPtr<PlacesBookmarkRemoved> bookmark = new PlacesBookmarkRemoved();
|
||||||
OnItemRemoved(child.id, child.parentId, child.position, child.type, uri,
|
bookmark->mItemType = TYPE_BOOKMARK;
|
||||||
child.guid, child.parentGuid, aSource));
|
bookmark->mId = child.id;
|
||||||
|
bookmark->mParentId = child.parentId;
|
||||||
|
bookmark->mIndex = child.position;
|
||||||
|
bookmark->mUrl.Assign(NS_ConvertUTF8toUTF16(child.url));
|
||||||
|
bookmark->mGuid.Assign(child.guid);
|
||||||
|
bookmark->mParentGuid.Assign(child.parentGuid);
|
||||||
|
bookmark->mSource = aSource;
|
||||||
|
bookmark->mIsTagging = (child.grandParentId == tagsRootId);
|
||||||
|
bookmark->mIsDescendantRemoval = (child.grandParentId != tagsRootId);
|
||||||
|
bool success = !!events.AppendElement(bookmark.forget(), fallible);
|
||||||
|
MOZ_RELEASE_ASSERT(success);
|
||||||
|
|
||||||
|
PlacesObservers::NotifyListeners(events);
|
||||||
|
}
|
||||||
if (child.type == TYPE_BOOKMARK && child.grandParentId == tagsRootId &&
|
if (child.type == TYPE_BOOKMARK && child.grandParentId == tagsRootId &&
|
||||||
uri) {
|
uri) {
|
||||||
// If the removed bookmark was a child of a tag container, notify all
|
// If the removed bookmark was a child of a tag container, notify all
|
||||||
|
|
|
@ -302,6 +302,7 @@ class nsNavBookmarks final
|
||||||
int64_t aSyncChangeDelta, int64_t aItemId,
|
int64_t aSyncChangeDelta, int64_t aItemId,
|
||||||
PRTime aValue);
|
PRTime aValue);
|
||||||
|
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult RemoveFolderChildren(int64_t aFolderId, uint16_t aSource);
|
nsresult RemoveFolderChildren(int64_t aFolderId, uint16_t aSource);
|
||||||
|
|
||||||
// Recursive method to build an array of folder's children
|
// Recursive method to build an array of folder's children
|
||||||
|
|
|
@ -1973,13 +1973,6 @@ nsNavHistoryQueryResultNode::GetSkipTags(bool* aSkipTags) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsNavHistoryQueryResultNode::GetSkipDescendantsOnItemRemoval(
|
|
||||||
bool* aSkipDescendantsOnItemRemoval) {
|
|
||||||
*aSkipDescendantsOnItemRemoval = false;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNavHistoryQueryResultNode::OnBeginUpdateBatch() { return NS_OK; }
|
nsNavHistoryQueryResultNode::OnBeginUpdateBatch() { return NS_OK; }
|
||||||
|
|
||||||
|
@ -2451,14 +2444,15 @@ nsresult nsNavHistoryQueryResultNode::OnItemAdded(
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult nsNavHistoryQueryResultNode::OnItemRemoved(
|
||||||
nsNavHistoryQueryResultNode::OnItemRemoved(int64_t aItemId, int64_t aParentId,
|
int64_t aItemId, int64_t aParentFolder, int32_t aIndex, uint16_t aItemType,
|
||||||
int32_t aIndex, uint16_t aItemType,
|
nsIURI* aURI, const nsACString& aGUID, const nsACString& aParentGUID,
|
||||||
nsIURI* aURI,
|
|
||||||
const nsACString& aGUID,
|
|
||||||
const nsACString& aParentGUID,
|
|
||||||
uint16_t aSource) {
|
uint16_t aSource) {
|
||||||
if (aItemType == nsINavBookmarksService::TYPE_BOOKMARK &&
|
if ((aItemType == nsINavBookmarksService::TYPE_BOOKMARK ||
|
||||||
|
(aItemType == nsINavBookmarksService::TYPE_FOLDER &&
|
||||||
|
mOptions->ResultType() ==
|
||||||
|
nsINavHistoryQueryOptions::RESULTS_AS_TAGS_ROOT &&
|
||||||
|
aParentGUID.EqualsLiteral(TAGS_ROOT_GUID))) &&
|
||||||
mLiveUpdate != QUERYUPDATE_SIMPLE && mLiveUpdate != QUERYUPDATE_TIME &&
|
mLiveUpdate != QUERYUPDATE_SIMPLE && mLiveUpdate != QUERYUPDATE_TIME &&
|
||||||
mLiveUpdate != QUERYUPDATE_MOBILEPREF) {
|
mLiveUpdate != QUERYUPDATE_MOBILEPREF) {
|
||||||
nsresult rv = Refresh();
|
nsresult rv = Refresh();
|
||||||
|
@ -3036,13 +3030,6 @@ nsNavHistoryFolderResultNode::GetSkipTags(bool* aSkipTags) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsNavHistoryFolderResultNode::GetSkipDescendantsOnItemRemoval(
|
|
||||||
bool* aSkipDescendantsOnItemRemoval) {
|
|
||||||
*aSkipDescendantsOnItemRemoval = false;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNavHistoryFolderResultNode::OnBeginUpdateBatch() { return NS_OK; }
|
nsNavHistoryFolderResultNode::OnBeginUpdateBatch() { return NS_OK; }
|
||||||
|
|
||||||
|
@ -3167,8 +3154,7 @@ nsresult nsNavHistoryQueryResultNode::OnMobilePrefChanged(bool newValue) {
|
||||||
return RemoveChildAt(existingIndex);
|
return RemoveChildAt(existingIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsresult nsNavHistoryFolderResultNode::OnItemRemoved(
|
||||||
nsNavHistoryFolderResultNode::OnItemRemoved(
|
|
||||||
int64_t aItemId, int64_t aParentFolder, int32_t aIndex, uint16_t aItemType,
|
int64_t aItemId, int64_t aParentFolder, int32_t aIndex, uint16_t aItemType,
|
||||||
nsIURI* aURI, const nsACString& aGUID, const nsACString& aParentGUID,
|
nsIURI* aURI, const nsACString& aGUID, const nsACString& aParentGUID,
|
||||||
uint16_t aSource) {
|
uint16_t aSource) {
|
||||||
|
@ -3539,7 +3525,7 @@ nsNavHistoryResult::~nsNavHistoryResult() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsNavHistoryResult::StopObserving() {
|
void nsNavHistoryResult::StopObserving() {
|
||||||
AutoTArray<PlacesEventType, 2> events;
|
AutoTArray<PlacesEventType, 3> events;
|
||||||
if (mIsBookmarkFolderObserver || mIsAllBookmarksObserver) {
|
if (mIsBookmarkFolderObserver || mIsAllBookmarksObserver) {
|
||||||
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
|
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||||
if (bookmarks) {
|
if (bookmarks) {
|
||||||
|
@ -3548,6 +3534,7 @@ void nsNavHistoryResult::StopObserving() {
|
||||||
mIsAllBookmarksObserver = false;
|
mIsAllBookmarksObserver = false;
|
||||||
}
|
}
|
||||||
events.AppendElement(PlacesEventType::Bookmark_added);
|
events.AppendElement(PlacesEventType::Bookmark_added);
|
||||||
|
events.AppendElement(PlacesEventType::Bookmark_removed);
|
||||||
}
|
}
|
||||||
if (mIsMobilePrefObserver) {
|
if (mIsMobilePrefObserver) {
|
||||||
Preferences::UnregisterCallback(OnMobilePrefChangedCallback,
|
Preferences::UnregisterCallback(OnMobilePrefChangedCallback,
|
||||||
|
@ -3594,8 +3581,9 @@ void nsNavHistoryResult::AddAllBookmarksObserver(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bookmarks->AddObserver(this, true);
|
bookmarks->AddObserver(this, true);
|
||||||
AutoTArray<PlacesEventType, 1> events;
|
AutoTArray<PlacesEventType, 2> events;
|
||||||
events.AppendElement(PlacesEventType::Bookmark_added);
|
events.AppendElement(PlacesEventType::Bookmark_added);
|
||||||
|
events.AppendElement(PlacesEventType::Bookmark_removed);
|
||||||
PlacesObservers::AddListener(events, this);
|
PlacesObservers::AddListener(events, this);
|
||||||
mIsAllBookmarksObserver = true;
|
mIsAllBookmarksObserver = true;
|
||||||
}
|
}
|
||||||
|
@ -3631,8 +3619,9 @@ void nsNavHistoryResult::AddBookmarkFolderObserver(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bookmarks->AddObserver(this, true);
|
bookmarks->AddObserver(this, true);
|
||||||
AutoTArray<PlacesEventType, 1> events;
|
AutoTArray<PlacesEventType, 2> events;
|
||||||
events.AppendElement(PlacesEventType::Bookmark_added);
|
events.AppendElement(PlacesEventType::Bookmark_added);
|
||||||
|
events.AppendElement(PlacesEventType::Bookmark_removed);
|
||||||
PlacesObservers::AddListener(events, this);
|
PlacesObservers::AddListener(events, this);
|
||||||
mIsBookmarkFolderObserver = true;
|
mIsBookmarkFolderObserver = true;
|
||||||
}
|
}
|
||||||
|
@ -3823,13 +3812,6 @@ nsNavHistoryResult::GetSkipTags(bool* aSkipTags) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsNavHistoryResult::GetSkipDescendantsOnItemRemoval(
|
|
||||||
bool* aSkipDescendantsOnItemRemoval) {
|
|
||||||
*aSkipDescendantsOnItemRemoval = true;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNavHistoryResult::OnBeginUpdateBatch() {
|
nsNavHistoryResult::OnBeginUpdateBatch() {
|
||||||
// Since we could be observing both history and bookmarks, it's possible both
|
// Since we could be observing both history and bookmarks, it's possible both
|
||||||
|
@ -3867,26 +3849,6 @@ nsNavHistoryResult::OnEndUpdateBatch() {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsNavHistoryResult::OnItemRemoved(int64_t aItemId, int64_t aParentId,
|
|
||||||
int32_t aIndex, uint16_t aItemType,
|
|
||||||
nsIURI* aURI, const nsACString& aGUID,
|
|
||||||
const nsACString& aParentGUID,
|
|
||||||
uint16_t aSource) {
|
|
||||||
NS_ENSURE_ARG(aItemType != nsINavBookmarksService::TYPE_BOOKMARK || aURI);
|
|
||||||
|
|
||||||
ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(
|
|
||||||
aParentId, OnItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI,
|
|
||||||
aGUID, aParentGUID, aSource));
|
|
||||||
ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnItemRemoved(aItemId, aParentId, aIndex,
|
|
||||||
aItemType, aURI, aGUID,
|
|
||||||
aParentGUID, aSource));
|
|
||||||
ENUMERATE_HISTORY_OBSERVERS(OnItemRemoved(aItemId, aParentId, aIndex,
|
|
||||||
aItemType, aURI, aGUID, aParentGUID,
|
|
||||||
aSource));
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNavHistoryResult::OnItemChanged(
|
nsNavHistoryResult::OnItemChanged(
|
||||||
int64_t aItemId, const nsACString& aProperty, bool aIsAnnotationProperty,
|
int64_t aItemId, const nsACString& aProperty, bool aIsAnnotationProperty,
|
||||||
|
@ -4113,6 +4075,31 @@ void nsNavHistoryResult::HandlePlacesEvent(const PlacesEventSequence& aEvents) {
|
||||||
item->mGuid, item->mParentGuid, item->mSource));
|
item->mGuid, item->mParentGuid, item->mSource));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PlacesEventType::Bookmark_removed: {
|
||||||
|
const dom::PlacesBookmarkRemoved* item =
|
||||||
|
event->AsPlacesBookmarkRemoved();
|
||||||
|
if (NS_WARN_IF(!item)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
|
||||||
|
if (item->mIsDescendantRemoval) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(
|
||||||
|
item->mParentId,
|
||||||
|
OnItemRemoved(item->mId, item->mParentId, item->mIndex,
|
||||||
|
item->mItemType, uri, item->mGuid, item->mParentGuid,
|
||||||
|
item->mSource));
|
||||||
|
ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnItemRemoved(
|
||||||
|
item->mId, item->mParentId, item->mIndex, item->mItemType, uri,
|
||||||
|
item->mGuid, item->mParentGuid, item->mSource));
|
||||||
|
ENUMERATE_HISTORY_OBSERVERS(OnItemRemoved(
|
||||||
|
item->mId, item->mParentId, item->mIndex, item->mItemType, uri,
|
||||||
|
item->mGuid, item->mParentGuid, item->mSource));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
MOZ_ASSERT_UNREACHABLE(
|
MOZ_ASSERT_UNREACHABLE(
|
||||||
"Receive notification of a type not subscribed to.");
|
"Receive notification of a type not subscribed to.");
|
||||||
|
|
|
@ -687,6 +687,12 @@ class nsNavHistoryQueryResultNode final
|
||||||
uint16_t aItemType, nsIURI* aURI, PRTime aDateAdded,
|
uint16_t aItemType, nsIURI* aURI, PRTime aDateAdded,
|
||||||
const nsACString& aGUID, const nsACString& aParentGUID,
|
const nsACString& aGUID, const nsACString& aParentGUID,
|
||||||
uint16_t aSource);
|
uint16_t aSource);
|
||||||
|
|
||||||
|
nsresult OnItemRemoved(int64_t aItemId, int64_t aParentFolder, int32_t aIndex,
|
||||||
|
uint16_t aItemType, nsIURI* aURI,
|
||||||
|
const nsACString& aGUID, const nsACString& aParentGUID,
|
||||||
|
uint16_t aSource);
|
||||||
|
|
||||||
// The internal version has an output aAdded parameter, it is incremented by
|
// The internal version has an output aAdded parameter, it is incremented by
|
||||||
// query nodes when the visited uri belongs to them. If no such query exists,
|
// query nodes when the visited uri belongs to them. If no such query exists,
|
||||||
// the history result creates a new query node dynamically.
|
// the history result creates a new query node dynamically.
|
||||||
|
@ -768,7 +774,10 @@ class nsNavHistoryFolderResultNode final
|
||||||
uint16_t aItemType, nsIURI* aURI, PRTime aDateAdded,
|
uint16_t aItemType, nsIURI* aURI, PRTime aDateAdded,
|
||||||
const nsACString& aGUID, const nsACString& aParentGUID,
|
const nsACString& aGUID, const nsACString& aParentGUID,
|
||||||
uint16_t aSource);
|
uint16_t aSource);
|
||||||
|
nsresult OnItemRemoved(int64_t aItemId, int64_t aParentFolder, int32_t aIndex,
|
||||||
|
uint16_t aItemType, nsIURI* aURI,
|
||||||
|
const nsACString& aGUID, const nsACString& aParentGUID,
|
||||||
|
uint16_t aSource);
|
||||||
virtual void OnRemoving() override;
|
virtual void OnRemoving() override;
|
||||||
|
|
||||||
// this indicates whether the folder contents are valid, they don't go away
|
// this indicates whether the folder contents are valid, they don't go away
|
||||||
|
|
|
@ -417,7 +417,7 @@ var PlacesTestUtils = Object.freeze({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (name == "skipTags" || name == "skipDescendantsOnItemRemoval") {
|
if (name == "skipTags") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return () => false;
|
return () => false;
|
||||||
|
|
|
@ -15,14 +15,10 @@ var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
// Put any other stuff relative to this test folder below.
|
// Put any other stuff relative to this test folder below.
|
||||||
|
|
||||||
function expectNotifications(skipDescendants, checkAllArgs) {
|
function expectNotifications(checkAllArgs) {
|
||||||
let notifications = [];
|
let notifications = [];
|
||||||
let observer = new Proxy(NavBookmarkObserver, {
|
let observer = new Proxy(NavBookmarkObserver, {
|
||||||
get(target, name) {
|
get(target, name) {
|
||||||
if (name == "skipDescendantsOnItemRemoval") {
|
|
||||||
return skipDescendants;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == "check") {
|
if (name == "check") {
|
||||||
PlacesUtils.bookmarks.removeObserver(observer);
|
PlacesUtils.bookmarks.removeObserver(observer);
|
||||||
return expectedNotifications =>
|
return expectedNotifications =>
|
||||||
|
@ -58,10 +54,16 @@ function expectNotifications(skipDescendants, checkAllArgs) {
|
||||||
return observer;
|
return observer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectPlacesObserverNotifications(types, checkAllArgs) {
|
function expectPlacesObserverNotifications(
|
||||||
|
types,
|
||||||
|
checkAllArgs = true,
|
||||||
|
skipDescendants = false
|
||||||
|
) {
|
||||||
let notifications = [];
|
let notifications = [];
|
||||||
let listener = events => {
|
let listener = events => {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added":
|
||||||
notifications.push({
|
notifications.push({
|
||||||
type: event.type,
|
type: event.type,
|
||||||
id: event.id,
|
id: event.id,
|
||||||
|
@ -76,6 +78,36 @@ function expectPlacesObserverNotifications(types, checkAllArgs) {
|
||||||
source: event.source,
|
source: event.source,
|
||||||
isTagging: event.isTagging,
|
isTagging: event.isTagging,
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case "bookmark-removed":
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
skipDescendants &&
|
||||||
|
event.isDescendantRemoval &&
|
||||||
|
!PlacesUtils.bookmarks.userContentRoots.includes(event.parentGuid)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (checkAllArgs) {
|
||||||
|
notifications.push({
|
||||||
|
type: event.type,
|
||||||
|
id: event.id,
|
||||||
|
itemType: event.itemType,
|
||||||
|
parentId: event.parentId,
|
||||||
|
index: event.index,
|
||||||
|
url: event.url || null,
|
||||||
|
guid: event.guid,
|
||||||
|
parentGuid: event.parentGuid,
|
||||||
|
source: event.source,
|
||||||
|
isTagging: event.isTagging,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
notifications.push({
|
||||||
|
type: event.type,
|
||||||
|
guid: event.guid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlacesUtils.observers.addListener(types, listener);
|
PlacesUtils.observers.addListener(types, listener);
|
||||||
|
|
|
@ -184,24 +184,27 @@ add_task(async function test_notifications() {
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
let skipDescendantsObserver = expectNotifications(true);
|
let skipDescendantsObserver = expectPlacesObserverNotifications(
|
||||||
let receiveAllObserver = expectNotifications(false);
|
["bookmark-removed"],
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
let receiveAllObserver = expectPlacesObserverNotifications(
|
||||||
|
["bookmark-removed"],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
await PlacesUtils.bookmarks.eraseEverything();
|
await PlacesUtils.bookmarks.eraseEverything();
|
||||||
|
|
||||||
let expectedNotifications = [
|
let expectedNotifications = [
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: {
|
|
||||||
guid: bms[1].guid,
|
guid: bms[1].guid,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: {
|
|
||||||
guid: bms[0].guid,
|
guid: bms[0].guid,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// If we're skipping descendents, we'll only be notified of the folder.
|
// If we're skipping descendents, we'll only be notified of the folder.
|
||||||
|
@ -209,10 +212,8 @@ add_task(async function test_notifications() {
|
||||||
|
|
||||||
// Note: Items of folders get notified first.
|
// Note: Items of folders get notified first.
|
||||||
expectedNotifications.unshift({
|
expectedNotifications.unshift({
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: {
|
|
||||||
guid: bms[2].guid,
|
guid: bms[2].guid,
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
receiveAllObserver.check(expectedNotifications);
|
receiveAllObserver.check(expectedNotifications);
|
||||||
|
|
|
@ -198,7 +198,7 @@ async function testMoveToFolder(details) {
|
||||||
|
|
||||||
let observer;
|
let observer;
|
||||||
if (details.notifications) {
|
if (details.notifications) {
|
||||||
observer = expectNotifications(false, true);
|
observer = expectNotifications(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let movedItems = await PlacesUtils.bookmarks.moveToFolder(
|
let movedItems = await PlacesUtils.bookmarks.moveToFolder(
|
||||||
|
|
|
@ -437,21 +437,20 @@ add_task(async function remove_bookmark() {
|
||||||
let itemId = await PlacesUtils.promiseItemId(bm.guid);
|
let itemId = await PlacesUtils.promiseItemId(bm.guid);
|
||||||
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
|
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
|
||||||
|
|
||||||
let observer = expectNotifications();
|
let observer = expectPlacesObserverNotifications(["bookmark-removed"]);
|
||||||
await PlacesUtils.bookmarks.remove(bm.guid);
|
await PlacesUtils.bookmarks.remove(bm.guid);
|
||||||
observer.check([
|
observer.check([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: itemId,
|
||||||
itemId,
|
|
||||||
parentId,
|
parentId,
|
||||||
bm.index,
|
index: bm.index,
|
||||||
bm.type,
|
url: bm.url,
|
||||||
bm.url,
|
guid: bm.guid,
|
||||||
bm.guid,
|
parentGuid: bm.parentGuid,
|
||||||
bm.parentGuid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
],
|
isTagging: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -472,34 +471,32 @@ add_task(async function remove_multiple_bookmarks() {
|
||||||
let itemId2 = await PlacesUtils.promiseItemId(bm2.guid);
|
let itemId2 = await PlacesUtils.promiseItemId(bm2.guid);
|
||||||
let parentId2 = await PlacesUtils.promiseItemId(bm2.parentGuid);
|
let parentId2 = await PlacesUtils.promiseItemId(bm2.parentGuid);
|
||||||
|
|
||||||
let observer = expectNotifications();
|
let observer = expectPlacesObserverNotifications(["bookmark-removed"]);
|
||||||
await PlacesUtils.bookmarks.remove([bm1, bm2]);
|
await PlacesUtils.bookmarks.remove([bm1, bm2]);
|
||||||
observer.check([
|
observer.check([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: itemId1,
|
||||||
itemId1,
|
parentId: parentId1,
|
||||||
parentId1,
|
index: bm1.index,
|
||||||
bm1.index,
|
url: bm1.url,
|
||||||
bm1.type,
|
guid: bm1.guid,
|
||||||
bm1.url,
|
parentGuid: bm1.parentGuid,
|
||||||
bm1.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
bm1.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: itemId2,
|
||||||
itemId2,
|
parentId: parentId2,
|
||||||
parentId2,
|
index: bm2.index - 1,
|
||||||
bm2.index - 1,
|
url: bm2.url,
|
||||||
bm2.type,
|
guid: bm2.guid,
|
||||||
bm2.url,
|
parentGuid: bm2.parentGuid,
|
||||||
bm2.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
bm2.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -512,21 +509,20 @@ add_task(async function remove_folder() {
|
||||||
let itemId = await PlacesUtils.promiseItemId(bm.guid);
|
let itemId = await PlacesUtils.promiseItemId(bm.guid);
|
||||||
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
|
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
|
||||||
|
|
||||||
let observer = expectNotifications();
|
let observer = expectPlacesObserverNotifications(["bookmark-removed"]);
|
||||||
await PlacesUtils.bookmarks.remove(bm.guid);
|
await PlacesUtils.bookmarks.remove(bm.guid);
|
||||||
observer.check([
|
observer.check([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: itemId,
|
||||||
itemId,
|
|
||||||
parentId,
|
parentId,
|
||||||
bm.index,
|
index: bm.index,
|
||||||
bm.type,
|
url: null,
|
||||||
null,
|
guid: bm.guid,
|
||||||
bm.guid,
|
parentGuid: bm.parentGuid,
|
||||||
bm.parentGuid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
],
|
isTagging: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -553,23 +549,25 @@ add_task(async function remove_bookmark_tag_notification() {
|
||||||
let tagId = await PlacesUtils.promiseItemId(tag.guid);
|
let tagId = await PlacesUtils.promiseItemId(tag.guid);
|
||||||
let tagParentId = await PlacesUtils.promiseItemId(tag.parentGuid);
|
let tagParentId = await PlacesUtils.promiseItemId(tag.parentGuid);
|
||||||
|
|
||||||
|
let placesObserver = expectPlacesObserverNotifications(["bookmark-removed"]);
|
||||||
let observer = expectNotifications();
|
let observer = expectNotifications();
|
||||||
await PlacesUtils.bookmarks.remove(tag.guid);
|
await PlacesUtils.bookmarks.remove(tag.guid);
|
||||||
|
|
||||||
observer.check([
|
placesObserver.check([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: tagId,
|
||||||
tagId,
|
parentId: tagParentId,
|
||||||
tagParentId,
|
index: tag.index,
|
||||||
tag.index,
|
url: tag.url,
|
||||||
tag.type,
|
guid: tag.guid,
|
||||||
tag.url,
|
parentGuid: tag.parentGuid,
|
||||||
tag.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
tag.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: true,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
]);
|
||||||
|
observer.check([
|
||||||
{
|
{
|
||||||
name: "onItemChanged",
|
name: "onItemChanged",
|
||||||
arguments: [
|
arguments: [
|
||||||
|
@ -617,61 +615,57 @@ add_task(async function remove_folder_notification() {
|
||||||
});
|
});
|
||||||
let bm2ItemId = await PlacesUtils.promiseItemId(bm2.guid);
|
let bm2ItemId = await PlacesUtils.promiseItemId(bm2.guid);
|
||||||
|
|
||||||
let observer = expectNotifications();
|
let observer = expectPlacesObserverNotifications(["bookmark-removed"]);
|
||||||
await PlacesUtils.bookmarks.remove(folder1.guid);
|
await PlacesUtils.bookmarks.remove(folder1.guid);
|
||||||
|
|
||||||
observer.check([
|
observer.check([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: bm2ItemId,
|
||||||
bm2ItemId,
|
parentId: folder2Id,
|
||||||
folder2Id,
|
index: bm2.index,
|
||||||
bm2.index,
|
url: bm2.url,
|
||||||
bm2.type,
|
guid: bm2.guid,
|
||||||
bm2.url,
|
parentGuid: bm2.parentGuid,
|
||||||
bm2.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
bm2.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: folder2Id,
|
||||||
folder2Id,
|
parentId: folder1Id,
|
||||||
folder1Id,
|
index: folder2.index,
|
||||||
folder2.index,
|
url: null,
|
||||||
folder2.type,
|
guid: folder2.guid,
|
||||||
null,
|
parentGuid: folder2.parentGuid,
|
||||||
folder2.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
folder2.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: bmItemId,
|
||||||
bmItemId,
|
parentId: folder1Id,
|
||||||
folder1Id,
|
index: bm.index,
|
||||||
bm.index,
|
url: bm.url,
|
||||||
bm.type,
|
guid: bm.guid,
|
||||||
bm.url,
|
parentGuid: bm.parentGuid,
|
||||||
bm.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
bm.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: folder1Id,
|
||||||
folder1Id,
|
parentId: folder1ParentId,
|
||||||
folder1ParentId,
|
index: folder1.index,
|
||||||
folder1.index,
|
url: null,
|
||||||
folder1.type,
|
guid: folder1.guid,
|
||||||
null,
|
parentGuid: folder1.parentGuid,
|
||||||
folder1.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
folder1.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -718,75 +712,70 @@ add_task(async function eraseEverything_notification() {
|
||||||
let menuBmId = await PlacesUtils.promiseItemId(menuBm.guid);
|
let menuBmId = await PlacesUtils.promiseItemId(menuBm.guid);
|
||||||
let menuBmParentId = await PlacesUtils.promiseItemId(menuBm.parentGuid);
|
let menuBmParentId = await PlacesUtils.promiseItemId(menuBm.parentGuid);
|
||||||
|
|
||||||
let observer = expectNotifications();
|
let observer = expectPlacesObserverNotifications(["bookmark-removed"]);
|
||||||
await PlacesUtils.bookmarks.eraseEverything();
|
await PlacesUtils.bookmarks.eraseEverything();
|
||||||
|
|
||||||
// Bookmarks should always be notified before their parents.
|
// Bookmarks should always be notified before their parents.
|
||||||
observer.check([
|
observer.check([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: itemId,
|
||||||
itemId,
|
|
||||||
parentId,
|
parentId,
|
||||||
bm.index,
|
index: bm.index,
|
||||||
bm.type,
|
url: bm.url,
|
||||||
bm.url,
|
guid: bm.guid,
|
||||||
bm.guid,
|
parentGuid: bm.parentGuid,
|
||||||
bm.parentGuid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
],
|
isTagging: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: folder2Id,
|
||||||
folder2Id,
|
parentId: folder2ParentId,
|
||||||
folder2ParentId,
|
index: folder2.index,
|
||||||
folder2.index,
|
url: null,
|
||||||
folder2.type,
|
guid: folder2.guid,
|
||||||
null,
|
parentGuid: folder2.parentGuid,
|
||||||
folder2.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
folder2.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: folder1Id,
|
||||||
folder1Id,
|
parentId: folder1ParentId,
|
||||||
folder1ParentId,
|
index: folder1.index,
|
||||||
folder1.index,
|
url: null,
|
||||||
folder1.type,
|
guid: folder1.guid,
|
||||||
null,
|
parentGuid: folder1.parentGuid,
|
||||||
folder1.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
folder1.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: menuBmId,
|
||||||
menuBmId,
|
parentId: menuBmParentId,
|
||||||
menuBmParentId,
|
index: menuBm.index,
|
||||||
menuBm.index,
|
url: menuBm.url,
|
||||||
menuBm.type,
|
guid: menuBm.guid,
|
||||||
menuBm.url,
|
parentGuid: menuBm.parentGuid,
|
||||||
menuBm.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
menuBm.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: toolbarBmId,
|
||||||
toolbarBmId,
|
parentId: toolbarBmParentId,
|
||||||
toolbarBmParentId,
|
index: toolbarBm.index,
|
||||||
toolbarBm.index,
|
url: toolbarBm.url,
|
||||||
toolbarBm.type,
|
guid: toolbarBm.guid,
|
||||||
toolbarBm.url,
|
parentGuid: toolbarBm.parentGuid,
|
||||||
toolbarBm.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
toolbarBm.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -820,49 +809,46 @@ add_task(async function eraseEverything_reparented_notification() {
|
||||||
bm = await PlacesUtils.bookmarks.update(bm);
|
bm = await PlacesUtils.bookmarks.update(bm);
|
||||||
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
|
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
|
||||||
|
|
||||||
let observer = expectNotifications();
|
let observer = expectPlacesObserverNotifications(["bookmark-removed"]);
|
||||||
await PlacesUtils.bookmarks.eraseEverything();
|
await PlacesUtils.bookmarks.eraseEverything();
|
||||||
|
|
||||||
// Bookmarks should always be notified before their parents.
|
// Bookmarks should always be notified before their parents.
|
||||||
observer.check([
|
observer.check([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: itemId,
|
||||||
itemId,
|
|
||||||
parentId,
|
parentId,
|
||||||
bm.index,
|
index: bm.index,
|
||||||
bm.type,
|
url: bm.url,
|
||||||
bm.url,
|
guid: bm.guid,
|
||||||
bm.guid,
|
parentGuid: bm.parentGuid,
|
||||||
bm.parentGuid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
],
|
isTagging: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: folder2Id,
|
||||||
folder2Id,
|
parentId: folder2ParentId,
|
||||||
folder2ParentId,
|
index: folder2.index,
|
||||||
folder2.index,
|
url: null,
|
||||||
folder2.type,
|
guid: folder2.guid,
|
||||||
null,
|
parentGuid: folder2.parentGuid,
|
||||||
folder2.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
folder2.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: [
|
id: folder1Id,
|
||||||
folder1Id,
|
parentId: folder1ParentId,
|
||||||
folder1ParentId,
|
index: folder1.index,
|
||||||
folder1.index,
|
url: null,
|
||||||
folder1.type,
|
guid: folder1.guid,
|
||||||
null,
|
parentGuid: folder1.parentGuid,
|
||||||
folder1.guid,
|
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
||||||
folder1.parentGuid,
|
itemType: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
|
isTagging: false,
|
||||||
],
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -198,11 +198,14 @@ add_task(async function remove_multiple_bookmarks_complex() {
|
||||||
let bmsToRemove = bms.slice(2, 4);
|
let bmsToRemove = bms.slice(2, 4);
|
||||||
let notifiedIndexes = [];
|
let notifiedIndexes = [];
|
||||||
let notificationPromise = PlacesTestUtils.waitForNotification(
|
let notificationPromise = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(itemId, parentId, index, itemType, uri, guid, parentGuid, source) => {
|
events => {
|
||||||
notifiedIndexes.push({ guid, index });
|
for (let event of events) {
|
||||||
return notifiedIndexes.length == bmsToRemove.length;
|
notifiedIndexes.push({ guid: event.guid, index: event.index });
|
||||||
}
|
}
|
||||||
|
return notifiedIndexes.length == bmsToRemove.length;
|
||||||
|
},
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
await PlacesUtils.bookmarks.remove(bmsToRemove);
|
await PlacesUtils.bookmarks.remove(bmsToRemove);
|
||||||
await notificationPromise;
|
await notificationPromise;
|
||||||
|
@ -238,11 +241,14 @@ add_task(async function remove_multiple_bookmarks_complex() {
|
||||||
bmsToRemove = [bms[1], bms[5], bms[6], bms[8]];
|
bmsToRemove = [bms[1], bms[5], bms[6], bms[8]];
|
||||||
notifiedIndexes = [];
|
notifiedIndexes = [];
|
||||||
notificationPromise = PlacesTestUtils.waitForNotification(
|
notificationPromise = PlacesTestUtils.waitForNotification(
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
(itemId, parentId, index, itemType, uri, guid, parentGuid, source) => {
|
events => {
|
||||||
notifiedIndexes.push({ guid, index });
|
for (let event of events) {
|
||||||
return notifiedIndexes.length == bmsToRemove.length;
|
notifiedIndexes.push({ guid: event.guid, index: event.index });
|
||||||
}
|
}
|
||||||
|
return notifiedIndexes.length == bmsToRemove.length;
|
||||||
|
},
|
||||||
|
"places"
|
||||||
);
|
);
|
||||||
await PlacesUtils.bookmarks.remove(bmsToRemove);
|
await PlacesUtils.bookmarks.remove(bmsToRemove);
|
||||||
await notificationPromise;
|
await notificationPromise;
|
||||||
|
@ -344,8 +350,16 @@ add_task(async function test_contents_removed() {
|
||||||
title: "",
|
title: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
let skipDescendantsObserver = expectNotifications(true);
|
let skipDescendantsObserver = expectPlacesObserverNotifications(
|
||||||
let receiveAllObserver = expectNotifications(false);
|
["bookmark-removed"],
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
let receiveAllObserver = expectPlacesObserverNotifications(
|
||||||
|
["bookmark-removed"],
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
let frecencyChangedPromise = promiseFrecencyChanged("http://example.com/", 0);
|
let frecencyChangedPromise = promiseFrecencyChanged("http://example.com/", 0);
|
||||||
await PlacesUtils.bookmarks.remove(folder1);
|
await PlacesUtils.bookmarks.remove(folder1);
|
||||||
Assert.strictEqual(await PlacesUtils.bookmarks.fetch(folder1.guid), null);
|
Assert.strictEqual(await PlacesUtils.bookmarks.fetch(folder1.guid), null);
|
||||||
|
@ -355,11 +369,9 @@ add_task(async function test_contents_removed() {
|
||||||
|
|
||||||
let expectedNotifications = [
|
let expectedNotifications = [
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: {
|
|
||||||
guid: folder1.guid,
|
guid: folder1.guid,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// If we're skipping descendents, we'll only be notified of the folder.
|
// If we're skipping descendents, we'll only be notified of the folder.
|
||||||
|
@ -367,12 +379,9 @@ add_task(async function test_contents_removed() {
|
||||||
|
|
||||||
// Note: Items of folders get notified first.
|
// Note: Items of folders get notified first.
|
||||||
expectedNotifications.unshift({
|
expectedNotifications.unshift({
|
||||||
name: "onItemRemoved",
|
type: "bookmark-removed",
|
||||||
arguments: {
|
|
||||||
guid: bm1.guid,
|
guid: bm1.guid,
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// If we don't skip descendents, we'll be notified of the folder and the
|
// If we don't skip descendents, we'll be notified of the folder and the
|
||||||
// bookmark.
|
// bookmark.
|
||||||
receiveAllObserver.check(expectedNotifications);
|
receiveAllObserver.check(expectedNotifications);
|
||||||
|
|
|
@ -63,9 +63,6 @@ var gBookmarksObserver = {
|
||||||
onEndUpdateBatch() {
|
onEndUpdateBatch() {
|
||||||
return this.validate("onEndUpdateBatch", arguments);
|
return this.validate("onEndUpdateBatch", arguments);
|
||||||
},
|
},
|
||||||
onItemRemoved() {
|
|
||||||
return this.validate("onItemRemoved", arguments);
|
|
||||||
},
|
|
||||||
onItemChanged() {
|
onItemChanged() {
|
||||||
return this.validate("onItemChanged", arguments);
|
return this.validate("onItemChanged", arguments);
|
||||||
},
|
},
|
||||||
|
@ -82,7 +79,6 @@ var gBookmarksObserver = {
|
||||||
|
|
||||||
var gBookmarkSkipObserver = {
|
var gBookmarkSkipObserver = {
|
||||||
skipTags: true,
|
skipTags: true,
|
||||||
skipDescendantsOnItemRemoval: true,
|
|
||||||
|
|
||||||
expected: null,
|
expected: null,
|
||||||
setup(expected) {
|
setup(expected) {
|
||||||
|
@ -122,9 +118,6 @@ var gBookmarkSkipObserver = {
|
||||||
onEndUpdateBatch() {
|
onEndUpdateBatch() {
|
||||||
return this.validate("onEndUpdateBatch", arguments);
|
return this.validate("onEndUpdateBatch", arguments);
|
||||||
},
|
},
|
||||||
onItemRemoved() {
|
|
||||||
return this.validate("onItemRemoved", arguments);
|
|
||||||
},
|
|
||||||
onItemChanged() {
|
onItemChanged() {
|
||||||
return this.validate("onItemChanged", arguments);
|
return this.validate("onItemChanged", arguments);
|
||||||
},
|
},
|
||||||
|
@ -152,11 +145,11 @@ add_task(async function setup() {
|
||||||
gBookmarkSkipObserver
|
gBookmarkSkipObserver
|
||||||
);
|
);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
gBookmarksObserver.handlePlacesEvents
|
gBookmarksObserver.handlePlacesEvents
|
||||||
);
|
);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
gBookmarkSkipObserver.handlePlacesEvents
|
gBookmarkSkipObserver.handlePlacesEvents
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -429,42 +422,16 @@ add_task(async function onItemChanged_tags_bookmark() {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved", // This is the tag.
|
eventType: "bookmark-removed", // This is the tag.
|
||||||
args: [
|
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: "parentId", check: v => typeof v == "number" && v > 0 },
|
||||||
{ name: "index", check: v => v === 0 },
|
{ name: "index", check: v => v === 0 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
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: "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: "onItemRemoved", // This is the tag folder.
|
|
||||||
args: [
|
|
||||||
{ name: "itemId", 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: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
@ -480,6 +447,7 @@ add_task(async function onItemChanged_tags_bookmark() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "onItemChanged",
|
name: "onItemChanged",
|
||||||
args: [
|
args: [
|
||||||
|
@ -509,6 +477,32 @@ add_task(async function onItemChanged_tags_bookmark() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
eventType: "bookmark-removed", // This is the tag folder.
|
||||||
|
args: [
|
||||||
|
{ 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: "url", check: v => v === "" },
|
||||||
|
{
|
||||||
|
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),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
PlacesUtils.tagging.tagURI(uri, [TAG]);
|
PlacesUtils.tagging.tagURI(uri, [TAG]);
|
||||||
|
@ -646,26 +640,26 @@ add_task(async function onItemMoved_bookmark() {
|
||||||
await promise;
|
await promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function onItemRemoved_bookmark() {
|
add_task(async function bookmarkItemRemoved_bookmark() {
|
||||||
let bm = await PlacesUtils.bookmarks.fetch({
|
let bm = await PlacesUtils.bookmarks.fetch({
|
||||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||||
index: 0,
|
index: 0,
|
||||||
});
|
});
|
||||||
let uri = Services.io.newURI(bm.url.href);
|
let uri = Services.io.newURI(bm.url.href);
|
||||||
let promise = Promise.all([
|
let promise = Promise.all([
|
||||||
gBookmarkSkipObserver.setup(["onItemRemoved"]),
|
gBookmarkSkipObserver.setup(["bookmark-removed"]),
|
||||||
gBookmarksObserver.setup([
|
gBookmarksObserver.setup([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
eventType: "bookmark-removed",
|
||||||
args: [
|
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: "parentId", check: v => v === gUnfiledFolderId },
|
||||||
{ name: "index", check: v => v === 0 },
|
{ name: "index", check: v => v === 0 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
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: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
@ -687,25 +681,25 @@ add_task(async function onItemRemoved_bookmark() {
|
||||||
await promise;
|
await promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function onItemRemoved_separator() {
|
add_task(async function bookmarkItemRemoved_separator() {
|
||||||
let bm = await PlacesUtils.bookmarks.fetch({
|
let bm = await PlacesUtils.bookmarks.fetch({
|
||||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||||
index: 0,
|
index: 0,
|
||||||
});
|
});
|
||||||
let promise = Promise.all([
|
let promise = Promise.all([
|
||||||
gBookmarkSkipObserver.setup(["onItemRemoved"]),
|
gBookmarkSkipObserver.setup(["bookmark-removed"]),
|
||||||
gBookmarksObserver.setup([
|
gBookmarksObserver.setup([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
eventType: "bookmark-removed",
|
||||||
args: [
|
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: "parentId", check: v => typeof v == "number" && v > 0 },
|
||||||
{ name: "index", check: v => v === 0 },
|
{ name: "index", check: v => v === 0 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR,
|
||||||
},
|
},
|
||||||
{ name: "uri", check: v => v === null },
|
{ name: "url", check: v => v === "" },
|
||||||
{
|
{
|
||||||
name: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
@ -727,25 +721,25 @@ add_task(async function onItemRemoved_separator() {
|
||||||
await promise;
|
await promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function onItemRemoved_folder() {
|
add_task(async function bookmarkItemRemoved_folder() {
|
||||||
let bm = await PlacesUtils.bookmarks.fetch({
|
let bm = await PlacesUtils.bookmarks.fetch({
|
||||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||||
index: 0,
|
index: 0,
|
||||||
});
|
});
|
||||||
let promise = Promise.all([
|
let promise = Promise.all([
|
||||||
gBookmarkSkipObserver.setup(["onItemRemoved"]),
|
gBookmarkSkipObserver.setup(["bookmark-removed"]),
|
||||||
gBookmarksObserver.setup([
|
gBookmarksObserver.setup([
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
eventType: "bookmark-removed",
|
||||||
args: [
|
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: "parentId", check: v => typeof v == "number" && v > 0 },
|
||||||
{ name: "index", check: v => v === 0 },
|
{ name: "index", check: v => v === 0 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER,
|
check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
},
|
},
|
||||||
{ name: "uri", check: v => v === null },
|
{ name: "url", check: v => v === "" },
|
||||||
{
|
{
|
||||||
name: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
@ -767,7 +761,7 @@ add_task(async function onItemRemoved_folder() {
|
||||||
await promise;
|
await promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function onItemRemoved_folder_recursive() {
|
add_task(async function bookmarkItemRemoved_folder_recursive() {
|
||||||
const title = "Folder 3";
|
const title = "Folder 3";
|
||||||
const BMTITLE = "Bookmark 1";
|
const BMTITLE = "Bookmark 1";
|
||||||
let uri = Services.io.newURI("http://1.mozilla.org/");
|
let uri = Services.io.newURI("http://1.mozilla.org/");
|
||||||
|
@ -777,7 +771,10 @@ add_task(async function onItemRemoved_folder_recursive() {
|
||||||
"bookmark-added",
|
"bookmark-added",
|
||||||
"bookmark-added",
|
"bookmark-added",
|
||||||
"bookmark-added",
|
"bookmark-added",
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
|
"bookmark-removed",
|
||||||
|
"bookmark-removed",
|
||||||
|
"bookmark-removed",
|
||||||
]),
|
]),
|
||||||
gBookmarksObserver.setup([
|
gBookmarksObserver.setup([
|
||||||
{
|
{
|
||||||
|
@ -893,16 +890,16 @@ add_task(async function onItemRemoved_folder_recursive() {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
eventType: "bookmark-removed",
|
||||||
args: [
|
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: "parentId", check: v => typeof v == "number" && v > 0 },
|
||||||
{ name: "index", check: v => v === 0 },
|
{ name: "index", check: v => v === 0 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
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: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
@ -919,16 +916,16 @@ add_task(async function onItemRemoved_folder_recursive() {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
eventType: "bookmark-removed",
|
||||||
args: [
|
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: "parentId", check: v => typeof v == "number" && v > 0 },
|
||||||
{ name: "index", check: v => v === 1 },
|
{ name: "index", check: v => v === 1 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER,
|
check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
},
|
},
|
||||||
{ name: "uri", check: v => v === null },
|
{ name: "url", check: v => v === "" },
|
||||||
{
|
{
|
||||||
name: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
@ -945,16 +942,16 @@ add_task(async function onItemRemoved_folder_recursive() {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
eventType: "bookmark-removed",
|
||||||
args: [
|
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: "parentId", check: v => typeof v == "number" && v > 0 },
|
||||||
{ name: "index", check: v => v === 0 },
|
{ name: "index", check: v => v === 0 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
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: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
@ -971,16 +968,16 @@ add_task(async function onItemRemoved_folder_recursive() {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "onItemRemoved",
|
eventType: "bookmark-removed",
|
||||||
args: [
|
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: "parentId", check: v => typeof v == "number" && v > 0 },
|
||||||
{ name: "index", check: v => v === 0 },
|
{ name: "index", check: v => v === 0 },
|
||||||
{
|
{
|
||||||
name: "itemType",
|
name: "itemType",
|
||||||
check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER,
|
check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||||
},
|
},
|
||||||
{ name: "uri", check: v => v === null },
|
{ name: "url", check: v => v === "" },
|
||||||
{
|
{
|
||||||
name: "guid",
|
name: "guid",
|
||||||
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
|
||||||
|
|
|
@ -31,7 +31,7 @@ add_task(async function test_removeFolderTransaction_reinsert() {
|
||||||
let listener = events => {
|
let listener = events => {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
notifications.push([
|
notifications.push([
|
||||||
"bookmark-added",
|
event.type,
|
||||||
event.id,
|
event.id,
|
||||||
event.parentId,
|
event.parentId,
|
||||||
event.guid,
|
event.guid,
|
||||||
|
@ -41,15 +41,18 @@ add_task(async function test_removeFolderTransaction_reinsert() {
|
||||||
};
|
};
|
||||||
let observer = {
|
let observer = {
|
||||||
__proto__: NavBookmarkObserver.prototype,
|
__proto__: NavBookmarkObserver.prototype,
|
||||||
onItemRemoved(itemId, parentId, index, type, uri, guid, parentGuid) {
|
|
||||||
notifications.push(["onItemRemoved", itemId, parentId, guid, parentGuid]);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
PlacesUtils.bookmarks.addObserver(observer);
|
PlacesUtils.bookmarks.addObserver(observer);
|
||||||
PlacesUtils.observers.addListener(["bookmark-added"], listener);
|
PlacesUtils.observers.addListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
listener
|
||||||
|
);
|
||||||
PlacesUtils.registerShutdownFunction(function() {
|
PlacesUtils.registerShutdownFunction(function() {
|
||||||
PlacesUtils.bookmarks.removeObserver(observer);
|
PlacesUtils.bookmarks.removeObserver(observer);
|
||||||
PlacesUtils.observers.removeListener(["bookmark-added"], listener);
|
PlacesUtils.observers.removeListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
listener
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let transaction = PlacesTransactions.Remove({ guid: folder.guid });
|
let transaction = PlacesTransactions.Remove({ guid: folder.guid });
|
||||||
|
@ -62,10 +65,10 @@ add_task(async function test_removeFolderTransaction_reinsert() {
|
||||||
|
|
||||||
checkNotifications(
|
checkNotifications(
|
||||||
[
|
[
|
||||||
["onItemRemoved", tbId, folderId, tb.guid, folder.guid],
|
["bookmark-removed", tbId, folderId, tb.guid, folder.guid],
|
||||||
["onItemRemoved", fxId, folderId, fx.guid, folder.guid],
|
["bookmark-removed", fxId, folderId, fx.guid, folder.guid],
|
||||||
[
|
[
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
folderId,
|
folderId,
|
||||||
PlacesUtils.bookmarksMenuFolderId,
|
PlacesUtils.bookmarksMenuFolderId,
|
||||||
folder.guid,
|
folder.guid,
|
||||||
|
@ -100,10 +103,10 @@ add_task(async function test_removeFolderTransaction_reinsert() {
|
||||||
|
|
||||||
checkNotifications(
|
checkNotifications(
|
||||||
[
|
[
|
||||||
["onItemRemoved", tbId, folderId, tb.guid, folder.guid],
|
["bookmark-removed", tbId, folderId, tb.guid, folder.guid],
|
||||||
["onItemRemoved", fxId, folderId, fx.guid, folder.guid],
|
["bookmark-removed", fxId, folderId, fx.guid, folder.guid],
|
||||||
[
|
[
|
||||||
"onItemRemoved",
|
"bookmark-removed",
|
||||||
folderId,
|
folderId,
|
||||||
PlacesUtils.bookmarksMenuFolderId,
|
PlacesUtils.bookmarksMenuFolderId,
|
||||||
folder.guid,
|
folder.guid,
|
||||||
|
|
|
@ -12,6 +12,8 @@ var bookmarksObserver = {
|
||||||
handlePlacesEvents(events) {
|
handlePlacesEvents(events) {
|
||||||
Assert.equal(events.length, 1);
|
Assert.equal(events.length, 1);
|
||||||
let event = events[0];
|
let event = events[0];
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added":
|
||||||
bookmarksObserver._itemAddedId = event.id;
|
bookmarksObserver._itemAddedId = event.id;
|
||||||
bookmarksObserver._itemAddedParent = event.parentId;
|
bookmarksObserver._itemAddedParent = event.parentId;
|
||||||
bookmarksObserver._itemAddedIndex = event.index;
|
bookmarksObserver._itemAddedIndex = event.index;
|
||||||
|
@ -32,6 +34,12 @@ var bookmarksObserver = {
|
||||||
do_check_valid_places_guid(stmt.row.guid);
|
do_check_valid_places_guid(stmt.row.guid);
|
||||||
Assert.equal(stmt.row.guid, event.guid);
|
Assert.equal(stmt.row.guid, event.guid);
|
||||||
stmt.finalize();
|
stmt.finalize();
|
||||||
|
break;
|
||||||
|
case "bookmark-removed":
|
||||||
|
bookmarksObserver._itemRemovedId = event.id;
|
||||||
|
bookmarksObserver._itemRemovedFolder = event.parentId;
|
||||||
|
bookmarksObserver._itemRemovedIndex = event.index;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onBeginUpdateBatch() {
|
onBeginUpdateBatch() {
|
||||||
|
@ -40,11 +48,7 @@ var bookmarksObserver = {
|
||||||
onEndUpdateBatch() {
|
onEndUpdateBatch() {
|
||||||
this._endUpdateBatch = true;
|
this._endUpdateBatch = true;
|
||||||
},
|
},
|
||||||
onItemRemoved(id, folder, index, itemType) {
|
|
||||||
this._itemRemovedId = id;
|
|
||||||
this._itemRemovedFolder = folder;
|
|
||||||
this._itemRemovedIndex = index;
|
|
||||||
},
|
|
||||||
onItemChanged(
|
onItemChanged(
|
||||||
id,
|
id,
|
||||||
property,
|
property,
|
||||||
|
@ -84,7 +88,10 @@ var bmStartIndex = 0;
|
||||||
|
|
||||||
add_task(async function test_bookmarks() {
|
add_task(async function test_bookmarks() {
|
||||||
bs.addObserver(bookmarksObserver);
|
bs.addObserver(bookmarksObserver);
|
||||||
os.addListener(["bookmark-added"], bookmarksObserver.handlePlacesEvents);
|
os.addListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
bookmarksObserver.handlePlacesEvents
|
||||||
|
);
|
||||||
|
|
||||||
// test special folders
|
// test special folders
|
||||||
Assert.ok(bs.placesRoot > 0);
|
Assert.ok(bs.placesRoot > 0);
|
||||||
|
|
|
@ -37,7 +37,12 @@ add_task(async function test_eraseEverything() {
|
||||||
}
|
}
|
||||||
Assert.equal(root.getChild(0).title, "title 1");
|
Assert.equal(root.getChild(0).title, "title 1");
|
||||||
Assert.equal(root.getChild(1).title, "title 2");
|
Assert.equal(root.getChild(1).title, "title 2");
|
||||||
|
|
||||||
await PlacesUtils.bookmarks.eraseEverything();
|
await PlacesUtils.bookmarks.eraseEverything();
|
||||||
|
|
||||||
|
// Refetch the guid to refresh the data.
|
||||||
|
unfiled = PlacesUtils.getFolderContents(PlacesUtils.bookmarks.unfiledGuid)
|
||||||
|
.root;
|
||||||
Assert.equal(unfiled.childCount, 0);
|
Assert.equal(unfiled.childCount, 0);
|
||||||
unfiled.containerOpen = false;
|
unfiled.containerOpen = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -296,6 +296,8 @@ function BookmarkObserver({ ignoreDates = true, skipTags = false } = {}) {
|
||||||
BookmarkObserver.prototype = {
|
BookmarkObserver.prototype = {
|
||||||
handlePlacesEvents(events) {
|
handlePlacesEvents(events) {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added": {
|
||||||
if (this.skipTags && event.isTagging) {
|
if (this.skipTags && event.isTagging) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -314,26 +316,39 @@ BookmarkObserver.prototype = {
|
||||||
params.dateAdded = event.dateAdded * 1000;
|
params.dateAdded = event.dateAdded * 1000;
|
||||||
}
|
}
|
||||||
this.notifications.push({ name: "bookmark-added", params });
|
this.notifications.push({ name: "bookmark-added", params });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "bookmark-removed": {
|
||||||
|
if (this.skipTags && event.isTagging) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Since we are now skipping tags on the listener side we don't
|
||||||
|
// prevent unTagging notifications from going out. These events cause empty
|
||||||
|
// tags folders to be removed which creates another bookmark-removed notification
|
||||||
|
if (
|
||||||
|
this.skipTags &&
|
||||||
|
event.parentGuid == PlacesUtils.bookmarks.tagsGuid
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let params = {
|
||||||
|
itemId: event.id,
|
||||||
|
parentId: event.parentId,
|
||||||
|
index: event.index,
|
||||||
|
type: event.itemType,
|
||||||
|
urlHref: event.url || null,
|
||||||
|
guid: event.guid,
|
||||||
|
parentGuid: event.parentGuid,
|
||||||
|
source: event.source,
|
||||||
|
};
|
||||||
|
this.notifications.push({ name: "bookmark-removed", params });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onBeginUpdateBatch() {},
|
onBeginUpdateBatch() {},
|
||||||
onEndUpdateBatch() {},
|
onEndUpdateBatch() {},
|
||||||
onItemRemoved(itemId, parentId, index, type, uri, guid, parentGuid, source) {
|
|
||||||
let urlHref = uri ? uri.spec : null;
|
|
||||||
this.notifications.push({
|
|
||||||
name: "onItemRemoved",
|
|
||||||
params: {
|
|
||||||
itemId,
|
|
||||||
parentId,
|
|
||||||
index,
|
|
||||||
type,
|
|
||||||
urlHref,
|
|
||||||
guid,
|
|
||||||
parentGuid,
|
|
||||||
source,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onItemChanged(
|
onItemChanged(
|
||||||
itemId,
|
itemId,
|
||||||
property,
|
property,
|
||||||
|
@ -401,7 +416,7 @@ BookmarkObserver.prototype = {
|
||||||
check(expectedNotifications) {
|
check(expectedNotifications) {
|
||||||
PlacesUtils.bookmarks.removeObserver(this);
|
PlacesUtils.bookmarks.removeObserver(this);
|
||||||
PlacesUtils.observers.removeListener(
|
PlacesUtils.observers.removeListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
this.handlePlacesEvents
|
this.handlePlacesEvents
|
||||||
);
|
);
|
||||||
if (!ObjectUtils.deepEqual(this.notifications, expectedNotifications)) {
|
if (!ObjectUtils.deepEqual(this.notifications, expectedNotifications)) {
|
||||||
|
@ -419,7 +434,7 @@ function expectBookmarkChangeNotifications(options) {
|
||||||
let observer = new BookmarkObserver(options);
|
let observer = new BookmarkObserver(options);
|
||||||
PlacesUtils.bookmarks.addObserver(observer);
|
PlacesUtils.bookmarks.addObserver(observer);
|
||||||
PlacesUtils.observers.addListener(
|
PlacesUtils.observers.addListener(
|
||||||
["bookmark-added"],
|
["bookmark-added", "bookmark-removed"],
|
||||||
observer.handlePlacesEvents
|
observer.handlePlacesEvents
|
||||||
);
|
);
|
||||||
return observer;
|
return observer;
|
||||||
|
|
|
@ -210,8 +210,17 @@ add_task(async function test_changes_deleted_bookmark() {
|
||||||
);
|
);
|
||||||
await PlacesTestUtils.markBookmarksAsSynced();
|
await PlacesTestUtils.markBookmarksAsSynced();
|
||||||
|
|
||||||
|
let wait = PlacesTestUtils.waitForNotification(
|
||||||
|
"bookmark-removed",
|
||||||
|
events =>
|
||||||
|
events.some(event => event.parentGuid == PlacesUtils.bookmarks.tagsGuid),
|
||||||
|
"places"
|
||||||
|
);
|
||||||
await PlacesUtils.bookmarks.remove("mozBmk______");
|
await PlacesUtils.bookmarks.remove("mozBmk______");
|
||||||
|
|
||||||
|
await wait;
|
||||||
|
// Wait for everything to be finished
|
||||||
|
await new Promise(resolve => Services.tm.dispatchToMainThread(resolve));
|
||||||
let controller = new AbortController();
|
let controller = new AbortController();
|
||||||
const wasMerged = await buf.merge(controller.signal);
|
const wasMerged = await buf.merge(controller.signal);
|
||||||
Assert.ok(wasMerged);
|
Assert.ok(wasMerged);
|
||||||
|
|
|
@ -433,19 +433,6 @@ add_task(async function test_apply_then_revert() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
observer.check([
|
observer.check([
|
||||||
{
|
|
||||||
name: "onItemRemoved",
|
|
||||||
params: {
|
|
||||||
itemId: localIdForD,
|
|
||||||
parentId: PlacesUtils.bookmarksMenuFolderId,
|
|
||||||
index: 1,
|
|
||||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
|
||||||
urlHref: "http://example.com/d",
|
|
||||||
guid: "bookmarkDDDD",
|
|
||||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
|
||||||
source: PlacesUtils.bookmarks.SOURCES.SYNC,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "onItemChanged",
|
name: "onItemChanged",
|
||||||
params: {
|
params: {
|
||||||
|
@ -461,6 +448,19 @@ add_task(async function test_apply_then_revert() {
|
||||||
source: PlacesUtils.bookmarks.SOURCES.SYNC,
|
source: PlacesUtils.bookmarks.SOURCES.SYNC,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "bookmark-removed",
|
||||||
|
params: {
|
||||||
|
itemId: localIdForD,
|
||||||
|
parentId: PlacesUtils.bookmarksMenuFolderId,
|
||||||
|
index: 1,
|
||||||
|
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||||
|
urlHref: "http://example.com/d",
|
||||||
|
guid: "bookmarkDDDD",
|
||||||
|
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||||
|
source: PlacesUtils.bookmarks.SOURCES.SYNC,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "bookmark-added",
|
name: "bookmark-added",
|
||||||
params: {
|
params: {
|
||||||
|
|
|
@ -1890,11 +1890,22 @@ add_task(async function test_tags() {
|
||||||
"eleven",
|
"eleven",
|
||||||
"twelve",
|
"twelve",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
let wait = PlacesTestUtils.waitForNotification(
|
||||||
|
"bookmark-removed",
|
||||||
|
events =>
|
||||||
|
events.some(event => event.parentGuid == PlacesUtils.bookmarks.tagsGuid),
|
||||||
|
"places"
|
||||||
|
);
|
||||||
|
|
||||||
PlacesUtils.tagging.untagURI(
|
PlacesUtils.tagging.untagURI(
|
||||||
Services.io.newURI("http://example.com/d"),
|
Services.io.newURI("http://example.com/d"),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await wait;
|
||||||
|
|
||||||
|
await new Promise(resolve => Services.tm.dispatchToMainThread(resolve));
|
||||||
info("Apply remote");
|
info("Apply remote");
|
||||||
let changesToUpload = await buf.apply();
|
let changesToUpload = await buf.apply();
|
||||||
deepEqual(await buf.fetchUnmergedGuids(), [], "Should merge all items");
|
deepEqual(await buf.fetchUnmergedGuids(), [], "Should merge all items");
|
||||||
|
|
|
@ -33,6 +33,8 @@ var observer = {
|
||||||
|
|
||||||
handlePlacesEvents(events) {
|
handlePlacesEvents(events) {
|
||||||
for (let event of events) {
|
for (let event of events) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "bookmark-added":
|
||||||
// Ignore tag items.
|
// Ignore tag items.
|
||||||
if (event.isTagging) {
|
if (event.isTagging) {
|
||||||
this.tagRelatedGuids.add(event.guid);
|
this.tagRelatedGuids.add(event.guid);
|
||||||
|
@ -47,6 +49,18 @@ var observer = {
|
||||||
title: event.title,
|
title: event.title,
|
||||||
url: event.url,
|
url: event.url,
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case "bookmark-removed":
|
||||||
|
if (this.tagRelatedGuids.has(event.guid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.itemsRemoved.set(event.guid, {
|
||||||
|
parentGuid: event.parentGuid,
|
||||||
|
index: event.index,
|
||||||
|
itemType: event.itemType,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -58,26 +72,6 @@ var observer = {
|
||||||
this.endUpdateBatch = true;
|
this.endUpdateBatch = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
onItemRemoved(
|
|
||||||
aItemId,
|
|
||||||
aParentId,
|
|
||||||
aIndex,
|
|
||||||
aItemType,
|
|
||||||
aURI,
|
|
||||||
aGuid,
|
|
||||||
aParentGuid
|
|
||||||
) {
|
|
||||||
if (this.tagRelatedGuids.has(aGuid)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.itemsRemoved.set(aGuid, {
|
|
||||||
parentGuid: aParentGuid,
|
|
||||||
index: aIndex,
|
|
||||||
itemType: aItemType,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onItemChanged(
|
onItemChanged(
|
||||||
aItemId,
|
aItemId,
|
||||||
aProperty,
|
aProperty,
|
||||||
|
@ -137,10 +131,16 @@ var bmStartIndex = 0;
|
||||||
function run_test() {
|
function run_test() {
|
||||||
bmsvc.addObserver(observer);
|
bmsvc.addObserver(observer);
|
||||||
observer.handlePlacesEvents = observer.handlePlacesEvents.bind(observer);
|
observer.handlePlacesEvents = observer.handlePlacesEvents.bind(observer);
|
||||||
obsvc.addListener(["bookmark-added"], observer.handlePlacesEvents);
|
obsvc.addListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
observer.handlePlacesEvents
|
||||||
|
);
|
||||||
registerCleanupFunction(function() {
|
registerCleanupFunction(function() {
|
||||||
bmsvc.removeObserver(observer);
|
bmsvc.removeObserver(observer);
|
||||||
obsvc.removeListener(["bookmark-added"], observer.handlePlacesEvents);
|
obsvc.removeListener(
|
||||||
|
["bookmark-added", "bookmark-removed"],
|
||||||
|
observer.handlePlacesEvents
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
run_next_test();
|
run_next_test();
|
||||||
|
@ -1241,7 +1241,34 @@ add_task(async function test_add_and_remove_bookmarks_with_additional_info() {
|
||||||
|
|
||||||
observer.reset();
|
observer.reset();
|
||||||
await PT.redo();
|
await PT.redo();
|
||||||
|
// The tag containers are removed in async and take some time
|
||||||
|
let oldCountTag1 = 0;
|
||||||
|
let oldCountTag2 = 0;
|
||||||
|
let allTags = await bmsvc.fetchTags();
|
||||||
|
for (let i of allTags) {
|
||||||
|
if (i.name == TAG_1) {
|
||||||
|
oldCountTag1 = i.count;
|
||||||
|
}
|
||||||
|
if (i.name == TAG_2) {
|
||||||
|
oldCountTag2 = i.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await TestUtils.waitForCondition(async () => {
|
||||||
|
allTags = await bmsvc.fetchTags();
|
||||||
|
let newCountTag1 = 0;
|
||||||
|
let newCountTag2 = 0;
|
||||||
|
for (let i of allTags) {
|
||||||
|
if (i.name == TAG_1) {
|
||||||
|
newCountTag1 = i.count;
|
||||||
|
}
|
||||||
|
if (i.name == TAG_2) {
|
||||||
|
newCountTag2 = i.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newCountTag1 == oldCountTag1 - 1 && newCountTag2 == oldCountTag2 - 1;
|
||||||
|
});
|
||||||
await ensureItemsRemoved(b2_info);
|
await ensureItemsRemoved(b2_info);
|
||||||
|
|
||||||
ensureTags([]);
|
ensureTags([]);
|
||||||
|
|
||||||
observer.reset();
|
observer.reset();
|
||||||
|
|
|
@ -31,9 +31,21 @@ add_task(async function test_removing_tagged_bookmark_removes_tag() {
|
||||||
let tags = ["foo", "bar"];
|
let tags = ["foo", "bar"];
|
||||||
tagssvc.tagURI(BOOKMARK_URI, tags);
|
tagssvc.tagURI(BOOKMARK_URI, tags);
|
||||||
ensureTagsExist(tags);
|
ensureTagsExist(tags);
|
||||||
|
let root = getTagRoot();
|
||||||
|
root.containerOpen = true;
|
||||||
|
let oldCount = root.childCount;
|
||||||
|
root.containerOpen = false;
|
||||||
|
|
||||||
print(" Remove the bookmark. The tags should no longer exist.");
|
print(" Remove the bookmark. The tags should no longer exist.");
|
||||||
|
let wait = TestUtils.waitForCondition(() => {
|
||||||
|
root = getTagRoot();
|
||||||
|
root.containerOpen = true;
|
||||||
|
let val = root.childCount == oldCount - 2;
|
||||||
|
root.containerOpen = false;
|
||||||
|
return val;
|
||||||
|
});
|
||||||
await PlacesUtils.bookmarks.remove(bookmark.guid);
|
await PlacesUtils.bookmarks.remove(bookmark.guid);
|
||||||
|
await wait;
|
||||||
ensureTagsExist([]);
|
ensureTagsExist([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,12 +70,40 @@ add_task(
|
||||||
tagssvc.tagURI(BOOKMARK_URI, tags);
|
tagssvc.tagURI(BOOKMARK_URI, tags);
|
||||||
ensureTagsExist(tags);
|
ensureTagsExist(tags);
|
||||||
|
|
||||||
|
// The tag containers are removed in async and take some time
|
||||||
|
let oldCountFoo = await tagCount("foo");
|
||||||
|
let oldCountBar = await tagCount("bar");
|
||||||
|
|
||||||
print(" Remove the folder. The tags should no longer exist.");
|
print(" Remove the folder. The tags should no longer exist.");
|
||||||
|
|
||||||
|
let wait = TestUtils.waitForCondition(async () => {
|
||||||
|
let newCountFoo = await tagCount("foo");
|
||||||
|
let newCountBar = await tagCount("bar");
|
||||||
|
return newCountFoo == oldCountFoo - 1 && newCountBar == oldCountBar - 1;
|
||||||
|
});
|
||||||
await PlacesUtils.bookmarks.remove(bookmark.guid);
|
await PlacesUtils.bookmarks.remove(bookmark.guid);
|
||||||
|
await wait;
|
||||||
ensureTagsExist([]);
|
ensureTagsExist([]);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function tagCount(aTag) {
|
||||||
|
let allTags = await PlacesUtils.bookmarks.fetchTags();
|
||||||
|
for (let i of allTags) {
|
||||||
|
if (i.name == aTag) {
|
||||||
|
return i.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTagRoot() {
|
||||||
|
var query = histsvc.getNewQuery();
|
||||||
|
var opts = histsvc.getNewQueryOptions();
|
||||||
|
opts.resultType = opts.RESULTS_AS_TAGS_ROOT;
|
||||||
|
var resultRoot = histsvc.executeQuery(query, opts).root;
|
||||||
|
return resultRoot;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Runs a tag query and ensures that the tags returned are those and only those
|
* Runs a tag query and ensures that the tags returned are those and only those
|
||||||
* in aTags. aTags may be empty, in which case this function ensures that no
|
* in aTags. aTags may be empty, in which case this function ensures that no
|
||||||
|
|
|
@ -36,13 +36,20 @@ add_task(async function run_test() {
|
||||||
this._changedCount++;
|
this._changedCount++;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handlePlacesEvents(events) {
|
||||||
onItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI, aGuid) {
|
for (let event of events) {
|
||||||
if (aGuid == bookmark.guid) {
|
switch (event.type) {
|
||||||
PlacesUtils.bookmarks.removeObserver(this);
|
case "bookmark-removed":
|
||||||
|
if (event.guid == bookmark.guid) {
|
||||||
|
PlacesUtils.observers.removeListener(
|
||||||
|
["bookmark-removed"],
|
||||||
|
this.handlePlacesEvents
|
||||||
|
);
|
||||||
Assert.equal(this._changedCount, 2);
|
Assert.equal(this._changedCount, 2);
|
||||||
promise.resolve();
|
promise.resolve();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onBeginUpdateBatch() {},
|
onBeginUpdateBatch() {},
|
||||||
|
@ -51,6 +58,13 @@ add_task(async function run_test() {
|
||||||
onItemMoved() {},
|
onItemMoved() {},
|
||||||
};
|
};
|
||||||
PlacesUtils.bookmarks.addObserver(bookmarksObserver);
|
PlacesUtils.bookmarks.addObserver(bookmarksObserver);
|
||||||
|
bookmarksObserver.handlePlacesEvents = bookmarksObserver.handlePlacesEvents.bind(
|
||||||
|
bookmarksObserver
|
||||||
|
);
|
||||||
|
PlacesUtils.observers.addListener(
|
||||||
|
["bookmark-removed"],
|
||||||
|
bookmarksObserver.handlePlacesEvents
|
||||||
|
);
|
||||||
|
|
||||||
PlacesUtils.tagging.tagURI(uri, ["d"]);
|
PlacesUtils.tagging.tagURI(uri, ["d"]);
|
||||||
PlacesUtils.tagging.tagURI(uri, ["e"]);
|
PlacesUtils.tagging.tagURI(uri, ["e"]);
|
||||||
|
|
|
@ -64,9 +64,16 @@ function run_test() {
|
||||||
tagssvc.untagURI(uri1, ["tag 1"]);
|
tagssvc.untagURI(uri1, ["tag 1"]);
|
||||||
Assert.equal(tag1node.childCount, 1);
|
Assert.equal(tag1node.childCount, 1);
|
||||||
|
|
||||||
|
let wait = PlacesTestUtils.waitForNotification(
|
||||||
|
"bookmark-removed",
|
||||||
|
events => events.some(event => event.id == tagRoot.itemId),
|
||||||
|
"places"
|
||||||
|
);
|
||||||
// removing the last uri from a tag should remove the tag-container
|
// removing the last uri from a tag should remove the tag-container
|
||||||
tagssvc.untagURI(uri2, ["tag 1"]);
|
tagssvc.untagURI(uri2, ["tag 1"]);
|
||||||
|
wait.then(() => {
|
||||||
Assert.equal(tagRoot.childCount, 1);
|
Assert.equal(tagRoot.childCount, 1);
|
||||||
|
});
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
tag1node.containerOpen = false;
|
tag1node.containerOpen = false;
|
||||||
|
@ -116,8 +123,15 @@ function run_test() {
|
||||||
do_throw("Passing a sparse array should not throw");
|
do_throw("Passing a sparse array should not throw");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
wait = PlacesTestUtils.waitForNotification(
|
||||||
|
"bookmark-removed",
|
||||||
|
events => events.some(event => event.id == tagRoot.itemId),
|
||||||
|
"places"
|
||||||
|
);
|
||||||
tagssvc.untagURI(uri1, [undefined, "tagSparse"]);
|
tagssvc.untagURI(uri1, [undefined, "tagSparse"]);
|
||||||
|
wait.then(() => {
|
||||||
Assert.equal(tagRoot.childCount, curChildCount);
|
Assert.equal(tagRoot.childCount, curChildCount);
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
do_throw("Passing a sparse array should not throw");
|
do_throw("Passing a sparse array should not throw");
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,6 +420,7 @@ module.exports = {
|
||||||
Permissions: false,
|
Permissions: false,
|
||||||
PlacesBookmark: false,
|
PlacesBookmark: false,
|
||||||
PlacesBookmarkAddition: false,
|
PlacesBookmarkAddition: false,
|
||||||
|
PlacesBookmarkRemoved: false,
|
||||||
PlacesEvent: false,
|
PlacesEvent: false,
|
||||||
PlacesObservers: false,
|
PlacesObservers: false,
|
||||||
PlacesVisit: false,
|
PlacesVisit: false,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче