Bug 1678607: Apply bookmark-tags-changed event. r=mak

Depends on D128326

Differential Revision: https://phabricator.services.mozilla.com/D128327
This commit is contained in:
Daisuke Akatsuka 2021-10-18 04:43:44 +00:00
Родитель 4e72afc41d
Коммит b3393c1f45
16 изменённых файлов: 193 добавлений и 331 удалений

Просмотреть файл

@ -343,7 +343,12 @@ var gEditItemOverlay = {
PlacesUtils.bookmarks.addObserver(this);
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
PlacesUtils.observers.addListener(
["bookmark-moved", "bookmark-title-changed", "bookmark-url-changed"],
[
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-title-changed",
"bookmark-url-changed",
],
this.handlePlacesEvents
);
window.addEventListener("unload", this);
@ -561,7 +566,12 @@ var gEditItemOverlay = {
if (this._observersAdded) {
PlacesUtils.bookmarks.removeObserver(this);
PlacesUtils.observers.removeListener(
["bookmark-moved", "bookmark-title-changed", "bookmark-url-changed"],
[
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-title-changed",
"bookmark-url-changed",
],
this.handlePlacesEvents
);
window.removeEventListener("unload", this);
@ -1154,6 +1164,11 @@ var gEditItemOverlay = {
bm.title
);
break;
case "bookmark-tags-changed":
if (this._paneInfo.visibleRows.has("tagsRow")) {
this._onTagsChange(event.guid).catch(Cu.reportError);
}
break;
case "bookmark-title-changed":
if (this._paneInfo.isItem || this._paneInfo.isTag) {
// This also updates titles of folders in the folder menu list.
@ -1291,11 +1306,6 @@ var gEditItemOverlay = {
aParentId,
aGuid
) {
if (aProperty == "tags" && this._paneInfo.visibleRows.has("tagsRow")) {
this._onTagsChange(aGuid).catch(Cu.reportError);
return;
}
if (!this._paneInfo.isItem || this._paneInfo.itemId != aItemId) {
return;
}

Просмотреть файл

@ -34,11 +34,15 @@ add_task(async function() {
);
let promiseTagResetNotification = PlacesTestUtils.waitForNotification(
"onItemChanged",
(itemId, prop) => {
let tags = PlacesUtils.tagging.getTagsForURI(uri);
return prop == "tags" && tags.length == 1 && tags[0] == "tag1";
}
"bookmark-tags-changed",
events =>
events.some(event => {
const tags = PlacesUtils.tagging.getTagsForURI(
Services.io.newURI(event.url)
);
return tags.length === 1 && tags[0] === "tag1";
}),
"places"
);
await withBookmarksDialog(
@ -60,11 +64,15 @@ add_task(async function() {
Assert.ok(!namepicker.readOnly, "Name field should not be read-only");
Assert.equal(namepicker.value, "tag1", "Node title is correct");
let promiseTagChangeNotification = PlacesTestUtils.waitForNotification(
"onItemChanged",
(itemId, prop) => {
let tags = PlacesUtils.tagging.getTagsForURI(uri);
return prop == "tags" && tags.length == 1 && tags[0] == "tag2";
}
"bookmark-tags-changed",
events =>
events.some(event => {
const tags = PlacesUtils.tagging.getTagsForURI(
Services.io.newURI(event.url)
);
return tags.length === 1 && tags[0] === "tag2";
}),
"places"
);
let promiseTagRemoveNotification = PlacesTestUtils.waitForNotification(

Просмотреть файл

@ -103,8 +103,9 @@ add_task(async function test_add_bookmark_tags_from_bookmarkProperties() {
// Click the bookmark star again, add more tags.
await clickBookmarkStar();
promiseNotification = PlacesTestUtils.waitForNotification(
"onItemChanged",
(id, property) => property == "tags"
"bookmark-tags-changed",
() => true,
"places"
);
await fillBookmarkTextField(
"editBMPanel_tagsField",

Просмотреть файл

@ -56,8 +56,9 @@ add_task(async function test_remove_tags_from_BookmarkStar() {
);
let promiseTagsChange = PlacesTestUtils.waitForNotification(
"onItemChanged",
(id, property) => property === "tags"
"bookmark-tags-changed",
() => true,
"places"
);
// Update the "tags" field.
@ -119,8 +120,9 @@ add_task(async function test_remove_tags_from_Toolbar() {
);
let promiseTagsChange = PlacesTestUtils.waitForNotification(
"onItemChanged",
(id, property) => property === "tags"
"bookmark-tags-changed",
() => true,
"places"
);
// Update the "tags" field.
@ -174,8 +176,9 @@ add_task(async function test_remove_tags_from_Sidebar() {
);
let promiseTagsChange = PlacesTestUtils.waitForNotification(
"onItemChanged",
(id, property) => property === "tags"
"bookmark-tags-changed",
() => true,
"places"
);
// Update the "tags" field.

Просмотреть файл

@ -23,8 +23,9 @@ add_task(async function() {
// add a tag
document.getElementById("editBMPanel_tagsField").value = testTag;
let promiseNotification = PlacesTestUtils.waitForNotification(
"onItemChanged",
(id, property) => property == "tags"
"bookmark-tags-changed",
() => true,
"places"
);
gEditItemOverlay.onTagsFieldChange();
await promiseNotification;

Просмотреть файл

@ -73,8 +73,9 @@ add_task(async function test_tags() {
);
let promiseNotification = PlacesTestUtils.waitForNotification(
"onItemChanged",
(id, property) => property == "tags"
"bookmark-tags-changed",
() => true,
"places"
);
ContentTree.view.controller.doCommand("cmd_delete");

Просмотреть файл

@ -809,6 +809,7 @@ BookmarksTracker.prototype = {
"bookmark-added",
"bookmark-removed",
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-time-changed",
"bookmark-title-changed",
"bookmark-url-changed",
@ -827,6 +828,7 @@ BookmarksTracker.prototype = {
"bookmark-added",
"bookmark-removed",
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-time-changed",
"bookmark-title-changed",
"bookmark-url-changed",
@ -886,6 +888,7 @@ BookmarksTracker.prototype = {
case "bookmark-removed":
case "bookmark-moved":
case "bookmark-guid-changed":
case "bookmark-tags-changed":
case "bookmark-time-changed":
case "bookmark-title-changed":
case "bookmark-url-changed":

Просмотреть файл

@ -336,26 +336,11 @@ var Bookmarks = Object.freeze({
}),
];
// If it's a tag, notify OnItemChanged to all bookmarks for this URL.
// If it's a tag, notify bookmark-tags-changed event to all bookmarks for this URL.
if (isTagging) {
let observers = PlacesUtils.bookmarks.getObservers();
for (let entry of await fetchBookmarksByURL(item, {
concurrent: true,
})) {
notify(observers, "onItemChanged", [
entry._id,
"tags",
false,
"",
PlacesUtils.toPRTime(entry.lastModified),
entry.type,
entry._parentId,
entry.guid,
entry.parentGuid,
"",
item.source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,
@ -868,9 +853,6 @@ var Bookmarks = Object.freeze({
const notifications = [];
// Notify onItemChanged to listeners.
let observers = PlacesUtils.bookmarks.getObservers();
// For lastModified, we only care about the original input, since we
// should not notify implicit lastModified changes.
if (
@ -934,20 +916,6 @@ var Bookmarks = Object.freeze({
{ tags: [updatedItem.title] },
{ concurrent: true }
)) {
notify(observers, "onItemChanged", [
entry._id,
"tags",
false,
"",
PlacesUtils.toPRTime(entry.lastModified),
entry.type,
entry._parentId,
entry.guid,
entry.parentGuid,
"",
updatedItem.source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,
@ -1342,7 +1310,6 @@ var Bookmarks = Object.freeze({
let notifications = [];
for (let item of removeItems) {
let observers = PlacesUtils.bookmarks.getObservers();
let isUntagging = item._grandParentId == PlacesUtils.tagsFolderId;
let url = "";
if (item.type == Bookmarks.TYPE_BOOKMARK) {
@ -1368,20 +1335,6 @@ var Bookmarks = Object.freeze({
for (let entry of await fetchBookmarksByURL(item, {
concurrent: true,
})) {
notify(observers, "onItemChanged", [
entry._id,
"tags",
false,
"",
PlacesUtils.toPRTime(entry.lastModified),
entry.type,
entry._parentId,
entry.guid,
entry.parentGuid,
"",
options.source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,
@ -1897,38 +1850,6 @@ var Bookmarks = Object.freeze({
// Globals.
/**
* Sends a bookmarks notification through the given observers.
*
* @param {Array} observers
* array of nsINavBookmarkObserver objects.
* @param {String} notification
* the notification name.
* @param {Array} [args]
* array of arguments to pass to the notification.
* @param {Object} [information]
* Information about the notification, so we can filter based
* based on the observer's preferences.
*/
function notify(observers, notification, args = [], information = {}) {
for (let observer of observers) {
if (information.isTagging && observer.skipTags) {
continue;
}
if (
information.isDescendantRemoval &&
!PlacesUtils.bookmarks.userContentRoots.includes(information.parentGuid)
) {
continue;
}
try {
observer[notification](...args);
} catch (ex) {}
}
}
// Update implementation.
/**
@ -3330,7 +3251,6 @@ var removeFoldersContents = async function(db, folderGuids, options) {
// Notify listeners in reverse order to serve children before parents.
let { source = Bookmarks.SOURCES.DEFAULT } = options;
let observers = PlacesUtils.bookmarks.getObservers();
let notifications = [];
for (let item of itemsRemoved.reverse()) {
let isUntagging = item._grandParentId == PlacesUtils.tagsFolderId;
@ -3357,20 +3277,6 @@ var removeFoldersContents = async function(db, folderGuids, options) {
if (isUntagging) {
for (let entry of await fetchBookmarksByURL(item, true)) {
notify(observers, "onItemChanged", [
entry._id,
"tags",
false,
"",
PlacesUtils.toPRTime(entry.lastModified),
entry.type,
entry._parentId,
entry.guid,
entry.parentGuid,
"",
source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,

Просмотреть файл

@ -457,14 +457,6 @@ nsNavBookmarks::InsertBookmark(int64_t aFolder, nsIURI* aURI, int32_t aIndex,
for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
// Check that bookmarks doesn't include the current tag itemId.
MOZ_ASSERT(bookmarks[i].id != *aNewBookmarkId);
NOTIFY_BOOKMARKS_OBSERVERS(
mCanNotify, mObservers,
OnItemChanged(bookmarks[i].id, "tags"_ns, false, ""_ns,
bookmarks[i].lastModified, TYPE_BOOKMARK,
bookmarks[i].parentId, bookmarks[i].guid,
bookmarks[i].parentGuid, ""_ns, aSource));
RefPtr<PlacesBookmarkTags> tagsChanged = new PlacesBookmarkTags();
tagsChanged->mId = bookmarks[i].id;
tagsChanged->mItemType = TYPE_BOOKMARK;
@ -599,13 +591,6 @@ nsNavBookmarks::RemoveItem(int64_t aItemId, uint16_t aSource) {
uri->GetSpec(utf8spec);
for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
NOTIFY_BOOKMARKS_OBSERVERS(
mCanNotify, mObservers,
OnItemChanged(bookmarks[i].id, "tags"_ns, false, ""_ns,
bookmarks[i].lastModified, TYPE_BOOKMARK,
bookmarks[i].parentId, bookmarks[i].guid,
bookmarks[i].parentGuid, ""_ns, aSource));
RefPtr<PlacesBookmarkTags> tagsChanged = new PlacesBookmarkTags();
tagsChanged->mId = bookmarks[i].id;
tagsChanged->mItemType = TYPE_BOOKMARK;
@ -920,13 +905,6 @@ nsresult nsNavBookmarks::RemoveFolderChildren(int64_t aFolderId,
uri->GetSpec(utf8spec);
for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
NOTIFY_BOOKMARKS_OBSERVERS(
mCanNotify, mObservers,
OnItemChanged(bookmarks[i].id, "tags"_ns, false, ""_ns,
bookmarks[i].lastModified, TYPE_BOOKMARK,
bookmarks[i].parentId, bookmarks[i].guid,
bookmarks[i].parentGuid, ""_ns, aSource));
RefPtr<PlacesBookmarkTags> tagsChanged = new PlacesBookmarkTags();
tagsChanged->mId = bookmarks[i].id;
tagsChanged->mItemType = TYPE_BOOKMARK;

Просмотреть файл

@ -22,6 +22,7 @@
#include "mozilla/dom/PlacesVisitRemoved.h"
#include "mozilla/dom/PlacesVisitTitle.h"
#include "mozilla/dom/PlacesBookmarkMoved.h"
#include "mozilla/dom/PlacesBookmarkTags.h"
#include "mozilla/dom/PlacesBookmarkTime.h"
#include "mozilla/dom/PlacesBookmarkTitle.h"
#include "mozilla/dom/PlacesBookmarkUrl.h"
@ -2483,25 +2484,6 @@ nsNavHistoryQueryResultNode::OnItemChanged(
return Refresh();
}
// Some node could observe both bookmarks and history. But a node observing
// only history should never get a bookmark notification.
NS_WARNING_ASSERTION(
mResult && mResult->mIsBookmarksObserver,
"history observers should not get OnItemChanged, but should get the "
"corresponding history notifications instead");
// Tags in history queries are a special case since tags are per uri and
// we filter tags based on searchterms.
if (aItemType == nsINavBookmarksService::TYPE_BOOKMARK &&
aProperty.EqualsLiteral("tags")) {
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIURI> uri;
nsresult rv = bookmarks->GetBookmarkURI(aItemId, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
rv = NotifyIfTagsChanged(uri);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -2522,6 +2504,19 @@ nsresult nsNavHistoryQueryResultNode::OnItemMoved(
return NS_OK;
}
nsresult nsNavHistoryQueryResultNode::OnItemTagsChanged(int64_t aItemId,
const nsAString& aURL) {
nsresult rv = nsNavHistoryResultNode::OnItemTagsChanged(aItemId, aURL);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), aURL);
NS_ENSURE_SUCCESS(rv, rv);
rv = NotifyIfTagsChanged(uri);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult nsNavHistoryQueryResultNode::OnItemUrlChanged(int64_t aItemId,
const nsACString& aGUID,
const nsACString& aURL,
@ -3193,6 +3188,24 @@ nsresult nsNavHistoryFolderResultNode::OnItemRemoved(
return RemoveChildAt(index);
}
nsresult nsNavHistoryResultNode::OnItemTagsChanged(int64_t aItemId,
const nsAString& aURL) {
if (aItemId != mItemId) {
return NS_OK;
}
mTags.SetIsVoid(true);
bool shouldNotify = !mParent || mParent->AreChildrenVisible();
if (shouldNotify) {
nsNavHistoryResult* result = GetResult();
NS_ENSURE_STATE(result);
NOTIFY_RESULT_OBSERVERS(result, NodeTagsChanged(this));
}
return NS_OK;
}
nsresult nsNavHistoryResultNode::OnItemTimeChanged(int64_t aItemId,
const nsACString& aGUID,
PRTime aDateAdded,
@ -3305,9 +3318,6 @@ nsNavHistoryResultNode::OnItemChanged(
NOTIFY_RESULT_OBSERVERS(
result, NodeHistoryDetailsChanged(this, oldTime, mAccessCount));
}
} else if (aProperty.EqualsLiteral("tags")) {
mTags.SetIsVoid(true);
if (shouldNotify) NOTIFY_RESULT_OBSERVERS(result, NodeTagsChanged(this));
} else if (aProperty.EqualsLiteral("keyword")) {
if (shouldNotify)
NOTIFY_RESULT_OBSERVERS(result, NodeKeywordChanged(this, aNewValue));
@ -3583,7 +3593,7 @@ nsNavHistoryResult::~nsNavHistoryResult() {
}
void nsNavHistoryResult::StopObserving() {
AutoTArray<PlacesEventType, 10> events;
AutoTArray<PlacesEventType, 11> events;
events.AppendElement(PlacesEventType::Favicon_changed);
if (mIsBookmarksObserver) {
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
@ -3594,6 +3604,7 @@ void nsNavHistoryResult::StopObserving() {
events.AppendElement(PlacesEventType::Bookmark_added);
events.AppendElement(PlacesEventType::Bookmark_removed);
events.AppendElement(PlacesEventType::Bookmark_moved);
events.AppendElement(PlacesEventType::Bookmark_tags_changed);
events.AppendElement(PlacesEventType::Bookmark_time_changed);
events.AppendElement(PlacesEventType::Bookmark_title_changed);
events.AppendElement(PlacesEventType::Bookmark_url_changed);
@ -3717,10 +3728,11 @@ void nsNavHistoryResult::EnsureIsObservingBookmarks() {
return;
}
bookmarks->AddObserver(this, true);
AutoTArray<PlacesEventType, 7> events;
AutoTArray<PlacesEventType, 8> events;
events.AppendElement(PlacesEventType::Bookmark_added);
events.AppendElement(PlacesEventType::Bookmark_removed);
events.AppendElement(PlacesEventType::Bookmark_moved);
events.AppendElement(PlacesEventType::Bookmark_tags_changed);
events.AppendElement(PlacesEventType::Bookmark_time_changed);
events.AppendElement(PlacesEventType::Bookmark_title_changed);
events.AppendElement(PlacesEventType::Bookmark_url_changed);
@ -4291,6 +4303,18 @@ void nsNavHistoryResult::HandlePlacesEvent(const PlacesEventSequence& aEvents) {
item->mParentGuid, item->mSource, url));
break;
}
case PlacesEventType::Bookmark_tags_changed: {
const dom::PlacesBookmarkTags* tagsEvent =
event->AsPlacesBookmarkTags();
if (NS_WARN_IF(!tagsEvent)) {
continue;
}
ENUMERATE_BOOKMARK_CHANGED_OBSERVERS(
tagsEvent->mParentGuid, tagsEvent->mId,
OnItemTagsChanged(tagsEvent->mId, tagsEvent->mUrl));
break;
}
case PlacesEventType::Bookmark_time_changed: {
const dom::PlacesBookmarkTime* timeEvent =
event->AsPlacesBookmarkTime();

Просмотреть файл

@ -314,6 +314,7 @@ class nsNavHistoryResultNode : public nsINavHistoryResultNode {
virtual void OnRemoving();
nsresult OnItemTagsChanged(int64_t aItemId, const nsAString& aURL);
nsresult OnItemTimeChanged(int64_t aItemId, const nsACString& aGUID,
PRTime aDateAdded, PRTime aLastModified);
nsresult OnItemTitleChanged(int64_t aItemId, const nsACString& aGUID,
@ -700,6 +701,7 @@ class nsNavHistoryQueryResultNode final
const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID, uint16_t aSource,
const nsACString& aURI);
nsresult OnItemTagsChanged(int64_t aItemId, const nsAString& aURL);
nsresult OnItemUrlChanged(int64_t aItemId, const nsACString& aGUID,
const nsACString& aURL, PRTime aLastModified);

Просмотреть файл

@ -123,6 +123,19 @@ function expectPlacesObserverNotifications(
isTagging: event.isTagging,
});
break;
case "bookmark-tags-changed":
notifications.push({
type: event.type,
id: event.id,
itemType: event.itemType,
url: event.url,
guid: event.guid,
parentGuid: event.parentGuid,
lastModified: new Date(event.lastModified),
source: event.source,
isTagging: event.isTagging,
});
break;
case "bookmark-time-changed":
notifications.push({
type: event.type,

Просмотреть файл

@ -150,15 +150,16 @@ add_task(async function insert_bookmark_tag_notification() {
url: new URL("http://tag.example.com/"),
});
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
let tagFolder = await PlacesUtils.bookmarks.insert({
type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentGuid: PlacesUtils.bookmarks.tagsGuid,
title: "tag",
});
let placesObserver = expectPlacesObserverNotifications(["bookmark-added"]);
let bookmarksObserver = expectNotifications();
const observer = expectPlacesObserverNotifications([
"bookmark-added",
"bookmark-tags-changed",
]);
let tag = await PlacesUtils.bookmarks.insert({
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentGuid: tagFolder.guid,
@ -167,7 +168,7 @@ add_task(async function insert_bookmark_tag_notification() {
let tagId = await PlacesUtils.promiseItemId(tag.guid);
let tagParentId = await PlacesUtils.promiseItemId(tag.parentGuid);
placesObserver.check([
observer.check([
{
type: "bookmark-added",
id: tagId,
@ -182,24 +183,16 @@ add_task(async function insert_bookmark_tag_notification() {
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: true,
},
]);
bookmarksObserver.check([
{
name: "onItemChanged",
arguments: [
itemId,
"tags",
false,
"",
PlacesUtils.toPRTime(bm.lastModified),
bm.type,
parentId,
bm.guid,
bm.parentGuid,
"",
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
],
type: "bookmark-tags-changed",
id: itemId,
itemType: bm.type,
url: bm.url,
guid: bm.guid,
parentGuid: bm.parentGuid,
lastModified: bm.lastModified,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: false,
},
]);
});
@ -545,7 +538,6 @@ add_task(async function remove_bookmark_tag_notification() {
url: new URL("http://untag.example.com/"),
});
let itemId = await PlacesUtils.promiseItemId(bm.guid);
let parentId = await PlacesUtils.promiseItemId(bm.parentGuid);
let tagFolder = await PlacesUtils.bookmarks.insert({
type: PlacesUtils.bookmarks.TYPE_FOLDER,
@ -560,11 +552,13 @@ add_task(async function remove_bookmark_tag_notification() {
let tagId = await PlacesUtils.promiseItemId(tag.guid);
let tagParentId = await PlacesUtils.promiseItemId(tag.parentGuid);
let placesObserver = expectPlacesObserverNotifications(["bookmark-removed"]);
let observer = expectNotifications();
const observer = expectPlacesObserverNotifications([
"bookmark-removed",
"bookmark-tags-changed",
]);
await PlacesUtils.bookmarks.remove(tag.guid);
placesObserver.check([
observer.check([
{
type: "bookmark-removed",
id: tagId,
@ -577,23 +571,16 @@ add_task(async function remove_bookmark_tag_notification() {
itemType: PlacesUtils.bookmarks.TYPE_BOOKMARK,
isTagging: true,
},
]);
observer.check([
{
name: "onItemChanged",
arguments: [
itemId,
"tags",
false,
"",
PlacesUtils.toPRTime(bm.lastModified),
bm.type,
parentId,
bm.guid,
bm.parentGuid,
"",
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
],
type: "bookmark-tags-changed",
id: itemId,
itemType: bm.type,
url: bm.url,
guid: bm.guid,
parentGuid: bm.parentGuid,
lastModified: bm.lastModified,
source: Ci.nsINavBookmarksService.SOURCE_DEFAULT,
isTagging: false,
},
]);
});
@ -993,35 +980,3 @@ add_task(async function update_notitle_notification() {
},
]);
});
function expectNotifications() {
let notifications = [];
let observer = new Proxy(NavBookmarkObserver, {
get(target, name) {
if (name == "check") {
PlacesUtils.bookmarks.removeObserver(observer);
return expectedNotifications =>
Assert.deepEqual(notifications, expectedNotifications);
}
if (name.startsWith("onItem")) {
return (...origArgs) => {
let args = Array.from(origArgs, arg => {
if (arg && arg instanceof Ci.nsIURI) {
return new URL(arg.spec);
}
return arg;
});
notifications.push({ name, arguments: args });
};
}
if (name in target) {
return target[name];
}
return undefined;
},
});
PlacesUtils.bookmarks.addObserver(observer);
return observer;
}

Просмотреть файл

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that each nsINavBookmarksObserver method gets the correct input.
// Tests that each bookmark event gets the correct input.
var gUnfiledFolderId;
@ -35,34 +35,9 @@ var gBookmarksObserver = {
}
},
validate(aMethodName, aArguments) {
Assert.equal(this.expected[0].name, aMethodName);
let args = this.expected.shift().args;
Assert.equal(aArguments.length, args.length);
for (let i = 0; i < aArguments.length; i++) {
Assert.ok(
args[i].check(aArguments[i]),
aMethodName + "(args[" + i + "]: " + args[i].name + ")"
);
}
if (this.expected.length === 0) {
this.deferred.resolve();
}
},
handlePlacesEvents(events) {
this.validateEvents(events);
},
// nsINavBookmarkObserver
onItemChanged() {
return this.validate("onItemChanged", arguments);
},
// nsISupports
QueryInterface: ChromeUtils.generateQI(["nsINavBookmarkObserver"]),
};
var gBookmarkSkipObserver = {
@ -88,29 +63,12 @@ var gBookmarkSkipObserver = {
}
},
validate(aMethodName) {
Assert.equal(this.expected.shift(), aMethodName);
if (this.expected.length === 0) {
this.deferred.resolve();
}
},
handlePlacesEvents(events) {
this.validateEvents(events);
},
// nsINavBookmarkObserver
onItemChanged() {
return this.validate("onItemChanged", arguments);
},
// nsISupports
QueryInterface: ChromeUtils.generateQI(["nsINavBookmarkObserver"]),
};
add_task(async function setup() {
PlacesUtils.bookmarks.addObserver(gBookmarksObserver);
PlacesUtils.bookmarks.addObserver(gBookmarkSkipObserver);
gUnfiledFolderId = await PlacesUtils.promiseItemId(
PlacesUtils.bookmarks.unfiledGuid
);
@ -125,6 +83,7 @@ add_task(async function setup() {
"bookmark-added",
"bookmark-removed",
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-title-changed",
],
gBookmarksObserver.handlePlacesEvents
@ -134,6 +93,7 @@ add_task(async function setup() {
"bookmark-added",
"bookmark-removed",
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-title-changed",
],
gBookmarkSkipObserver.handlePlacesEvents
@ -268,7 +228,7 @@ add_task(async function bookmarkItemAdded_folder() {
await promise;
});
add_task(async function onItemChanged_title_bookmark() {
add_task(async function bookmarkTitleChanged() {
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0,
@ -304,7 +264,7 @@ add_task(async function onItemChanged_title_bookmark() {
await promise;
});
add_task(async function onItemChanged_tags_bookmark() {
add_task(async function bookmarkTagsChanged() {
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0,
@ -312,7 +272,10 @@ add_task(async function onItemChanged_tags_bookmark() {
let uri = Services.io.newURI(bm.url.href);
const TAG = "tag";
let promise = Promise.all([
gBookmarkSkipObserver.setup(["onItemChanged", "onItemChanged"]),
gBookmarkSkipObserver.setup([
"bookmark-tags-changed",
"bookmark-tags-changed",
]),
gBookmarksObserver.setup([
{
eventType: "bookmark-added", // This is the tag folder.
@ -371,18 +334,13 @@ add_task(async function onItemChanged_tags_bookmark() {
],
},
{
name: "onItemChanged",
eventType: "bookmark-tags-changed",
args: [
{ name: "itemId", check: v => typeof v == "number" && v > 0 },
{ name: "property", check: v => v === "tags" },
{ name: "isAnno", check: v => v === false },
{ name: "newValue", check: v => v === "" },
{ name: "lastModified", check: v => typeof v == "number" && v > 0 },
{ name: "id", check: v => typeof v == "number" && v > 0 },
{
name: "itemType",
check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK,
},
{ name: "parentId", check: v => v === gUnfiledFolderId },
{
name: "guid",
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
@ -391,12 +349,16 @@ add_task(async function onItemChanged_tags_bookmark() {
name: "parentGuid",
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
},
{ name: "oldValue", check: v => typeof v == "string" },
{ name: "lastModified", check: v => typeof v == "number" && v > 0 },
{
name: "source",
check: v =>
Object.values(PlacesUtils.bookmarks.SOURCES).includes(v),
},
{
name: "isTagging",
check: v => v === false,
},
],
},
{
@ -425,20 +387,14 @@ add_task(async function onItemChanged_tags_bookmark() {
},
],
},
{
name: "onItemChanged",
eventType: "bookmark-tags-changed",
args: [
{ name: "itemId", check: v => typeof v == "number" && v > 0 },
{ name: "property", check: v => v === "tags" },
{ name: "isAnno", check: v => v === false },
{ name: "newValue", check: v => v === "" },
{ name: "lastModified", check: v => typeof v == "number" && v > 0 },
{ name: "id", check: v => typeof v == "number" && v > 0 },
{
name: "itemType",
check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK,
},
{ name: "parentId", check: v => v === gUnfiledFolderId },
{
name: "guid",
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
@ -447,12 +403,16 @@ add_task(async function onItemChanged_tags_bookmark() {
name: "parentGuid",
check: v => typeof v == "string" && PlacesUtils.isValidGuid(v),
},
{ name: "oldValue", check: v => typeof v == "string" },
{ name: "lastModified", check: v => typeof v == "number" && v > 0 },
{
name: "source",
check: v =>
Object.values(PlacesUtils.bookmarks.SOURCES).includes(v),
},
{
name: "isTagging",
check: v => v === false,
},
],
},
{
@ -952,14 +912,24 @@ add_task(async function bookmarkItemRemoved_folder_recursive() {
});
add_task(function cleanup() {
PlacesUtils.bookmarks.removeObserver(gBookmarksObserver);
PlacesUtils.bookmarks.removeObserver(gBookmarkSkipObserver);
PlacesUtils.observers.removeListener(
["bookmark-added"],
[
"bookmark-added",
"bookmark-removed",
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-title-changed",
],
gBookmarksObserver.handlePlacesEvents
);
PlacesUtils.observers.removeListener(
["bookmark-added"],
[
"bookmark-added",
"bookmark-removed",
"bookmark-moved",
"bookmark-tags-changed",
"bookmark-title-changed",
],
gBookmarkSkipObserver.handlePlacesEvents
);
});

Просмотреть файл

@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
// This test checks that changing a tag for a bookmark with multiple tags
// notifies OnItemChanged("tags") only once, and not once per tag.
// notifies bookmark-tags-changed event only once, and not once per tag.
add_task(async function run_test() {
let tags = ["a", "b", "c"];
@ -18,24 +18,7 @@ add_task(async function run_test() {
let promise = PromiseUtils.defer();
let bookmarksObserver = {
QueryInterface: ChromeUtils.generateQI(["nsINavBookmarkObserver"]),
_changedCount: 0,
onItemChanged(
aItemId,
aProperty,
aIsAnnotationProperty,
aValue,
aLastModified,
aItemType,
aParentId,
aGuid
) {
if (aProperty == "tags") {
Assert.equal(aGuid, bookmark.guid);
this._changedCount++;
}
},
handlePlacesEvents(events) {
for (let event of events) {
switch (event.type) {
@ -48,16 +31,20 @@ add_task(async function run_test() {
Assert.equal(this._changedCount, 2);
promise.resolve();
}
break;
case "bookmark-tags-changed":
Assert.equal(event.guid, bookmark.guid);
this._changedCount++;
break;
}
}
},
};
PlacesUtils.bookmarks.addObserver(bookmarksObserver);
bookmarksObserver.handlePlacesEvents = bookmarksObserver.handlePlacesEvents.bind(
bookmarksObserver
);
PlacesUtils.observers.addListener(
["bookmark-removed"],
["bookmark-removed", "bookmark-tags-changed"],
bookmarksObserver.handlePlacesEvents
);

Просмотреть файл

@ -39,6 +39,7 @@ skip-if = os == "linux" # Bug 821781
[test_1606731.js]
[test_asyncExecuteLegacyQueries.js]
[test_async_transactions.js]
[test_bookmark-tags-changed_frequency.js]
[test_bookmarks_json.js]
[test_bookmarks_json_corrupt.js]
[test_bookmarks_html.js]
@ -75,7 +76,6 @@ support-files = noRoot.sqlite
[test_multi_word_tags.js]
[test_nsINavHistoryViewer.js]
[test_null_interfaces.js]
[test_onItemChanged_tags.js]
[test_origins.js]
[test_origins_parsing.js]
[test_pageGuid_bookmarkGuid.js]