Bug 961587: Only create Windows 8 Touch smart bookmark once a user has intialized their Metro bookmark list. r=mbrubeck, r=mak77
authorMarina Samuel <msamuel@mozilla.com>
Mon, 10 Mar 2014 12:53:19 -0400
changeset 191040 cb89890bd6c72656c7ec889f9484dadadad8b823
parent 191039 8f90256a56e8850f3edd7935f6f6fb49febecdd2
child 191041 403ef36f7d350022e2d613017e4f4b0f3c5a6379
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck, mak77
bugs961587
milestone30.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 961587: Only create Windows 8 Touch smart bookmark once a user has intialized their Metro bookmark list. r=mbrubeck, r=mak77
browser/components/nsBrowserGlue.js
browser/components/places/tests/unit/head_bookmarks.js
browser/locales/en-US/chrome/browser/places/places.properties
browser/metro/components/BrowserStartup.js
toolkit/locales/en-US/chrome/places/places.properties
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1628,17 +1628,17 @@ BrowserGlue.prototype = {
   ensurePlacesDefaultQueriesInitialized:
   function BG_ensurePlacesDefaultQueriesInitialized() {
     // This is actual version of the smart bookmarks, must be increased every
     // time smart bookmarks change.
     // When adding a new smart bookmark below, its newInVersion property must
     // be set to the version it has been added in, we will compare its value
     // to users' smartBookmarksVersion and add new smart bookmarks without
     // recreating old deleted ones.
-    const SMART_BOOKMARKS_VERSION = 6;
+    const SMART_BOOKMARKS_VERSION = 7;
     const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
     const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
 
     // TODO bug 399268: should this be a pref?
     const MAX_RESULTS = 10;
 
     // Get current smart bookmarks version.  If not set, create them.
     let smartBookmarksCurrentVersion = 0;
@@ -1660,76 +1660,86 @@ BrowserGlue.prototype = {
 
         let smartBookmarks = {
           MostVisited: {
             title: bundle.GetStringFromName("mostVisitedTitle"),
             uri: NetUtil.newURI("place:sort=" +
                                 Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
                                 "&maxResults=" + MAX_RESULTS),
             parent: PlacesUtils.toolbarFolderId,
-            position: toolbarIndex++,
+            get position() { return toolbarIndex++; },
             newInVersion: 1
           },
           RecentlyBookmarked: {
             title: bundle.GetStringFromName("recentlyBookmarkedTitle"),
             uri: NetUtil.newURI("place:folder=BOOKMARKS_MENU" +
                                 "&folder=UNFILED_BOOKMARKS" +
                                 "&folder=TOOLBAR" +
                                 "&queryType=" +
                                 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
                                 "&sort=" +
                                 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
                                 "&maxResults=" + MAX_RESULTS +
                                 "&excludeQueries=1"),
             parent: PlacesUtils.bookmarksMenuFolderId,
-            position: menuIndex++,
+            get position() { return menuIndex++; },
             newInVersion: 1
           },
           RecentTags: {
             title: bundle.GetStringFromName("recentTagsTitle"),
             uri: NetUtil.newURI("place:"+
                                 "type=" +
                                 Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
                                 "&sort=" +
                                 Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
                                 "&maxResults=" + MAX_RESULTS),
             parent: PlacesUtils.bookmarksMenuFolderId,
-            position: menuIndex++,
+            get position() { return menuIndex++; },
             newInVersion: 1
           },
         };
 
         if (Services.metro && Services.metro.supported) {
           smartBookmarks.Windows8Touch = {
-            title: bundle.GetStringFromName("windows8TouchTitle"),
-            uri: NetUtil.newURI("place:folder=" +
-                                PlacesUtils.annotations.getItemsWithAnnotation('metro/bookmarksRoot', {})[0] +
-                                "&queryType=" +
-                                Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
-                                "&sort=" +
-                                Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
-                                "&maxResults=" + MAX_RESULTS +
-                                "&excludeQueries=1"),
+            title: PlacesUtils.getString("windows8TouchTitle"),
+            get uri() {
+              let metroBookmarksRoot = PlacesUtils.annotations.getItemsWithAnnotation('metro/bookmarksRoot', {});
+              if (metroBookmarksRoot.length > 0) {
+                return NetUtil.newURI("place:folder=" +
+                                      metroBookmarksRoot[0] +
+                                      "&queryType=" +
+                                      Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
+                                      "&sort=" +
+                                      Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
+                                      "&maxResults=" + MAX_RESULTS +
+                                      "&excludeQueries=1")
+              }
+              return null;
+            },
             parent: PlacesUtils.bookmarksMenuFolderId,
-            position: menuIndex++,
-            newInVersion: 6
+            get position() { return menuIndex++; },
+            newInVersion: 7
           };
         }
 
         // Set current itemId, parent and position if Smart Bookmark exists,
         // we will use these informations to create the new version at the same
         // position.
         let smartBookmarkItemIds = PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
         smartBookmarkItemIds.forEach(function (itemId) {
           let queryId = PlacesUtils.annotations.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
           if (queryId in smartBookmarks) {
             let smartBookmark = smartBookmarks[queryId];
+            if (!smartBookmark.uri) {
+              PlacesUtils.bookmarks.removeItem(itemId);
+              return;
+            }
             smartBookmark.itemId = itemId;
             smartBookmark.parent = PlacesUtils.bookmarks.getFolderIdForItem(itemId);
-            smartBookmark.position = PlacesUtils.bookmarks.getItemIndex(itemId);
+            smartBookmark.updatedPosition = PlacesUtils.bookmarks.getItemIndex(itemId);
           }
           else {
             // We don't remove old Smart Bookmarks because user could still
             // find them useful, or could have personalized them.
             // Instead we remove the Smart Bookmark annotation.
             PlacesUtils.annotations.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
           }
         });
@@ -1737,30 +1747,30 @@ BrowserGlue.prototype = {
         for (let queryId in smartBookmarks) {
           let smartBookmark = smartBookmarks[queryId];
 
           // We update or create only changed or new smart bookmarks.
           // Also we respect user choices, so we won't try to create a smart
           // bookmark if it has been removed.
           if (smartBookmarksCurrentVersion > 0 &&
               smartBookmark.newInVersion <= smartBookmarksCurrentVersion &&
-              !smartBookmark.itemId)
+              !smartBookmark.itemId || !smartBookmark.uri)
             continue;
 
           // Remove old version of the smart bookmark if it exists, since it
           // will be replaced in place.
           if (smartBookmark.itemId) {
             PlacesUtils.bookmarks.removeItem(smartBookmark.itemId);
           }
 
           // Create the new smart bookmark and store its updated itemId.
           smartBookmark.itemId =
             PlacesUtils.bookmarks.insertBookmark(smartBookmark.parent,
                                                  smartBookmark.uri,
-                                                 smartBookmark.position,
+                                                 smartBookmark.updatedPosition || smartBookmark.position,
                                                  smartBookmark.title);
           PlacesUtils.annotations.setItemAnnotation(smartBookmark.itemId,
                                                     SMART_BOOKMARKS_ANNO,
                                                     queryId, 0,
                                                     PlacesUtils.annotations.EXPIRE_NEVER);
         }
 
         // If we are creating all Smart Bookmarks from ground up, add a
--- a/browser/components/places/tests/unit/head_bookmarks.js
+++ b/browser/components/places/tests/unit/head_bookmarks.js
@@ -58,16 +58,15 @@ let (XULAppInfo = {
   };
   let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
   registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"),
                             "XULAppInfo", "@mozilla.org/xre/app-info;1",
                             XULAppInfoFactory);
 }
 
 // Smart bookmarks constants.
-let isMetroSupported = Services.metro && Services.metro.supported;
-const SMART_BOOKMARKS_VERSION = 6
+const SMART_BOOKMARKS_VERSION = 7;
 const SMART_BOOKMARKS_ON_TOOLBAR = 1;
-const SMART_BOOKMARKS_ON_MENU = isMetroSupported ? 4 : 3; // Takes in count the additional separator.
+const SMART_BOOKMARKS_ON_MENU =  3; // Takes into account the additional separator.
 
 // Default bookmarks constants.
 const DEFAULT_BOOKMARKS_ON_TOOLBAR = 1;
 const DEFAULT_BOOKMARKS_ON_MENU = 1;
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -65,20 +65,16 @@ detailsPane.noItems=No items
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # #1 number of items
 # example: 111 items
 detailsPane.itemsCountLabel=One item;#1 items
 
 mostVisitedTitle=Most Visited
 recentlyBookmarkedTitle=Recently Bookmarked
 recentTagsTitle=Recent Tags
-# LOCALIZATION NOTE (windows8TouchTitle): this is the name of the folder used
-# to store bookmarks created in Metro mode and share bookmarks between Metro
-# and Desktop.
-windows8TouchTitle=Windows 8 Touch
 
 OrganizerQueryHistory=History
 OrganizerQueryDownloads=Downloads
 OrganizerQueryAllBookmarks=All Bookmarks
 OrganizerQueryTags=Tags
 
 # LOCALIZATION NOTE (tagResultLabel) :
 # Noun used to describe the location bar autocomplete result type
--- a/browser/metro/components/BrowserStartup.js
+++ b/browser/metro/components/BrowserStartup.js
@@ -3,16 +3,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+                                  "resource://gre/modules/PlacesUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
+                                  "resource://gre/modules/NetUtil.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Task",
+                                  "resource://gre/modules/Task.jsm");
+
 // Custom factory object to ensure that we're a singleton
 const BrowserStartupServiceFactory = {
   _instance: null,
   createInstance: function (outer, iid) {
     if (outer != null)
       throw Components.results.NS_ERROR_NO_AGGREGATION;
     return this._instance || (this._instance = new BrowserStartup());
   }
@@ -57,17 +64,45 @@ BrowserStartup.prototype = {
                   getService(Ci.nsIAnnotationService);
       let metroRootItems = annos.getItemsWithAnnotation("metro/bookmarksRoot", {});
       if (metroRootItems.length > 0)
         return; // no need to do initial import
     }
 
     Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm");
 
-    BookmarkJSONUtils.importFromURL("chrome://browser/locale/bookmarks.json", false);
+    Task.spawn(function() {
+      yield BookmarkJSONUtils.importFromURL("chrome://browser/locale/bookmarks.json", false);
+
+      // Create the new smart bookmark.
+      const MAX_RESULTS = 10;
+      const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
+
+      // Place the Metro folder at the end of the smart bookmarks list.
+      let maxIndex =  Math.max.apply(null,
+        PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO).map(id => {
+          return PlacesUtils.bookmarks.getItemIndex(id);
+        }));
+      let smartBookmarkId =
+        PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarksMenuFolderId,
+                                             NetUtil.newURI("place:folder=" +
+                                                            PlacesUtils.annotations.getItemsWithAnnotation('metro/bookmarksRoot', {})[0] +
+                                                            "&queryType=" +
+                                                            Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
+                                                            "&sort=" +
+                                                            Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
+                                                            "&maxResults=" + MAX_RESULTS +
+                                                            "&excludeQueries=1"),
+                                             maxIndex + 1,
+                                             PlacesUtils.getString("windows8TouchTitle"));
+      PlacesUtils.annotations.setItemAnnotation(smartBookmarkId,
+                                                SMART_BOOKMARKS_ANNO,
+                                                "Windows8Touch", 0,
+                                                PlacesUtils.annotations.EXPIRE_NEVER);
+    });
   },
 
   _startupActions: function() {
   },
 
   // nsIObserver
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
--- a/toolkit/locales/en-US/chrome/places/places.properties
+++ b/toolkit/locales/en-US/chrome/places/places.properties
@@ -25,8 +25,12 @@ finduri-MonthYear=%1$S %2$S
 localhost=(local files)
 
 # LOCALIZATION NOTE
 # The string is used for showing file size of each backup in the "fileRestorePopup" popup
 # %1$S is the file size
 # %2$S is the file size unit
 backupFileSizeText=%1$S %2$S
 
+# LOCALIZATION NOTE (windows8TouchTitle): this is the name of the folder used
+# to store bookmarks created in Metro mode and share bookmarks between Metro
+# and Desktop.
+windows8TouchTitle=Windows 8 Touch
\ No newline at end of file