Bug 493557 - Entries for "Recent Tags" and "Recently Bookmarked" are flipped on upgrade.
authorMarco Bonardo <mbonardo@mozilla.com>
Tue, 23 Nov 2010 14:04:07 +0100
changeset 59349 6cdfd382478d0ad089d34d727cd753d5baeecb9b
parent 59348 ac0b81efdb004863874b237de25a2c8a5e0a0598
child 59350 4ff3fc8162d8d59dce3e6a76518a1faa74f6a4da
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
bugs493557
milestone2.0b8pre
Bug 493557 - Entries for "Recent Tags" and "Recently Bookmarked" are flipped on upgrade. r=dietrich a=dietrich
browser/components/nsBrowserGlue.js
browser/components/places/tests/unit/test_browserGlue_smartBookmarks.js
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -52,16 +52,21 @@ const XULNS = "http://www.mozilla.org/ke
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
+XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() {
+  Cu.import("resource://gre/modules/PlacesUtils.jsm");
+  return PlacesUtils;
+});
+
 const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
 const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
 const PREF_PLUGINS_UPDATEURL  = "plugins.update.url";
 
 // We try to backup bookmarks at idle times, to avoid doing that at shutdown.
 // Number of idle seconds before trying to backup bookmarks.  15 minutes.
 const BOOKMARKS_BACKUP_IDLE_TIME = 15 * 60;
 // Minimum interval in milliseconds between backups.
