Bug 1147554 - Lazily create desktop reading list's database connection. r=markh, a=readinglist
authorDrew Willcoxon <adw@mozilla.com>
Wed, 01 Apr 2015 18:24:32 -0700
changeset 258183 acc50d404648
parent 258182 7dded32396ba
child 258184 9104d1f928a7
push id4617
push userdwillcoxon@mozilla.com
push date2015-04-02 02:05 +0000
treeherdermozilla-beta@818e63fbfba2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarkh, readinglist
bugs1147554
milestone38.0
Bug 1147554 - Lazily create desktop reading list's database connection. r=markh, a=readinglist
browser/base/content/browser.js
browser/components/readinglist/SQLiteStore.jsm
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1027,17 +1027,17 @@ var gBrowserInit = {
       }
       goSetCommandEnabled("cmd_newNavigatorTab", false);
     }
 
     // Misc. inits.
     CombinedStopReload.init();
     gPrivateBrowsingUI.init();
     TabsInTitlebar.init();
-    ReadingListUI.init();
+//     ReadingListUI.init();
 
 #ifdef XP_WIN
     if (window.matchMedia("(-moz-os-version: windows-win8)").matches &&
         window.matchMedia("(-moz-windows-default-theme)").matches) {
       let windowFrameColor = Cu.import("resource:///modules/Windows8WindowFrameColor.jsm", {})
                                .Windows8WindowFrameColor.get();
 
       // Formula from W3C's WCAG 2.0 spec's color ratio and relative luminance,
@@ -1356,16 +1356,18 @@ var gBrowserInit = {
 
     gBrowserThumbnails.init();
 
     // Add Devtools menuitems and listeners
     gDevToolsBrowser.registerBrowserWindow(window);
 
     gMenuButtonUpdateBadge.init();
 
+    ReadingListUI.init();
+
     window.addEventListener("mousemove", MousePosTracker, false);
     window.addEventListener("dragover", MousePosTracker, false);
 
     gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
     gNavToolbox.addEventListener("customizationchange", CustomizationHandler);
     gNavToolbox.addEventListener("customizationending", CustomizationHandler);
 
     // End startup crash tracking after a delay to catch crashes while restoring
--- a/browser/components/readinglist/SQLiteStore.jsm
+++ b/browser/components/readinglist/SQLiteStore.jsm
@@ -22,34 +22,33 @@ XPCOMUtils.defineLazyModuleGetter(this, 
  * A SQLite Reading List store backed by a database on disk.  The database is
  * created if it doesn't exist.
  *
  * @param pathRelativeToProfileDir The path of the database file relative to
  *        the profile directory.
  */
 this.SQLiteStore = function SQLiteStore(pathRelativeToProfileDir) {
   this.pathRelativeToProfileDir = pathRelativeToProfileDir;
-  this._ensureConnection(pathRelativeToProfileDir);
 };
 
 this.SQLiteStore.prototype = {
 
   /**
    * Yields the number of items in the store that match the given options.
    *
    * @param userOptsList A variable number of options objects that control the
    *        items that are matched.  See Options Objects in ReadingList.jsm.
    * @param controlOpts A single options object.  Use this to filter out items
    *        that don't match it -- in other words, to override the user options.
    *        See Options Objects in ReadingList.jsm.
    * @return Promise<number> The number of matching items in the store.
    *         Rejected with an Error on error.
    */
   count: Task.async(function* (userOptsList=[], controlOpts={}) {
-      let [sql, args] = sqlWhereFromOptions(userOptsList, controlOpts);
+    let [sql, args] = sqlWhereFromOptions(userOptsList, controlOpts);
     let count = 0;
     let conn = yield this._connectionPromise;
     yield conn.executeCached(`
       SELECT COUNT(*) AS count FROM items ${sql};
     `, args, row => count = row.getResultByName("count"));
     return count;
   }),
 
@@ -151,44 +150,49 @@ this.SQLiteStore.prototype = {
   /**
    * Call this when you're done with the store.  Don't use it afterward.
    */
   destroy() {
     if (!this._destroyPromise) {
       this._destroyPromise = Task.spawn(function* () {
         let conn = yield this._connectionPromise;
         yield conn.close();
-        this._connectionPromise = Promise.reject("Store destroyed");
+        this.__connectionPromise = Promise.reject("Store destroyed");
       }.bind(this));
     }
     return this._destroyPromise;
   },
 
   /**
-   * Creates the database connection if it hasn't been created already.
-   *
-   * @param pathRelativeToProfileDir The path of the database file relative to
-   *        the profile directory.
+   * Promise<Sqlite.OpenedConnection>
    */
-  _ensureConnection: Task.async(function* (pathRelativeToProfileDir) {
-    if (!this._connectionPromise) {
-      this._connectionPromise = Task.spawn(function* () {
-        let conn = yield Sqlite.openConnection({
-          path: pathRelativeToProfileDir,
-          sharedMemoryCache: false,
-        });
-        Sqlite.shutdown.addBlocker("readinglist/SQLiteStore: Destroy",
-                                   this.destroy.bind(this));
-        yield conn.execute(`
-          PRAGMA locking_mode = EXCLUSIVE;
-        `);
-        yield this._checkSchema(conn);
-        return conn;
-      }.bind(this));
+  get _connectionPromise() {
+    if (!this.__connectionPromise) {
+      this.__connectionPromise = this._createConnection();
     }
+    return this.__connectionPromise;
+  },
+
+  /**
+   * Creates the database connection.
+   *
+   * @return Promise<Sqlite.OpenedConnection>
+   */
+  _createConnection: Task.async(function* () {
+    let conn = yield Sqlite.openConnection({
+      path: this.pathRelativeToProfileDir,
+      sharedMemoryCache: false,
+    });
+    Sqlite.shutdown.addBlocker("readinglist/SQLiteStore: Destroy",
+                               this.destroy.bind(this));
+    yield conn.execute(`
+      PRAGMA locking_mode = EXCLUSIVE;
+    `);
+    yield this._checkSchema(conn);
+    return conn;
   }),
 
   /**
    * Updates the properties of an item that's already present in the store.  See
    * ReadingList.prototype.updateItem.
    *
    * @param item The item to update.  It must have the property named by
    *        keyProp.
@@ -205,19 +209,16 @@ this.SQLiteStore.prototype = {
     if (!item[keyProp]) {
       throw new Error("Item must have " + keyProp);
     }
     yield conn.executeCached(`
       UPDATE items SET ${assignments} WHERE ${keyProp} = :${keyProp};
     `, item);
   }),
 
-  // Promise<Sqlite.OpenedConnection>
-  _connectionPromise: null,
-
   // The current schema version.
   _schemaVersion: 1,
 
   _checkSchema: Task.async(function* (conn) {
     let version = parseInt(yield conn.getSchemaVersion());
     for (; version < this._schemaVersion; version++) {
       let meth = `_migrateSchema${version}To${version + 1}`;
       yield this[meth](conn);