Bug 1678607: Implement a mechanism to fire bookmark-tags-changed event. r=mak

Differential Revision: https://phabricator.services.mozilla.com/D128326
This commit is contained in:
Daisuke Akatsuka 2021-10-17 22:47:36 +00:00
Родитель 2bba3cec69
Коммит ef8ed2e02d
7 изменённых файлов: 250 добавлений и 70 удалений

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

@ -0,0 +1,49 @@
/* -*- 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_PlacesBookmarkTags_h
#define mozilla_dom_PlacesBookmarkTags_h
#include "mozilla/dom/PlacesBookmarkChanged.h"
namespace mozilla {
namespace dom {
class PlacesBookmarkTags final : public PlacesBookmarkChanged {
public:
explicit PlacesBookmarkTags()
: PlacesBookmarkChanged(PlacesEventType::Bookmark_tags_changed) {}
static already_AddRefed<PlacesBookmarkTags> Constructor(
const GlobalObject& aGlobal, const PlacesBookmarkTagsInit& aInitDict) {
RefPtr<PlacesBookmarkTags> event = new PlacesBookmarkTags();
event->mId = aInitDict.mId;
event->mItemType = aInitDict.mItemType;
event->mUrl = aInitDict.mUrl;
event->mGuid = aInitDict.mGuid;
event->mParentGuid = aInitDict.mParentGuid;
event->mLastModified = aInitDict.mLastModified;
event->mSource = aInitDict.mSource;
event->mIsTagging = aInitDict.mIsTagging;
return event.forget();
}
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override {
return PlacesBookmarkTags_Binding::Wrap(aCx, this, aGivenProto);
}
const PlacesBookmarkTags* AsPlacesBookmarkTags() const override {
return this;
}
private:
~PlacesBookmarkTags() = default;
};
} // namespace dom
} // namespace mozilla
#endif

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

@ -47,6 +47,9 @@ class PlacesEvent : public nsWrapperCache {
virtual const PlacesBookmarkGuid* AsPlacesBookmarkGuid() const {
return nullptr;
}
virtual const PlacesBookmarkTags* AsPlacesBookmarkTags() const {
return nullptr;
}
virtual const PlacesBookmarkTime* AsPlacesBookmarkTime() const {
return nullptr;
}

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

@ -226,6 +226,7 @@ EXPORTS.mozilla.dom += [
"PlacesBookmarkGuid.h",
"PlacesBookmarkMoved.h",
"PlacesBookmarkRemoved.h",
"PlacesBookmarkTags.h",
"PlacesBookmarkTime.h",
"PlacesBookmarkTitle.h",
"PlacesBookmarkUrl.h",

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

@ -24,6 +24,10 @@ enum PlacesEventType {
* data: PlacesBookmarkGuid. Fired whenever a bookmark guid changes.
*/
"bookmark-guid-changed",
/**
* data: PlacesBookmarkTags. Fired whenever tags of bookmark changes.
*/
"bookmark-tags-changed",
/**
* data: PlacesBookmarkTime.
* Fired whenever dateAdded or lastModified of a bookmark is explicitly changed
@ -302,6 +306,22 @@ interface PlacesBookmarkGuid : PlacesBookmarkChanged {
constructor(PlacesBookmarkGuidInit initDict);
};
dictionary PlacesBookmarkTagsInit {
required long long id;
required unsigned short itemType;
DOMString? url = null;
required ByteString guid;
required ByteString parentGuid;
required long long lastModified;
required unsigned short source;
required boolean isTagging;
};
[ChromeOnly, Exposed=Window]
interface PlacesBookmarkTags : PlacesBookmarkChanged {
constructor(PlacesBookmarkTagsInit initDict);
};
dictionary PlacesBookmarkTimeInit {
required long long id;
required unsigned short itemType;

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

@ -320,20 +320,21 @@ var Bookmarks = Object.freeze({
url = item.url.href;
}
let notification = new PlacesBookmarkAddition({
id: itemId,
url,
itemType: item.type,
parentId: parent._id,
index: item.index,
title: item.title,
dateAdded: item.dateAdded,
guid: item.guid,
parentGuid: item.parentGuid,
source: item.source,
isTagging: isTagging || isTagsFolder,
});
PlacesObservers.notifyListeners([notification]);
const notifications = [
new PlacesBookmarkAddition({
id: itemId,
url,
itemType: item.type,
parentId: parent._id,
index: item.index,
title: item.title,
dateAdded: item.dateAdded,
guid: item.guid,
parentGuid: item.parentGuid,
source: item.source,
isTagging: isTagging || isTagsFolder,
}),
];
// If it's a tag, notify OnItemChanged to all bookmarks for this URL.
if (isTagging) {
@ -354,9 +355,24 @@ var Bookmarks = Object.freeze({
"",
item.source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,
itemType: entry.type,
url,
guid: entry.guid,
parentGuid: entry.parentGuid,
lastModified: entry.lastModified,
source: item.source,
isTagging: false,
})
);
}
}
PlacesObservers.notifyListeners(notifications);
// Remove non-enumerable properties.
delete item.source;
return Object.assign({}, item);
@ -931,6 +947,19 @@ var Bookmarks = Object.freeze({
"",
updatedItem.source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,
itemType: entry.type,
url: entry.url,
guid: entry.guid,
parentGuid: entry.parentGuid,
lastModified: entry.lastModified,
source: updatedItem.source,
isTagging: false,
})
);
}
}
}
@ -1352,6 +1381,19 @@ var Bookmarks = Object.freeze({
"",
options.source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,
itemType: entry.type,
url,
guid: entry.guid,
parentGuid: entry.parentGuid,
lastModified: entry.lastModified,
source: options.source,
isTagging: false,
})
);
}
}
}
@ -3328,6 +3370,19 @@ var removeFoldersContents = async function(db, folderGuids, options) {
"",
source,
]);
notifications.push(
new PlacesBookmarkTags({
id: entry._id,
itemType: entry.type,
url,
guid: entry.guid,
parentGuid: entry.parentGuid,
lastModified: entry.lastModified,
source,
isTagging: false,
})
);
}
}
}

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

@ -19,6 +19,7 @@
#include "mozilla/storage.h"
#include "mozilla/dom/PlacesBookmarkAddition.h"
#include "mozilla/dom/PlacesBookmarkRemoved.h"
#include "mozilla/dom/PlacesBookmarkTags.h"
#include "mozilla/dom/PlacesBookmarkTime.h"
#include "mozilla/dom/PlacesBookmarkTitle.h"
#include "mozilla/dom/PlacesObservers.h"
@ -421,29 +422,29 @@ nsNavBookmarks::InsertBookmark(int64_t aFolder, nsIURI* aURI, int32_t aIndex,
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
if (mCanNotify) {
Sequence<OwningNonNull<PlacesEvent>> events;
nsAutoCString utf8spec;
aURI->GetSpec(utf8spec);
RefPtr<PlacesBookmarkAddition> bookmark = new PlacesBookmarkAddition();
bookmark->mItemType = TYPE_BOOKMARK;
bookmark->mId = *aNewBookmarkId;
bookmark->mParentId = aFolder;
bookmark->mIndex = index;
bookmark->mUrl.Assign(NS_ConvertUTF8toUTF16(utf8spec));
bookmark->mTitle.Assign(NS_ConvertUTF8toUTF16(title));
bookmark->mDateAdded = dateAdded / 1000;
bookmark->mGuid.Assign(guid);
bookmark->mParentGuid.Assign(folderGuid);
bookmark->mSource = aSource;
bookmark->mIsTagging = grandParentId == mDB->GetTagsFolderId();
bool success = !!events.AppendElement(bookmark.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
PlacesObservers::NotifyListeners(events);
if (!mCanNotify) {
return NS_OK;
}
Sequence<OwningNonNull<PlacesEvent>> notifications;
nsAutoCString utf8spec;
aURI->GetSpec(utf8spec);
RefPtr<PlacesBookmarkAddition> bookmark = new PlacesBookmarkAddition();
bookmark->mItemType = TYPE_BOOKMARK;
bookmark->mId = *aNewBookmarkId;
bookmark->mParentId = aFolder;
bookmark->mIndex = index;
bookmark->mUrl.Assign(NS_ConvertUTF8toUTF16(utf8spec));
bookmark->mTitle.Assign(NS_ConvertUTF8toUTF16(title));
bookmark->mDateAdded = dateAdded / 1000;
bookmark->mGuid.Assign(guid);
bookmark->mParentGuid.Assign(folderGuid);
bookmark->mSource = aSource;
bookmark->mIsTagging = grandParentId == mDB->GetTagsFolderId();
bool success = !!notifications.AppendElement(bookmark.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
// If the bookmark has been added to a tag container, notify all
// bookmark-folder result nodes which contain a bookmark for the new
// bookmark's url.
@ -463,9 +464,23 @@ nsNavBookmarks::InsertBookmark(int64_t aFolder, nsIURI* aURI, int32_t aIndex,
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;
tagsChanged->mUrl.Assign(NS_ConvertUTF8toUTF16(utf8spec));
tagsChanged->mGuid = bookmarks[i].guid;
tagsChanged->mParentGuid = bookmarks[i].parentGuid;
tagsChanged->mLastModified = bookmarks[i].lastModified / 1000;
tagsChanged->mSource = aSource;
tagsChanged->mIsTagging = false;
success = !!notifications.AppendElement(tagsChanged.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
}
}
PlacesObservers::NotifyListeners(notifications);
return NS_OK;
}
@ -550,27 +565,28 @@ nsNavBookmarks::RemoveItem(int64_t aItemId, uint16_t aSource) {
NS_WARNING_ASSERTION(uri, "Invalid URI in RemoveItem");
}
if (mCanNotify) {
Sequence<OwningNonNull<PlacesEvent>> events;
RefPtr<PlacesBookmarkRemoved> bookmarkRef = new PlacesBookmarkRemoved();
bookmarkRef->mItemType = bookmark.type;
bookmarkRef->mId = bookmark.id;
bookmarkRef->mParentId = bookmark.parentId;
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 (!mCanNotify) {
return NS_OK;
}
Sequence<OwningNonNull<PlacesEvent>> notifications;
RefPtr<PlacesBookmarkRemoved> bookmarkRef = new PlacesBookmarkRemoved();
bookmarkRef->mItemType = bookmark.type;
bookmarkRef->mId = bookmark.id;
bookmarkRef->mParentId = bookmark.parentId;
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 = !!notifications.AppendElement(bookmarkRef.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
if (bookmark.type == TYPE_BOOKMARK && bookmark.grandParentId == tagsRootId &&
uri) {
// If the removed bookmark was child of a tag container, notify a tags
@ -579,6 +595,9 @@ nsNavBookmarks::RemoveItem(int64_t aItemId, uint16_t aSource) {
rv = GetBookmarksForURI(uri, bookmarks);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString utf8spec;
uri->GetSpec(utf8spec);
for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
NOTIFY_BOOKMARKS_OBSERVERS(
mCanNotify, mObservers,
@ -586,9 +605,23 @@ nsNavBookmarks::RemoveItem(int64_t aItemId, uint16_t aSource) {
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;
tagsChanged->mUrl.Assign(NS_ConvertUTF8toUTF16(utf8spec));
tagsChanged->mGuid = bookmarks[i].guid;
tagsChanged->mParentGuid = bookmarks[i].parentGuid;
tagsChanged->mLastModified = bookmarks[i].lastModified / 1000;
tagsChanged->mSource = aSource;
tagsChanged->mIsTagging = false;
success = !!notifications.AppendElement(tagsChanged.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
}
}
PlacesObservers::NotifyListeners(notifications);
return NS_OK;
}
@ -856,21 +889,24 @@ nsresult nsNavBookmarks::RemoveFolderChildren(int64_t aFolderId,
NS_WARNING_ASSERTION(uri, "Invalid URI in RemoveFolderChildren");
}
if (mCanNotify) {
RefPtr<PlacesBookmarkRemoved> bookmark = new PlacesBookmarkRemoved();
bookmark->mItemType = TYPE_BOOKMARK;
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 = !!notifications.AppendElement(bookmark.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
if (!mCanNotify) {
return NS_OK;
}
RefPtr<PlacesBookmarkRemoved> bookmark = new PlacesBookmarkRemoved();
bookmark->mItemType = TYPE_BOOKMARK;
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 = !!notifications.AppendElement(bookmark.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
if (child.type == TYPE_BOOKMARK && child.grandParentId == tagsRootId &&
uri) {
// If the removed bookmark was a child of a tag container, notify all
@ -880,6 +916,9 @@ nsresult nsNavBookmarks::RemoveFolderChildren(int64_t aFolderId,
rv = GetBookmarksForURI(uri, bookmarks);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString utf8spec;
uri->GetSpec(utf8spec);
for (uint32_t i = 0; i < bookmarks.Length(); ++i) {
NOTIFY_BOOKMARKS_OBSERVERS(
mCanNotify, mObservers,
@ -887,11 +926,23 @@ nsresult nsNavBookmarks::RemoveFolderChildren(int64_t aFolderId,
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;
tagsChanged->mUrl.Assign(NS_ConvertUTF8toUTF16(utf8spec));
tagsChanged->mGuid = bookmarks[i].guid;
tagsChanged->mParentGuid = bookmarks[i].parentGuid;
tagsChanged->mLastModified = bookmarks[i].lastModified / 1000;
tagsChanged->mSource = aSource;
tagsChanged->mIsTagging = false;
success = !!notifications.AppendElement(tagsChanged.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
}
}
}
if (notifications.Length() > 0) {
if (notifications.Length()) {
PlacesObservers::NotifyListeners(notifications);
}

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

@ -432,6 +432,7 @@ module.exports = {
PlacesBookmarkGuid: false,
PlacesBookmarkMoved: false,
PlacesBookmarkRemoved: false,
PlacesBookmarkTags: false,
PlacesBookmarkTime: false,
PlacesBookmarkTitle: false,
PlacesBookmarkUrl: false,