Bug 1460849 - Allow new items (as well as existing) to be skipped in nsNavHistoryFolderResultNode::OnItemMoved if excludeItems is set. r=mak
authorMark Banner <standard8@mozilla.com>
Fri, 11 May 2018 13:23:41 +0100
changeset 472696 e3c0dd79cbfc5c57e65aa0f671a8c3cf446b4dfe
parent 472695 54538505ee0a40b4eac7ca35cfbfe870118089b2
child 472697 7358416f54f4676032ff99747b65630aefb398b9
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs1460849
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1460849 - Allow new items (as well as existing) to be skipped in nsNavHistoryFolderResultNode::OnItemMoved if excludeItems is set. r=mak MozReview-Commit-ID: CUCAsmG99A8
toolkit/components/places/Bookmarks.jsm
toolkit/components/places/SyncedBookmarksMirror.jsm
toolkit/components/places/nsINavBookmarksService.idl
toolkit/components/places/nsNavHistoryResult.cpp
toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
toolkit/components/places/tests/bookmarks/test_nsINavBookmarkObserver.js
toolkit/components/places/tests/sync/head_sync.js
toolkit/components/places/tests/sync/test_bookmark_structure_changes.js
toolkit/components/places/tests/sync/test_bookmark_value_changes.js
--- a/toolkit/components/places/Bookmarks.jsm
+++ b/toolkit/components/places/Bookmarks.jsm
@@ -781,17 +781,18 @@ var Bookmarks = Object.freeze({
         // If the item was moved, notify onItemMoved.
         if (item.parentGuid != updatedItem.parentGuid ||
             item.index != updatedItem.index) {
           notify(observers, "onItemMoved", [ updatedItem._id, item._parentId,
                                              item.index, updatedItem._parentId,
                                              updatedItem.index, updatedItem.type,
                                              updatedItem.guid, item.parentGuid,
                                              updatedItem.parentGuid,
-                                             updatedItem.source ]);
+                                             updatedItem.source,
+                                             updatedItem.url && updatedItem.url.href ]);
         }
 
         // Remove non-enumerable properties.
         delete updatedItem.source;
         return Object.assign({}, updatedItem);
       });
     })();
   },