@@ -759,34 +764,29 @@ BrowserGlue.prototype = {
    * - browser.bookmarks.restore_default_bookmarks
    *   Set to true by safe-mode dialog to indicate we must restore default
    *   bookmarks.
    */
   _initPlaces: function BG__initPlaces() {
     // We must instantiate the history service since it will tell us if we
     // need to import or restore bookmarks due to first-run, corruption or
     // forced migration (due to a major schema change).
-    var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
-                  getService(Ci.nsINavHistoryService);
-
     // If the database is corrupt or has been newly created we should
     // import bookmarks.
-    var databaseStatus = histsvc.databaseStatus;
-    var importBookmarks = databaseStatus == histsvc.DATABASE_STATUS_CREATE ||
-                          databaseStatus == histsvc.DATABASE_STATUS_CORRUPT;
+    var dbStatus = PlacesUtils.history.databaseStatus;
+    var importBookmarks = dbStatus == PlacesUtils.history.DATABASE_STATUS_CREATE ||
+                          dbStatus == PlacesUtils.history.DATABASE_STATUS_CORRUPT;
 
-    if (databaseStatus == histsvc.DATABASE_STATUS_CREATE) {
+    if (dbStatus == PlacesUtils.history.DATABASE_STATUS_CREATE) {
       // If the database has just been created, but we already have any
       // bookmark, this is not the initial import.  This can happen after a
       // migration from a different browser since migrators run before us.
       // In such a case we should not import, unless some pref has been set.
-      var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-                  getService(Ci.nsINavBookmarksService);
-      if (bmsvc.getIdForItemAt(bmsvc.bookmarksMenuFolder, 0) != -1 ||
-          bmsvc.getIdForItemAt(bmsvc.toolbarFolder, 0) != -1)
+      if (PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 0) != -1 ||
+          PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0) != -1)
         importBookmarks = false;
     }
 
     // Check if user or an extension has required to import bookmarks.html
     var importBookmarksHTML = false;
     try {
       importBookmarksHTML =
         Services.prefs.getBoolPref("browser.places.importBookmarksHTML");
@@ -806,17 +806,16 @@ BrowserGlue.prototype = {
         importBookmarks = true;
       }
     } catch(ex) {}
 
     // If the user did not require to restore default bookmarks, or import
     // from bookmarks.html, we will try to restore from JSON
     if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
       // get latest JSON backup
-      Cu.import("resource://gre/modules/PlacesUtils.jsm");
       var bookmarksBackupFile = PlacesUtils.backups.getMostRecent("json");
       if (bookmarksBackupFile) {
         // restore from JSON backup
         PlacesUtils.restoreBookmarksFromJSONFile(bookmarksBackupFile);
         importBookmarks = false;
       }
       else {
         // We have created a new database but we don't have any backup available
@@ -938,18 +937,16 @@ BrowserGlue.prototype = {
         backupBookmarksFile();
     }
   },
 
   /**
    * Backup bookmarks if needed.
    */
   _backupBookmarks: function BG__backupBookmarks() {
-    Cu.import("resource://gre/modules/PlacesUtils.jsm");
-
     let lastBackupFile = PlacesUtils.backups.getMostRecent();
 
     // Backup bookmarks if there are no backups or the maximum interval between
     // backups elapsed.
     if (!lastBackupFile ||
         new Date() - PlacesUtils.backups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_INTERVAL) {
       let maxBackups = BOOKMARKS_BACKUP_MAX_BACKUPS;
       try {
@@ -1129,151 +1126,143 @@ BrowserGlue.prototype = {
     // recreating old deleted ones.
     const SMART_BOOKMARKS_VERSION = 2;
     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
-    // By default, if the pref is not set up, we must create Smart Bookmarks
-    var smartBookmarksCurrentVersion = 0;
+    // Get current smart bookmarks version.  If not set, create them.
+    let smartBookmarksCurrentVersion = 0;
     try {
       smartBookmarksCurrentVersion = Services.prefs.getIntPref(SMART_BOOKMARKS_PREF);
-    } catch(ex) { /* no version set, new profile */ }
-
-    // bail out if we don't have to create or update Smart Bookmarks
-    if (smartBookmarksCurrentVersion == -1 ||
-        smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION)
-      return;
+    } catch(ex) {}
 
-    var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-                getService(Ci.nsINavBookmarksService);
-    var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
-                  getService(Ci.nsIAnnotationService);
+    // If version is current or smart bookmarks are disabled, just bail out.
+    if (smartBookmarksCurrentVersion == -1 ||
+        smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION) {
+      return;
+    }
 
-    var callback = {
-      _uri: function BG_EPDQI__uri(aSpec) {
-        return Services.io.newURI(aSpec, null, null);
-      },
-
+    let batch = {
       runBatched: function BG_EPDQI_runBatched() {
-        var smartBookmarks = [];
-        var bookmarksMenuIndex = 0;
-        var bookmarksToolbarIndex = 0;
+        let menuIndex = 0;
+        let toolbarIndex = 0;
+        let bundle = Services.strings.createBundle("chrome://browser/locale/places/places.properties");
 
-        var placesBundle = Services.strings.createBundle("chrome://browser/locale/places/places.properties");
-
-        // MOST VISITED
-        var smart = {queryId: "MostVisited", // don't change this
-                     itemId: null,
-                     title: placesBundle.GetStringFromName("mostVisitedTitle"),
-                     uri: this._uri("place:redirectsMode=" +
-                                    Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET +
-                                    "&sort=" +
-                                    Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
-                                    "&maxResults=" + MAX_RESULTS),
-                     parent: bmsvc.toolbarFolder,
-                     position: bookmarksToolbarIndex++,
-                     newInVersion: 1 };
-        smartBookmarks.push(smart);
-
-        // RECENTLY BOOKMARKED
-        smart = {queryId: "RecentlyBookmarked", // don't change this
-                 itemId: null,
-                 title: placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
-                 uri: this._uri("place:folder=BOOKMARKS_MENU" +
+        let smartBookmarks = {
+          MostVisited: {
+            title: bundle.GetStringFromName("mostVisitedTitle"),
+            uri: NetUtil.newURI("place:redirectsMode=" +
+                                Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET +
+                                "&sort=" +
+                                Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
+                                "&maxResults=" + MAX_RESULTS),
+            parent: PlacesUtils.toolbarFolderId,
+            position: 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 +
                                 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
                                 "&maxResults=" + MAX_RESULTS +
                                 "&excludeQueries=1"),
-                 parent: bmsvc.bookmarksMenuFolder,
-                 position: bookmarksMenuIndex++,
-                 newInVersion: 1 };
-        smartBookmarks.push(smart);
+            parent: PlacesUtils.bookmarksMenuFolderId,
+            position: 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++,
+            newInVersion: 1
+          },
+        };
 
-        // RECENT TAGS
-        smart = {queryId: "RecentTags", // don't change this
-                 itemId: null,
-                 title: placesBundle.GetStringFromName("recentTagsTitle"),
-                 uri: this._uri("place:"+
-                    "type=" +
-                    Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
-                    "&sort=" +
-                    Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
-                    "&maxResults=" + MAX_RESULTS),
-                 parent: bmsvc.bookmarksMenuFolder,
-                 position: bookmarksMenuIndex++,
-                 newInVersion: 1 };
-        smartBookmarks.push(smart);
-
-        var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO);
         // Set current itemId, parent and position if Smart Bookmark exists,
         // we will use these informations to create the new version at the same
         // position.
-        for each(var itemId in smartBookmarkItemIds) {
-          var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
-          for (var i = 0; i < smartBookmarks.length; i++){
-            if (smartBookmarks[i].queryId == queryId) {
-              smartBookmarks[i].found = true;
-              smartBookmarks[i].itemId = itemId;
-              smartBookmarks[i].parent = bmsvc.getFolderIdForItem(itemId);
-              smartBookmarks[i].position = bmsvc.getItemIndex(itemId);
-              // remove current item, since it will be replaced
-              bmsvc.removeItem(itemId);
-              break;
-            }
+        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];
+            smartBookmarks[queryId].itemId = itemId;
+            smartBookmarks[queryId].parent = PlacesUtils.bookmarks.getFolderIdForItem(itemId);
+            smartBookmarks[queryId].position = 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.
-            if (i == smartBookmarks.length - 1)
-              annosvc.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
+            PlacesUtils.annotations.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
           }
-        }
+        });
 
-        // create smart bookmarks
-        for each(var smartBookmark in smartBookmarks) {
+        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.found)
+              !smartBookmark.itemId)
             continue;
 
-          smartBookmark.itemId = bmsvc.insertBookmark(smartBookmark.parent,
-                                                      smartBookmark.uri,
-                                                      smartBookmark.position,
-                                                      smartBookmark.title);
-          annosvc.setItemAnnotation(smartBookmark.itemId,
-                                    SMART_BOOKMARKS_ANNO, smartBookmark.queryId,
-                                    0, annosvc.EXPIRE_NEVER);
+          // 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.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
         // separator below them in the bookmarks menu.
         if (smartBookmarksCurrentVersion == 0 &&
             smartBookmarkItemIds.length == 0) {
-          let id = bmsvc.getIdForItemAt(bmsvc.bookmarksMenuFolder,
-                                        bookmarksMenuIndex);
+          let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId,
+                                                        menuIndex);
           // Don't add a separator if the menu was empty or there is one already.
-          if (id != -1 && bmsvc.getItemType(id) != bmsvc.TYPE_SEPARATOR)
-            bmsvc.insertSeparator(bmsvc.bookmarksMenuFolder, bookmarksMenuIndex);
+          if (id != -1 &&
+              PlacesUtils.bookmarks.getItemType(id) != PlacesUtils.bookmarks.TYPE_SEPARATOR) {
+            PlacesUtils.bookmarks.insertSeparator(PlacesUtils.bookmarksMenuFolderId,
+                                                  menuIndex);
+          }
         }
       }
     };
 
     try {
-      bmsvc.runInBatchMode(callback, null);
+      PlacesUtils.bookmarks.runInBatchMode(batch, null);
     }
     catch(ex) {
       Components.utils.reportError(ex);
     }
     finally {
       Services.prefs.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION);
       Services.prefs.savePrefFile(null);
     }