@@ -1195,17 +1196,17 @@ var Bookmarks = Object.freeze({
       // Note that child.index is the old index.
       for (let i = 0; i < sortedChildren.length; ++i) {
         let child = sortedChildren[i];
         notify(observers, "onItemMoved", [ child._id, child._parentId,
                                            child.index, child._parentId,
                                            i, child.type,
                                            child.guid, child.parentGuid,
                                            child.parentGuid,
-                                           source ]);
+                                           source, child.url && child.url.href ]);
       }
     })();
   },
 
   /**
    * Searches a list of bookmark-items by a search term, url or title.
    *
    * IMPORTANT:
--- a/toolkit/components/places/SyncedBookmarksMirror.jsm
+++ b/toolkit/components/places/SyncedBookmarksMirror.jsm
@@ -1442,32 +1442,34 @@ class SyncedBookmarksMirror {
       };
       observersToNotify.noteItemAdded(info);
     }
 
     MirrorLog.trace("Recording observer notifications for moved items");
     let movedItemRows = await this.db.execute(`
       SELECT b.id, b.guid, b.type, p.id AS newParentId, c.oldParentId,
              p.guid AS newParentGuid, c.oldParentGuid,
-             b.position AS newPosition, c.oldPosition
+             b.position AS newPosition, c.oldPosition, h.url
       FROM itemsMoved c
       JOIN moz_bookmarks b ON b.id = c.itemId
       JOIN moz_bookmarks p ON p.id = b.parent
+      LEFT JOIN moz_places h ON h.id = b.fk
       ORDER BY c.level, newParentId, newPosition`);
     for await (let row of yieldingIterator(movedItemRows)) {
       let info = {
         id: row.getResultByName("id"),
         guid: row.getResultByName("guid"),
         type: row.getResultByName("type"),
         newParentId: row.getResultByName("newParentId"),
         oldParentId: row.getResultByName("oldParentId"),
         newParentGuid: row.getResultByName("newParentGuid"),
         oldParentGuid: row.getResultByName("oldParentGuid"),
         newPosition: row.getResultByName("newPosition"),
         oldPosition: row.getResultByName("oldPosition"),
+        urlHref: row.getResultByName("url"),
       };
       observersToNotify.noteItemMoved(info);
     }
 
     MirrorLog.trace("Recording observer notifications for changed items");
     let changedItemRows = await this.db.execute(`
       SELECT b.id, b.guid, b.lastModified, b.type,
              IFNULL(b.title, "") AS newTitle,
@@ -4598,17 +4600,17 @@ class BookmarkObserverRecorder {
   }
 
   noteItemMoved(info) {
     this.bookmarkObserverNotifications.push({
       name: "onItemMoved",
       isTagging: false,
       args: [info.id, info.oldParentId, info.oldPosition, info.newParentId,
         info.newPosition, info.type, info.guid, info.oldParentGuid,
-        info.newParentGuid, PlacesUtils.bookmarks.SOURCES.SYNC],
+        info.newParentGuid, PlacesUtils.bookmarks.SOURCES.SYNC, info.urlHref],
     });
   }
 
   noteItemChanged(info) {
     if (info.oldTitle != info.newTitle) {
       this.bookmarkObserverNotifications.push({
         name: "onItemChanged",
         isTagging: false,
--- a/toolkit/components/places/nsINavBookmarksService.idl
+++ b/toolkit/components/places/nsINavBookmarksService.idl
@@ -241,27 +241,30 @@ interface nsINavBookmarkObserver : nsISu
    *        The unique ID associated with the item.
    * @param aOldParentGuid
    *        The unique ID associated with the old item's parent.
    * @param aNewParentGuid
    *        The unique ID associated with the new item's parent.
    * @param aSource
    *        A change source constant from nsINavBookmarksService::SOURCE_*,
    *        passed to the method that notifies the observer.
+   * @param aURI
+   *        The URI for this bookmark.
    */
   void onItemMoved(in long long aItemId,
                    in long long aOldParentId,
                    in long aOldIndex,
                    in long long aNewParentId,
                    in long aNewIndex,
                    in unsigned short aItemType,
                    in ACString aGuid,
                    in ACString aOldParentGuid,
                    in ACString aNewParentGuid,
-                   in unsigned short aSource);
+                   in unsigned short aSource,
+                   in AUTF8String aURI);
 };
 
 /**
  * The BookmarksService interface provides methods for managing bookmarked
  * history items.  Bookmarks consist of a set of user-customizable
  * folders.  A URI in history can be contained in one or more such folders.
  */
 
--- a/toolkit/components/places/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -3027,17 +3027,18 @@ nsNavHistoryQueryResultNode::OnItemMoved
                                          int64_t aOldParent,
                                          int32_t aOldIndex,
                                          int64_t aNewParent,
                                          int32_t aNewIndex,
                                          uint16_t aItemType,
                                          const nsACString& aGUID,
                                          const nsACString& aOldParentGUID,
                                          const nsACString& aNewParentGUID,
-                                         uint16_t aSource)
+                                         uint16_t aSource,
+                                         const nsACString& aURI)
 {
   // 1. The query cannot be affected by the item's position
   // 2. For the time being, we cannot optimize this not to update
   //    queries which are not restricted to some folders, due to way
   //    sub-queries are updated (see Refresh)
   if (mLiveUpdate == QUERYUPDATE_COMPLEX_WITH_BOOKMARKS &&
       aItemType != nsINavBookmarksService::TYPE_SEPARATOR &&
       aOldParent != aNewParent) {
@@ -3986,41 +3987,46 @@ nsNavHistoryFolderResultNode::OnItemMove
                                           int64_t aOldParent,
                                           int32_t aOldIndex,
                                           int64_t aNewParent,
                                           int32_t aNewIndex,
                                           uint16_t aItemType,
                                           const nsACString& aGUID,
                                           const nsACString& aOldParentGUID,
                                           const nsACString& aNewParentGUID,
-                                          uint16_t aSource)
+                                          uint16_t aSource,
+                                          const nsACString& aURI)
 {
   NS_ASSERTION(aOldParent == mTargetFolderItemId || aNewParent == mTargetFolderItemId,
                "Got a bookmark message that doesn't belong to us");
 
   RESTART_AND_RETURN_IF_ASYNC_PENDING();
 
+  bool excludeItems = mOptions->ExcludeItems();
+  if (excludeItems &&
+      (aItemType == nsINavBookmarksService::TYPE_SEPARATOR ||
+       (aItemType == nsINavBookmarksService::TYPE_BOOKMARK &&
+        !StringBeginsWith(aURI, NS_LITERAL_CSTRING("place:"))))) {
+    // This is a bookmark or a separator, so we don't need to handle this if
+    // we're excluding items.
+    return NS_OK;
+  }
+
   uint32_t index;
   nsNavHistoryResultNode* node = FindChildById(aItemId, &index);
   // Bug 1097528.
   // It's possible our result registered due to a previous notification, for
   // example the Library left pane could have refreshed and replaced the
   // right pane as a consequence. In such a case our contents are already
   // up-to-date.  That's OK.
   if (node && aNewParent == mTargetFolderItemId && index == static_cast<uint32_t>(aNewIndex))
     return NS_OK;
   if (!node && aOldParent == mTargetFolderItemId)
     return NS_OK;
 
-  bool excludeItems = mOptions->ExcludeItems();
-  if (node && excludeItems && (node->IsURI() || node->IsSeparator())) {
-    // Don't update items when we aren't displaying them.
-    return NS_OK;
-  }
-
   if (!StartIncrementalUpdate())
     return NS_OK; // entire container was refreshed for us
 
   if (aOldParent == aNewParent) {
     // getting moved within the same folder, we don't want to do a remove and
     // an add because that will lose your tree state.
 
     // adjust bookmark indices
@@ -4665,35 +4671,36 @@ nsNavHistoryResult::OnItemMoved(int64_t 
                                 int64_t aOldParent,
                                 int32_t aOldIndex,
                                 int64_t aNewParent,
                                 int32_t aNewIndex,
                                 uint16_t aItemType,
                                 const nsACString& aGUID,
                                 const nsACString& aOldParentGUID,
                                 const nsACString& aNewParentGUID,
-                                uint16_t aSource)
+                                uint16_t aSource,
+                                const nsACString& aURI)
 {
   ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aOldParent,
       OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex,
-                  aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource));
+                  aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource, aURI));
   if (aNewParent != aOldParent) {
     ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aNewParent,
         OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex,
-                    aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource));
+                    aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource, aURI));
   }
   ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex,
                                                 aNewParent, aNewIndex,
                                                 aItemType, aGUID,
                                                 aOldParentGUID,
-                                                aNewParentGUID, aSource));
+                                                aNewParentGUID, aSource, aURI));
   ENUMERATE_HISTORY_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex,
                                           aNewParent, aNewIndex, aItemType,
                                           aGUID, aOldParentGUID,
-                                          aNewParentGUID, aSource));
+                                          aNewParentGUID, aSource, aURI));
   return NS_OK;
 }
 
 
 nsresult
 nsNavHistoryResult::OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
                             uint32_t aTransitionType, const nsACString& aGUID, bool aHidden,
                             uint32_t aVisitCount, const nsAString& aLastKnownTitle)
--- a/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
+++ b/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js
@@ -188,30 +188,32 @@ add_task(async function update_move_same
   let observer = expectNotifications();
   bm = await PlacesUtils.bookmarks.update({ guid: bm.guid,
                                             parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                             index: 0 });
   Assert.equal(bm.index, 0);
   observer.check([ { name: "onItemMoved",
                      arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
                                   bm.type, bm.guid, bm.parentGuid, bm.parentGuid,
-                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT,
+                                  "http://move.example.com/" ] }
                  ]);
 
   // Test that we get the right index for DEFAULT_INDEX input.
   bmOldIndex = 0;
   observer = expectNotifications();
   bm = await PlacesUtils.bookmarks.update({ guid: bm.guid,
                                             parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                             index: PlacesUtils.bookmarks.DEFAULT_INDEX });
   Assert.ok(bm.index > 0);
   observer.check([ { name: "onItemMoved",
                      arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
                                   bm.type, bm.guid, bm.parentGuid, bm.parentGuid,
-                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT,
+                                  bm.url ] }
                  ]);
 });
 
 add_task(async function update_move_different_folder() {
   let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                                 url: new URL("http://move.example.com/") });
   let folder = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