--- a/browser/components/places/tests/unit/test_browserGlue_smartBookmarks.js
+++ b/browser/components/places/tests/unit/test_browserGlue_smartBookmarks.js
@@ -36,253 +36,334 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
  * Tests that nsBrowserGlue is correctly interpreting the preferences settable
  * by the user or by other components.
  */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-// Initialize Places.
-var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
-         getService(Ci.nsINavHistoryService);
-var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-         getService(Ci.nsINavBookmarksService);
-// Get other services.
-var ps = Cc["@mozilla.org/preferences-service;1"].
-         getService(Ci.nsIPrefBranch);
-var os = Cc["@mozilla.org/observer-service;1"].
-         getService(Ci.nsIObserverService);
-var as = Cc["@mozilla.org/browser/annotation-service;1"].
-         getService(Ci.nsIAnnotationService);
-
 const PREF_SMART_BOOKMARKS_VERSION = "browser.places.smartBookmarksVersion";
 const PREF_AUTO_EXPORT_HTML = "browser.bookmarks.autoExportHTML";
 const PREF_IMPORT_BOOKMARKS_HTML = "browser.places.importBookmarksHTML";
 const PREF_RESTORE_DEFAULT_BOOKMARKS = "browser.bookmarks.restore_default_bookmarks";
 
 const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
 
 /**
  * Rebuilds smart bookmarks listening to console output to report any message or
  * exception generated when calling ensurePlacesDefaultQueriesInitialized().
  */
 function rebuildSmartBookmarks() {
-  var consoleListener = {
+  let consoleListener = {
     observe: function(aMsg) {
       print("Got console message: " + aMsg.message);
     },
 
     QueryInterface: XPCOMUtils.generateQI([
       Ci.nsIConsoleListener
     ]),
   };
-  var console = Cc["@mozilla.org/consoleservice;1"].
-                getService(Ci.nsIConsoleService);
-  console.reset();
-  console.registerListener(consoleListener);
-  var bg = Cc["@mozilla.org/browser/browserglue;1"].
-           getService(Ci.nsIBrowserGlue);
-  bg.ensurePlacesDefaultQueriesInitialized();
-  console.unregisterListener(consoleListener);
+  Services.console.reset();
+  Services.console.registerListener(consoleListener);
+  Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue)
+                                          .ensurePlacesDefaultQueriesInitialized();
+  Services.console.unregisterListener(consoleListener);
 }
 
 