@@ -226,17 +228,18 @@ add_task(async function update_move_diff
                                             index: PlacesUtils.bookmarks.DEFAULT_INDEX });
   Assert.equal(bm.index, 0);
   let bmNewParentId = await PlacesUtils.promiseItemId(folder.guid);
   observer.check([ { name: "onItemMoved",
                      arguments: [ bmItemId, bmOldParentId, bmOldIndex, bmNewParentId,
                                   bm.index, bm.type, bm.guid,
                                   PlacesUtils.bookmarks.unfiledGuid,
                                   bm.parentGuid,
-                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
+                                  Ci.nsINavBookmarksService.SOURCE_DEFAULT,
+                                  "http://move.example.com/" ] }
                  ]);
 });
 
 add_task(async function remove_bookmark() {
   let bm = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
                                                 parentGuid: PlacesUtils.bookmarks.unfiledGuid,
                                                 url: new URL("http://remove.example.com/") });
   let itemId = await PlacesUtils.promiseItemId(bm.guid);
@@ -517,17 +520,18 @@ add_task(async function reorder_notifica
                                               PlacesUtils.unfiledBookmarksFolderId,
                                               child.index,
                                               PlacesUtils.unfiledBookmarksFolderId,
                                               i,
                                               child.type,
                                               child.guid,
                                               child.parentGuid,
                                               child.parentGuid,
-                                              Ci.nsINavBookmarksService.SOURCE_DEFAULT
+                                              Ci.nsINavBookmarksService.SOURCE_DEFAULT,
+                                              child.url
                                             ] });
   }
   observer.check(expectedNotifications);
 });
 
 add_task(async function update_notitle_notification() {
   let toolbarBmURI = Services.io.newURI("https://example.com");
   let toolbarBmId =
--- a/toolkit/components/places/tests/bookmarks/test_nsINavBookmarkObserver.js
+++ b/toolkit/components/places/tests/bookmarks/test_nsINavBookmarkObserver.js
@@ -328,29 +328,31 @@ add_task(async function onItemMoved_book
           { name: "oldIndex", check: v => v === 0 },
           { name: "newParentId", check: v => v === PlacesUtils.toolbarFolderId },
           { name: "newIndex", check: v => v === 0 },
           { name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
           { name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
           { name: "oldParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
           { name: "newParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
           { name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
+          { name: "url", check: v => typeof(v) == "string" },
         ] },
       { name: "onItemMoved",
         args: [
           { name: "itemId", check: v => typeof(v) == "number" && v > 0 },
           { name: "oldParentId", check: v => v === PlacesUtils.toolbarFolderId },
           { name: "oldIndex", check: v => v === 0 },
           { name: "newParentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
           { name: "newIndex", check: v => v === 0 },
           { name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
           { name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
           { name: "oldParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
           { name: "newParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
           { name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
+          { name: "url", check: v => typeof(v) == "string" },
         ] },
   ])]);
   await PlacesUtils.bookmarks.update({
     guid: bm.guid,
     parentGuid: PlacesUtils.bookmarks.toolbarGuid,
     index: 0
   });
   await PlacesUtils.bookmarks.update({
--- a/toolkit/components/places/tests/sync/head_sync.js
+++ b/toolkit/components/places/tests/sync/head_sync.js
@@ -248,21 +248,21 @@ BookmarkObserver.prototype = {
                    guid, parentGuid, oldValue, source };
     if (!this.ignoreDates) {
       params.lastModified = lastModified;
     }
     this.notifications.push({ name: "onItemChanged", params });
   },
   onItemVisited() {},
   onItemMoved(itemId, oldParentId, oldIndex, newParentId, newIndex, type, guid,
-              oldParentGuid, newParentGuid, source) {
+              oldParentGuid, newParentGuid, source, uri) {
     this.notifications.push({
       name: "onItemMoved",
       params: { itemId, oldParentId, oldIndex, newParentId, newIndex, type,
-                guid, oldParentGuid, newParentGuid, source },
+                guid, oldParentGuid, newParentGuid, source, uri },
     });
   },
 
   QueryInterface: ChromeUtils.generateQI([
     Ci.nsINavBookmarkObserver,
   ]),
 
   check(expectedNotifications) {
--- a/toolkit/components/places/tests/sync/test_bookmark_structure_changes.js
+++ b/toolkit/components/places/tests/sync/test_bookmark_structure_changes.js
@@ -110,27 +110,29 @@ add_task(async function test_value_struc
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkEEEE"),
               oldParentId: localItemIds.get("folderDDDDDD"),
               oldIndex: 1, newParentId: localItemIds.get("folderDDDDDD"),
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkEEEE",
               oldParentGuid: "folderDDDDDD",
               newParentGuid: "folderDDDDDD",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/e" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkBBBB"),
               oldParentId: localItemIds.get("folderDDDDDD"),
               oldIndex: 0, newParentId: localItemIds.get("folderDDDDDD"),
               newIndex: 1, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkBBBB",
               oldParentGuid: "folderDDDDDD",
               newParentGuid: "folderDDDDDD",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/b" },
   }, {
     name: "onItemChanged",
     params: { itemId: localItemIds.get("folderDDDDDD"), property: "title",
               isAnnoProperty: false, newValue: "D (remote)",
               type: PlacesUtils.bookmarks.TYPE_FOLDER,
               parentId: PlacesUtils.bookmarksMenuFolderId, guid: "folderDDDDDD",
               parentGuid: PlacesUtils.bookmarks.menuGuid, oldValue: "D",
               source: PlacesUtils.bookmarks.SOURCES.SYNC },
@@ -284,77 +286,84 @@ add_task(async function test_move() {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("devFolder___"),
               oldParentId: PlacesUtils.bookmarksMenuFolderId,
               oldIndex: 0, newParentId: PlacesUtils.toolbarFolderId,
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_FOLDER,
               guid: "devFolder___",
               oldParentGuid: PlacesUtils.bookmarks.menuGuid,
               newParentGuid: PlacesUtils.bookmarks.toolbarGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: null },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("mozFolder___"),
               oldParentId: localItemIds.get("devFolder___"),
               oldIndex: 1, newParentId: PlacesUtils.unfiledBookmarksFolderId,
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_FOLDER,
               guid: "mozFolder___",
               oldParentGuid: "devFolder___",
               newParentGuid: PlacesUtils.bookmarks.unfiledGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: null },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bzBmk_______"),
               oldParentId: PlacesUtils.bookmarksMenuFolderId,
               oldIndex: 1, newParentId: localItemIds.get("devFolder___"),
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bzBmk_______",
               oldParentGuid: PlacesUtils.bookmarks.menuGuid,
               newParentGuid: "devFolder___",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "https://bugzilla.mozilla.org/" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("wmBmk_______"),
               oldParentId: localItemIds.get("devFolder___"),
               oldIndex: 2, newParentId: localItemIds.get("devFolder___"),
               newIndex: 1, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "wmBmk_______",
               oldParentGuid: "devFolder___",
               newParentGuid: "devFolder___",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "https://webmaker.org/" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("nightlyBmk__"),
               oldParentId: localItemIds.get("mozFolder___"),
               oldIndex: 1, newParentId: localItemIds.get("mozFolder___"),
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "nightlyBmk__",
               oldParentGuid: "mozFolder___",
               newParentGuid: "mozFolder___",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "https://nightly.mozilla.org/" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("mdnBmk______"),
               oldParentId: localItemIds.get("devFolder___"),
               oldIndex: 0, newParentId: localItemIds.get("mozFolder___"),
               newIndex: 1, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "mdnBmk______",
               oldParentGuid: "devFolder___",
               newParentGuid: "mozFolder___",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "https://developer.mozilla.org/" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("fxBmk_______"),
               oldParentId: localItemIds.get("mozFolder___"),
               oldIndex: 0, newParentId: localItemIds.get("mozFolder___"),
               newIndex: 2, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "fxBmk_______",
               oldParentGuid: "mozFolder___",
               newParentGuid: "mozFolder___",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://getfirefox.com/" },
   }]);
 
   await assertLocalTree(PlacesUtils.bookmarks.rootGuid, {
     guid: PlacesUtils.bookmarks.rootGuid,
     type: PlacesUtils.bookmarks.TYPE_FOLDER,
     index: 0,
     title: "",
     children: [{
@@ -508,17 +517,18 @@ add_task(async function test_move_into_p
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkBBBB"),
               oldParentId: localItemIds.get("folderAAAAAA"),
               oldIndex: 0, newParentId: localItemIds.get("folderCCCCCC"),
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkBBBB",
               oldParentGuid: "folderAAAAAA",
               newParentGuid: "folderCCCCCC",
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/b" },
   }]);
 
   await assertLocalTree(PlacesUtils.bookmarks.menuGuid, {
     guid: PlacesUtils.bookmarks.menuGuid,
     type: PlacesUtils.bookmarks.TYPE_FOLDER,
     index: 0,
     title: BookmarksMenuTitle,
     children: [{
@@ -661,27 +671,29 @@ add_task(async function test_complex_mov
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkCCCC"),
               oldParentId: localItemIds.get("folderAAAAAA"),
               oldIndex: 1, newParentId: PlacesUtils.bookmarksMenuFolderId,
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkCCCC",
               oldParentGuid: "folderAAAAAA",
               newParentGuid: PlacesUtils.bookmarks.menuGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/c" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("folderAAAAAA"),
               oldParentId: PlacesUtils.bookmarksMenuFolderId,
               oldIndex: 0, newParentId: PlacesUtils.toolbarFolderId,
               newIndex: 0, type: PlacesUtils.bookmarks.TYPE_FOLDER,
               guid: "folderAAAAAA",
               oldParentGuid: PlacesUtils.bookmarks.menuGuid,
               newParentGuid: PlacesUtils.bookmarks.toolbarGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: null },
   }]);
 
   await assertLocalTree(PlacesUtils.bookmarks.rootGuid, {
     guid: PlacesUtils.bookmarks.rootGuid,
     type: PlacesUtils.bookmarks.TYPE_FOLDER,
     index: 0,
     title: "",
     children: [{
--- a/toolkit/components/places/tests/sync/test_bookmark_value_changes.js
+++ b/toolkit/components/places/tests/sync/test_bookmark_value_changes.js
@@ -140,17 +140,18 @@ add_task(async function test_value_combo
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bzBmk_______"),
               oldParentId: PlacesUtils.toolbarFolderId,
               oldIndex: 0, newParentId: PlacesUtils.toolbarFolderId,
               newIndex: 2, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bzBmk_______",
               oldParentGuid: PlacesUtils.bookmarks.toolbarGuid,
               newParentGuid: PlacesUtils.bookmarks.toolbarGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "https://bugzilla.mozilla.org/" },
   }, {
     name: "onItemChanged",
     params: { itemId: localItemIds.get("mozBmk______"), property: "title",
               isAnnoProperty: false, newValue: "Mozilla home page",
               type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               parentId: PlacesUtils.bookmarksMenuFolderId, guid: "mozBmk______",
               parentGuid: PlacesUtils.bookmarks.menuGuid, oldValue: "Mozilla",
               source: PlacesUtils.bookmarks.SOURCES.SYNC },
@@ -703,47 +704,51 @@ add_task(async function test_keywords_co
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkBBBB"),
               oldParentId: PlacesUtils.bookmarksMenuFolderId,
               oldIndex: 0, newParentId: PlacesUtils.bookmarksMenuFolderId,
               newIndex: 2, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkBBBB",
               oldParentGuid: PlacesUtils.bookmarks.menuGuid,
               newParentGuid: PlacesUtils.bookmarks.menuGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/b" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkCCCC"),
               oldParentId: PlacesUtils.bookmarksMenuFolderId,
               oldIndex: 1, newParentId: PlacesUtils.bookmarksMenuFolderId,
               newIndex: 3, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkCCCC",
               oldParentGuid: PlacesUtils.bookmarks.menuGuid,
               newParentGuid: PlacesUtils.bookmarks.menuGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/c-remote" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkDDDD"),
               oldParentId: PlacesUtils.bookmarksMenuFolderId,
               oldIndex: 2, newParentId: PlacesUtils.bookmarksMenuFolderId,
               newIndex: 4, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkDDDD",
               oldParentGuid: PlacesUtils.bookmarks.menuGuid,
               newParentGuid: PlacesUtils.bookmarks.menuGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/d" },
   }, {
     name: "onItemMoved",
     params: { itemId: localItemIds.get("bookmarkEEEE"),
               oldParentId: PlacesUtils.bookmarksMenuFolderId,
               oldIndex: 3, newParentId: PlacesUtils.bookmarksMenuFolderId,
               newIndex: 5, type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               guid: "bookmarkEEEE",
               oldParentGuid: PlacesUtils.bookmarks.menuGuid,
               newParentGuid: PlacesUtils.bookmarks.menuGuid,
-              source: PlacesUtils.bookmarks.SOURCES.SYNC },
+              source: PlacesUtils.bookmarks.SOURCES.SYNC,
+              uri: "http://example.com/e" },
   }, {
     name: "onItemChanged",
     params: { itemId: localItemIds.get("bookmarkCCCC"), property: "title",
               isAnnoProperty: false, newValue: "C (remote)",
               type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
               parentId: PlacesUtils.bookmarksMenuFolderId, guid: "bookmarkCCCC",
               parentGuid: PlacesUtils.bookmarks.menuGuid, oldValue: "C",
               source: PlacesUtils.bookmarks.SOURCES.SYNC },