-var tests = [];
+let tests = [];
 //------------------------------------------------------------------------------
 
 tests.push({
   description: "All smart bookmarks are created if smart bookmarks version is 0.",
   exec: function() {
     // Sanity check: we should have default bookmark.
-    do_check_neq(bs.getIdForItemAt(bs.toolbarFolder, 0), -1);
-    do_check_neq(bs.getIdForItemAt(bs.bookmarksMenuFolder, 0), -1);
+    do_check_neq(PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0), -1);
+    do_check_neq(PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 0), -1);
 
     // Set preferences.
-    ps.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 0);
+    Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 0);
 
     rebuildSmartBookmarks();
 
     // Count items.
-    do_check_eq(countFolderChildren(bs.toolbarFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
                 SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
-    do_check_eq(countFolderChildren(bs.bookmarksMenuFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
                 SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
 
     // Check version has been updated.
-    do_check_eq(ps.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
+    do_check_eq(Services.prefs.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
                 SMART_BOOKMARKS_VERSION);
 
     next_test();
   }
 });
 
 //------------------------------------------------------------------------------
 
 tests.push({
   description: "An existing smart bookmark is replaced when version changes.",
   exec: function() {
     // Sanity check: we have a smart bookmark on the toolbar.
-    var itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
+    let itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
     do_check_neq(itemId, -1);
-    do_check_true(as.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
     // Change its title.
-    bs.setItemTitle(itemId, "new title");
-    do_check_eq(bs.getItemTitle(itemId), "new title");
+    PlacesUtils.bookmarks.setItemTitle(itemId, "new title");
+    do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "new title");
 
     // Sanity check items.
-    do_check_eq(countFolderChildren(bs.toolbarFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
                 SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
-    do_check_eq(countFolderChildren(bs.bookmarksMenuFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
                 SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
 
     // Set preferences.
-    ps.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 1);
+    Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 1);
+
+    rebuildSmartBookmarks();
+
+    // Count items.
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
+                SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
+                SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
+
+    // Check smart bookmark has been replaced, itemId has changed.
+    itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0);
+    do_check_neq(itemId, -1);
+    do_check_neq(PlacesUtils.bookmarks.getItemTitle(itemId), "new title");
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
+
+    // Check version has been updated.
+    do_check_eq(Services.prefs.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
+                SMART_BOOKMARKS_VERSION);
+
+    next_test();
+  }
+});
+
+//------------------------------------------------------------------------------
+
+tests.push({
+  description: "bookmarks position is retained when version changes.",
+  exec: function() {
+    // Sanity check items.
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
+                SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
+                SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
+
+    let itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 0);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
+    let firstItemTitle = PlacesUtils.bookmarks.getItemTitle(itemId);
+
+    itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 1);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
+    let secondItemTitle = PlacesUtils.bookmarks.getItemTitle(itemId);
+
+    // Set preferences.
+    Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 1);
 
     rebuildSmartBookmarks();
 
     // Count items.
-    do_check_eq(countFolderChildren(bs.toolbarFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
                 SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
-    do_check_eq(countFolderChildren(bs.bookmarksMenuFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
+                SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
+
+    // Check smart bookmarks are still in correct position.
+    itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 0);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
+    do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), firstItemTitle);
+
+    itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 1);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
+    do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), secondItemTitle);
+
+    // Check version has been updated.
+    do_check_eq(Services.prefs.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
+                SMART_BOOKMARKS_VERSION);
+
+    next_test();
+  }
+});
+
+//------------------------------------------------------------------------------
+
+tests.push({
+  description: "moved bookmarks position is retained when version changes.",
+  exec: function() {
+    // Sanity check items.
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
+                SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
                 SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
 
-    // Check smart bookmark has been replaced, itemId has changed.
-    itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
-    do_check_neq(itemId, -1);
-    do_check_neq(bs.getItemTitle(itemId), "new title");
-    do_check_true(as.itemHasAnnotation(itemId, SMART_BOOKMARKS_ANNO));
+    let itemId1 = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 0);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId1, SMART_BOOKMARKS_ANNO));
+    let firstItemTitle = PlacesUtils.bookmarks.getItemTitle(itemId1);
+
+    let itemId2 = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 1);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId2, SMART_BOOKMARKS_ANNO));
+    let secondItemTitle = PlacesUtils.bookmarks.getItemTitle(itemId2);
+
+    // Move the first smart bookmark to the end of the menu.
+    PlacesUtils.bookmarks.moveItem(itemId1, PlacesUtils.bookmarksMenuFolderId,
+                                   PlacesUtils.bookmarks.DEFAULT_INDEX);
+
+    do_check_eq(itemId1, PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId,
+                                                   PlacesUtils.bookmarks.DEFAULT_INDEX));
+
+    // Set preferences.
+    Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 1);
+
+    rebuildSmartBookmarks();
+
+    // Count items.
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
+                SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
+                SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
+
+    // Check smart bookmarks are still in correct position.
+    itemId2 = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 0);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId2, SMART_BOOKMARKS_ANNO));
+    do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId2), secondItemTitle);
+
+    itemId1 = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.bookmarksMenuFolderId,
+                                                   PlacesUtils.bookmarks.DEFAULT_INDEX);
+    do_check_true(PlacesUtils.annotations.itemHasAnnotation(itemId1, SMART_BOOKMARKS_ANNO));
+    do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId1), firstItemTitle);
+
+    // Move back the smart bookmark to the original position.
+    PlacesUtils.bookmarks.moveItem(itemId1, PlacesUtils.bookmarksMenuFolderId, 1);
 
     // Check version has been updated.
-    do_check_eq(ps.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
+    do_check_eq(Services.prefs.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
                 SMART_BOOKMARKS_VERSION);
 
     next_test();
   }
 });
 
 //------------------------------------------------------------------------------
 
 tests.push({
   description: "An explicitly removed smart bookmark should not be recreated.",
   exec: function() {   
     // Remove toolbar's smart bookmarks
-    bs.removeItem(bs.getIdForItemAt(bs.toolbarFolder, 0));
+    PlacesUtils.bookmarks.removeItem(PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0));
 
     // Sanity check items.
-    do_check_eq(countFolderChildren(bs.toolbarFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
                 DEFAULT_BOOKMARKS_ON_TOOLBAR);
-    do_check_eq(countFolderChildren(bs.bookmarksMenuFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
                 SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
 
     // Set preferences.
-    ps.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 1);
+    Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 1);
 
     rebuildSmartBookmarks();
 
     // Count items.
     // We should not have recreated the smart bookmark on toolbar.
-    do_check_eq(countFolderChildren(bs.toolbarFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
                 DEFAULT_BOOKMARKS_ON_TOOLBAR);
-    do_check_eq(countFolderChildren(bs.bookmarksMenuFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
                 SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
 
     // Check version has been updated.
-    do_check_eq(ps.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
+    do_check_eq(Services.prefs.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
                 SMART_BOOKMARKS_VERSION);
 
     next_test();
   }
 });
 
 //------------------------------------------------------------------------------
 
 tests.push({
   description: "Even if a smart bookmark has been removed recreate it if version is 0.",
   exec: function() {
     // Sanity check items.
-    do_check_eq(countFolderChildren(bs.toolbarFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
                 DEFAULT_BOOKMARKS_ON_TOOLBAR);
-    do_check_eq(countFolderChildren(bs.bookmarksMenuFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
                 SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
 
     // Set preferences.
-    ps.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 0);
+    Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 0);
 
     rebuildSmartBookmarks();
 
     // Count items.
     // We should not have recreated the smart bookmark on toolbar.
-    do_check_eq(countFolderChildren(bs.toolbarFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.toolbarFolderId),
                 SMART_BOOKMARKS_ON_TOOLBAR + DEFAULT_BOOKMARKS_ON_TOOLBAR);
-    do_check_eq(countFolderChildren(bs.bookmarksMenuFolder),
+    do_check_eq(countFolderChildren(PlacesUtils.bookmarksMenuFolderId),
                 SMART_BOOKMARKS_ON_MENU + DEFAULT_BOOKMARKS_ON_MENU);
 
     // Check version has been updated.
-    do_check_eq(ps.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
+    do_check_eq(Services.prefs.getIntPref(PREF_SMART_BOOKMARKS_VERSION),
                 SMART_BOOKMARKS_VERSION);
 
     next_test();
   }
 });
 //------------------------------------------------------------------------------
 
 function countFolderChildren(aFolderItemId) {
-  var query = hs.getNewQuery();
-  query.setFolders([aFolderItemId], 1);
-  var options = hs.getNewQueryOptions();
-  var rootNode = hs.executeQuery(query, options).root;
-  rootNode.containerOpen = true;
-  var cc = rootNode.childCount;
+  let rootNode = PlacesUtils.getFolderContents(aFolderItemId).root;
+  let cc = rootNode.childCount;
   // Dump contents.
-  for (var i = 0; i < cc ; i++) {
-    var node = rootNode.getChild(i);
-    print("Found child at " + i + ": " + node.title);
+  for (let i = 0; i < cc ; i++) {
+    let node = rootNode.getChild(i);
+    let title = PlacesUtils.nodeIsSeparator(node) ? "---" : node.title;
+    print("Found child(" + i + "): " + title);
   }
   rootNode.containerOpen = false;
   return cc;
 }
 
-var testIndex = 0;
 function next_test() {
   if (tests.length) {
     // Execute next test.
     let test = tests.shift();
-    print("\nTEST " + (++testIndex) + ": " + test.description);
+    print("\nTEST: " + test.description);
     test.exec();
   }
   else {
     // Clean up database from all bookmarks.
     remove_all_bookmarks();
     do_test_finished();
   }
 }
 
 function run_test() {
-  // Bug 510219.
-  // Disabled on Windows due to almost permanent failure.
-  if ("@mozilla.org/windows-registry-key;1" in Components.classes)
-    return;
-
   do_test_pending();
 
   remove_bookmarks_html();
   remove_all_JSON_backups();
 
-  // Initialize browserGlue.
-  var bg = Cc["@mozilla.org/browser/browserglue;1"].
-           getService(Ci.nsIBrowserGlue);
-  bg.QueryInterface(Ci.nsIObserver).observe(null, "places-init-complete", null);
+  // Initialize browserGlue, but remove it's listener to places-init-complete.
+  let bg = Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver);
+  // Initialize Places.
+  PlacesUtils.history;
+  // Usually places init would async notify to glue, but we want to avoid
+  // randomness here, thus we fire the notification synchronously.
+  bg.observe(null, "places-init-complete", null);
 
   // Ensure preferences status.
-  do_check_false(ps.getBoolPref(PREF_AUTO_EXPORT_HTML));
+  do_check_false(Services.prefs.getBoolPref(PREF_AUTO_EXPORT_HTML));
+  do_check_false(Services.prefs.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
   try {
-    do_check_false(ps.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
+    do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML));
     do_throw("importBookmarksHTML pref should not exist");
   }
   catch(ex) {}
-  do_check_false(ps.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS));
 
   // Kick-off tests.
   next_test();
 }