Bug 742098 - refactor observe() into a set of distinct methods [r=zpao]
authorMax Li <maxli@maxli.ca>
Wed, 11 Apr 2012 12:52:48 -0700
changeset 91458 6d83a00be8a0d0fa5efadc5f4be5ef25f649f6af
parent 91457 bd071b2e8a16cde9ba17beb9d172f24ec20ccdac
child 91459 7814c8fdc48b5e13074217a53185ad63034baa7f
push id22445
push usereakhgari@mozilla.com
push dateThu, 12 Apr 2012 16:19:55 +0000
treeherdermozilla-central@901dfde60183 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerszpao
bugs742098
milestone14.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 742098 - refactor observe() into a set of distinct methods [r=zpao]
browser/components/sessionstore/src/nsSessionStore.js
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -492,275 +492,53 @@ SessionStoreService.prototype = {
       this._prefBranch.clearUserPref("sessionstore.max_concurrent_tabs");
     }
   },
 
   /**
    * Handle notifications
    */
   observe: function sss_observe(aSubject, aTopic, aData) {
-    // for event listeners
-    var _this = this;
-
     switch (aTopic) {
-    case "domwindowopened": // catch new windows
-      aSubject.addEventListener("load", function(aEvent) {
-        aEvent.currentTarget.removeEventListener("load", arguments.callee, false);
-        _this.onLoad(aEvent.currentTarget);
-      }, false);
-      break;
-    case "domwindowclosed": // catch closed windows
-      this.onClose(aSubject);
-      break;
-    case "quit-application-requested":
-      // get a current snapshot of all windows
-      this._forEachBrowserWindow(function(aWindow) {
-        this._collectWindowData(aWindow);
-      });
-      // we must cache this because _getMostRecentBrowserWindow will always
-      // return null by the time quit-application occurs
-      var activeWindow = this._getMostRecentBrowserWindow();
-      if (activeWindow)
-        this.activeWindowSSiCache = activeWindow.__SSi || "";
-      this._dirtyWindows = [];
-      break;
-    case "quit-application-granted":
-      // freeze the data at what we've got (ignoring closing windows)
-      this._loadState = STATE_QUITTING;
-      break;
-    case "browser-lastwindow-close-granted":
-      // last browser window is quitting.
-      // remember to restore the last window when another browser window is opened
-      // do not account for pref(resume_session_once) at this point, as it might be
-      // set by another observer getting this notice after us
-      this._restoreLastWindow = true;
-      break;
-    case "quit-application":
-      if (aData == "restart") {
-        this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
-        // The browser:purge-session-history notification fires after the
-        // quit-application notification so unregister the
-        // browser:purge-session-history notification to prevent clearing
-        // session data on disk on a restart.  It is also unnecessary to
-        // perform any other sanitization processing on a restart as the
-        // browser is about to exit anyway.
-        Services.obs.removeObserver(this, "browser:purge-session-history");
-      }
-      else if (this._resume_session_once_on_shutdown != null) {
-        // if the sessionstore.resume_session_once preference was changed by
-        // saveState because crash recovery is disabled then restore the
-        // preference back to the value it was prior to that.  This will prevent
-        // SessionStore from always restoring the session when crash recovery is
-        // disabled.
-        this._prefBranch.setBoolPref("sessionstore.resume_session_once",
-                                     this._resume_session_once_on_shutdown);
-      }
-
-      if (aData != "restart") {
-        // Throw away the previous session on shutdown
-        this._lastSessionState = null;
-      }
-
-      this._loadState = STATE_QUITTING; // just to be sure
-      this._uninit();
-      break;
-    case "browser:purge-session-history": // catch sanitization 
-      this._clearDisk();
-      // If the browser is shutting down, simply return after clearing the
-      // session data on disk as this notification fires after the
-      // quit-application notification so the browser is about to exit.
-      if (this._loadState == STATE_QUITTING)
-        return;
-      this._lastSessionState = null;
-      let openWindows = {};
-      this._forEachBrowserWindow(function(aWindow) {
-        Array.forEach(aWindow.gBrowser.tabs, function(aTab) {
-          delete aTab.linkedBrowser.__SS_data;
-          delete aTab.linkedBrowser.__SS_tabStillLoading;
-          delete aTab.linkedBrowser.__SS_formDataSaved;
-          delete aTab.linkedBrowser.__SS_hostSchemeData;
-          if (aTab.linkedBrowser.__SS_restoreState)
-            this._resetTabRestoringState(aTab);
-        });
-        openWindows[aWindow.__SSi] = true;
-      });
-      // also clear all data about closed tabs and windows
-      for (let ix in this._windows) {
-        if (ix in openWindows) {
-          this._windows[ix]._closedTabs = [];
-        }
-        else {
-          delete this._windows[ix];
-          delete this._internalWindows[ix];
-        }
-      }
-      // also clear all data about closed windows
-      this._closedWindows = [];
-      // give the tabbrowsers a chance to clear their histories first
-      var win = this._getMostRecentBrowserWindow();
-      if (win)
-        win.setTimeout(function() { _this.saveState(true); }, 0);
-      else if (this._loadState == STATE_RUNNING)
-        this.saveState(true);
-      // Delete the private browsing backed up state, if any
-      if ("_stateBackup" in this)
-        delete this._stateBackup;
-
-      this._clearRestoringWindows();
-      break;
-    case "browser:purge-domain-data":
-      // does a session history entry contain a url for the given domain?
-      function containsDomain(aEntry) {
-        try {
-          if (this._getURIFromString(aEntry.url).host.hasRootDomain(aData))
-            return true;
-        }
-        catch (ex) { /* url had no host at all */ }
-        return aEntry.children && aEntry.children.some(containsDomain, this);
-      }
-      // remove all closed tabs containing a reference to the given domain
-      for (let ix in this._windows) {
-        let closedTabs = this._windows[ix]._closedTabs;
-        for (let i = closedTabs.length - 1; i >= 0; i--) {
-          if (closedTabs[i].state.entries.some(containsDomain, this))
-            closedTabs.splice(i, 1);
-        }
-      }
-      // remove all open & closed tabs containing a reference to the given
-      // domain in closed windows
-      for (let ix = this._closedWindows.length - 1; ix >= 0; ix--) {
-        let closedTabs = this._closedWindows[ix]._closedTabs;
-        let openTabs = this._closedWindows[ix].tabs;
-        let openTabCount = openTabs.length;
-        for (let i = closedTabs.length - 1; i >= 0; i--)
-          if (closedTabs[i].state.entries.some(containsDomain, this))
-            closedTabs.splice(i, 1);
-        for (let j = openTabs.length - 1; j >= 0; j--) {
-          if (openTabs[j].entries.some(containsDomain, this)) {
-            openTabs.splice(j, 1);
-            if (this._closedWindows[ix].selected > j)
-              this._closedWindows[ix].selected--;
-          }
-        }
-        if (openTabs.length == 0) {
-          this._closedWindows.splice(ix, 1);
-        }
-        else if (openTabs.length != openTabCount) {
-          // Adjust the window's title if we removed an open tab
-          let selectedTab = openTabs[this._closedWindows[ix].selected - 1];
-          // some duplication from restoreHistory - make sure we get the correct title
-          let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
-          if (activeIndex >= selectedTab.entries.length)
-            activeIndex = selectedTab.entries.length - 1;
-          this._closedWindows[ix].title = selectedTab.entries[activeIndex].title;
-        }
-      }
-      if (this._loadState == STATE_RUNNING)
-        this.saveState(true);
-
-      this._clearRestoringWindows();
-      break;
-    case "nsPref:changed": // catch pref changes
-      switch (aData) {
-      // if the user decreases the max number of closed tabs they want
-      // preserved update our internal states to match that max
-      case "sessionstore.max_tabs_undo":
-        this._max_tabs_undo = this._prefBranch.getIntPref("sessionstore.max_tabs_undo");
-        for (let ix in this._windows) {
-          this._windows[ix]._closedTabs.splice(this._max_tabs_undo, this._windows[ix]._closedTabs.length);
-        }
+      case "domwindowopened": // catch new windows
+        this.onOpen(aSubject);
+        break;
+      case "domwindowclosed": // catch closed windows
+        this.onClose(aSubject);
+        break;
+      case "quit-application-requested":
+        this.onQuitApplicationRequested();
+        break;
+      case "quit-application-granted":
+        this.onQuitApplicationGranted();
+        break;
+      case "browser-lastwindow-close-granted":
+        this.onLastWindowCloseGranted();
+        break;
+      case "quit-application":
+        this.onQuitApplication(aData);
         break;
-      case "sessionstore.max_windows_undo":
-        this._max_windows_undo = this._prefBranch.getIntPref("sessionstore.max_windows_undo");
-        this._capClosedWindows();
-        break;
-      case "sessionstore.interval":
-        this._interval = this._prefBranch.getIntPref("sessionstore.interval");
-        // reset timer and save
-        if (this._saveTimer) {
-          this._saveTimer.cancel();
-          this._saveTimer = null;
-        }
-        this.saveStateDelayed(null, -1);
+      case "browser:purge-session-history": // catch sanitization 
+        this.onPurgeSessionHistory();
         break;
-      case "sessionstore.resume_from_crash":
-        this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
-        // restore original resume_session_once preference if set in saveState
-        if (this._resume_session_once_on_shutdown != null) {
-          this._prefBranch.setBoolPref("sessionstore.resume_session_once",
-                                       this._resume_session_once_on_shutdown);
-          this._resume_session_once_on_shutdown = null;
-        }
-        // either create the file with crash recovery information or remove it
-        // (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
-        if (!this._resume_from_crash)
-          this._clearDisk();
-        this.saveState(true);
+      case "browser:purge-domain-data":
+        this.onPurgeDomainData(aData);
         break;
-      case "sessionstore.restore_on_demand":
-        this._restoreOnDemand =
-          this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
-        break;
-      case "sessionstore.restore_hidden_tabs":
-        this._restoreHiddenTabs =
-          this._prefBranch.getBoolPref("sessionstore.restore_hidden_tabs");
-        break;
-      case "sessionstore.restore_pinned_tabs_on_demand":
-        this._restorePinnedTabsOnDemand =
-          this._prefBranch.getBoolPref("sessionstore.restore_pinned_tabs_on_demand");
+      case "nsPref:changed": // catch pref changes
+        this.onPrefChange(aData);
         break;
-      }
-      break;
-    case "timer-callback": // timer call back for delayed saving
-      this._saveTimer = null;
-      this.saveState();
-      break;
-    case "private-browsing":
-      switch (aData) {
-      case "enter":
-        this._inPrivateBrowsing = true;
+      case "timer-callback": // timer call back for delayed saving
+        this.onTimerCallback();
         break;
-      case "exit":
-        aSubject.QueryInterface(Ci.nsISupportsPRBool);
-        let quitting = aSubject.data;
-        if (quitting) {
-          // save the backed up state with session set to stopped,
-          // otherwise resuming next time would look like a crash.
-          // Whether we restore the session upon resume will be determined by the
-          // usual startup prefs, so we will have the same behavior regardless of
-          // whether the browser was closed while in normal or private browsing mode.
-          if ("_stateBackup" in this) {
-            var oState = this._stateBackup;
-            oState.session = { state: STATE_STOPPED_STR };
-
-            this._saveStateObject(oState);
-          }
-        }
-        else
-          this._inPrivateBrowsing = false;
-        delete this._stateBackup;
+      case "private-browsing":
+        this.onPrivateBrowsing(aSubject, aData);
         break;
-      }
-
-      this._clearRestoringWindows();
-      break;
-    case "private-browsing-change-granted":
-      if (aData == "enter") {
-        this.saveState(true);
-        // We stringify & parse the current state so that we have have an object
-        // that won't change. _getCurrentState returns an object with references
-        // to objects that can change (specifically this._windows[x]).
-        this._stateBackup = JSON.parse(this._toJSONString(this._getCurrentState(true)));
-      }
-      // Make sure _tabsToRestore is cleared. It will be repopulated when
-      // entering/exiting private browsing (by calls to setBrowserState).
-      this._resetRestoringState();
-
-      this._clearRestoringWindows();
-      break;
+      case "private-browsing-change-granted":
+        this.onPrivateBrowsingChangeGranted(aData);
+        break;
     }
   },
 
 /* ........ Window Event Handlers .............. */
 
   /**
    * Implement nsIDOMEventListener for handling various window and tab events
    */
@@ -951,16 +729,30 @@ SessionStoreService.prototype = {
     for (let i = 0; i < tabbrowser.tabs.length; i++) {
       this.onTabAdd(aWindow, tabbrowser.tabs[i], true);
     }
     // notification of tab add/remove/selection/show/hide
     TAB_EVENTS.forEach(function(aEvent) {
       tabbrowser.tabContainer.addEventListener(aEvent, this, true);
     }, this);
   },
+  
+  /**
+   * On window open
+   * @param aWindow
+   *        Window reference
+   */
+  onOpen: function sss_onOpen(aWindow) {
+    var _this = this;
+    aWindow.addEventListener("load", function(aEvent) {
+      aEvent.currentTarget.removeEventListener("load", arguments.callee, false);
+      _this.onLoad(aEvent.currentTarget);
+    }, false);
+    return;
+  },
 
   /**
    * On window close...
    * - remove event listeners from tabs
    * - save all window data
    * @param aWindow
    *        Window reference
    */
@@ -1044,16 +836,315 @@ SessionStoreService.prototype = {
     
     // cache the window state until the window is completely gone
     aWindow.__SS_dyingCache = winData;
     
     delete aWindow.__SSi;
   },
 
   /**
+   * On quit application requested
+   */
+  onQuitApplicationRequested: function sss_onQuitApplicationRequested() {
+    // get a current snapshot of all windows
+    this._forEachBrowserWindow(function(aWindow) {
+      this._collectWindowData(aWindow);
+    });
+    // we must cache this because _getMostRecentBrowserWindow will always
+    // return null by the time quit-application occurs
+    var activeWindow = this._getMostRecentBrowserWindow();
+    if (activeWindow)
+      this.activeWindowSSiCache = activeWindow.__SSi || "";
+    this._dirtyWindows = [];
+  },
+  
+  /**
+   * On quit application granted
+   */
+  onQuitApplicationGranted: function sss_onQuitApplicationGranted() {
+    // freeze the data at what we've got (ignoring closing windows)
+    this._loadState = STATE_QUITTING;
+  },
+  
+  /**
+   * On last browser window close
+   */
+  onLastWindowCloseGranted: function sss_onLastWindowCloseGranted() {
+    // last browser window is quitting.
+    // remember to restore the last window when another browser window is opened
+    // do not account for pref(resume_session_once) at this point, as it might be
+    // set by another observer getting this notice after us
+    this._restoreLastWindow = true;
+  },
+
+  /**
+   * On quitting application
+   * @param aData
+   *        String type of quitting
+   */
+  onQuitApplication: function sss_onQuitApplication(aData) {
+    if (aData == "restart") {
+      this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
+      // The browser:purge-session-history notification fires after the
+      // quit-application notification so unregister the
+      // browser:purge-session-history notification to prevent clearing
+      // session data on disk on a restart.  It is also unnecessary to
+      // perform any other sanitization processing on a restart as the
+      // browser is about to exit anyway.
+      Services.obs.removeObserver(this, "browser:purge-session-history");
+    }
+    else if (this._resume_session_once_on_shutdown != null) {
+      // if the sessionstore.resume_session_once preference was changed by
+      // saveState because crash recovery is disabled then restore the
+      // preference back to the value it was prior to that.  This will prevent
+      // SessionStore from always restoring the session when crash recovery is
+      // disabled.
+      this._prefBranch.setBoolPref("sessionstore.resume_session_once",
+                                   this._resume_session_once_on_shutdown);
+    }
+
+    if (aData != "restart") {
+      // Throw away the previous session on shutdown
+      this._lastSessionState = null;
+    }
+
+    this._loadState = STATE_QUITTING; // just to be sure
+    this._uninit();
+  },
+
+  /**
+   * On purge of session history
+   */
+  onPurgeSessionHistory: function sss_onPurgeSessionHistory() {
+    var _this = this;
+    this._clearDisk();
+    // If the browser is shutting down, simply return after clearing the
+    // session data on disk as this notification fires after the
+    // quit-application notification so the browser is about to exit.
+    if (this._loadState == STATE_QUITTING)
+      return;
+    this._lastSessionState = null;
+    let openWindows = {};
+    this._forEachBrowserWindow(function(aWindow) {
+      Array.forEach(aWindow.gBrowser.tabs, function(aTab) {
+        delete aTab.linkedBrowser.__SS_data;
+        delete aTab.linkedBrowser.__SS_tabStillLoading;
+        delete aTab.linkedBrowser.__SS_formDataSaved;
+        delete aTab.linkedBrowser.__SS_hostSchemeData;
+        if (aTab.linkedBrowser.__SS_restoreState)
+          this._resetTabRestoringState(aTab);
+      });
+      openWindows[aWindow.__SSi] = true;
+    });
+    // also clear all data about closed tabs and windows
+    for (let ix in this._windows) {
+      if (ix in openWindows) {
+        this._windows[ix]._closedTabs = [];
+      }
+      else {
+        delete this._windows[ix];
+        delete this._internalWindows[ix];
+      }
+    }
+    // also clear all data about closed windows
+    this._closedWindows = [];
+    // give the tabbrowsers a chance to clear their histories first
+    var win = this._getMostRecentBrowserWindow();
+    if (win)
+      win.setTimeout(function() { _this.saveState(true); }, 0);
+    else if (this._loadState == STATE_RUNNING)
+      this.saveState(true);
+    // Delete the private browsing backed up state, if any
+    if ("_stateBackup" in this)
+      delete this._stateBackup;
+
+    this._clearRestoringWindows();
+  },
+
+  /**
+   * On purge of domain data
+   * @param aData
+   *        String domain data
+   */
+  onPurgeDomainData: function sss_onPurgeDomainData(aData) {
+    // does a session history entry contain a url for the given domain?
+    function containsDomain(aEntry) {
+      try {
+        if (this._getURIFromString(aEntry.url).host.hasRootDomain(aData))
+          return true;
+      }
+      catch (ex) { /* url had no host at all */ }
+      return aEntry.children && aEntry.children.some(containsDomain, this);
+    }
+    // remove all closed tabs containing a reference to the given domain
+    for (let ix in this._windows) {
+      let closedTabs = this._windows[ix]._closedTabs;
+      for (let i = closedTabs.length - 1; i >= 0; i--) {
+        if (closedTabs[i].state.entries.some(containsDomain, this))
+          closedTabs.splice(i, 1);
+      }
+    }
+    // remove all open & closed tabs containing a reference to the given
+    // domain in closed windows
+    for (let ix = this._closedWindows.length - 1; ix >= 0; ix--) {
+      let closedTabs = this._closedWindows[ix]._closedTabs;
+      let openTabs = this._closedWindows[ix].tabs;
+      let openTabCount = openTabs.length;
+      for (let i = closedTabs.length - 1; i >= 0; i--)
+        if (closedTabs[i].state.entries.some(containsDomain, this))
+          closedTabs.splice(i, 1);
+      for (let j = openTabs.length - 1; j >= 0; j--) {
+        if (openTabs[j].entries.some(containsDomain, this)) {
+          openTabs.splice(j, 1);
+          if (this._closedWindows[ix].selected > j)
+            this._closedWindows[ix].selected--;
+        }
+      }
+      if (openTabs.length == 0) {
+        this._closedWindows.splice(ix, 1);
+      }
+      else if (openTabs.length != openTabCount) {
+        // Adjust the window's title if we removed an open tab
+        let selectedTab = openTabs[this._closedWindows[ix].selected - 1];
+        // some duplication from restoreHistory - make sure we get the correct title
+        let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
+        if (activeIndex >= selectedTab.entries.length)
+          activeIndex = selectedTab.entries.length - 1;
+        this._closedWindows[ix].title = selectedTab.entries[activeIndex].title;
+      }
+    }
+    if (this._loadState == STATE_RUNNING)
+      this.saveState(true);
+
+    this._clearRestoringWindows();
+  },
+
+  /**
+   * On preference change
+   * @param aData
+   *        String preference changed
+   */
+  onPrefChange: function sss_onPrefChange(aData) {
+    switch (aData) {
+      // if the user decreases the max number of closed tabs they want
+      // preserved update our internal states to match that max
+      case "sessionstore.max_tabs_undo":
+        this._max_tabs_undo = this._prefBranch.getIntPref("sessionstore.max_tabs_undo");
+        for (let ix in this._windows) {
+          this._windows[ix]._closedTabs.splice(this._max_tabs_undo, this._windows[ix]._closedTabs.length);
+        }
+        break;
+      case "sessionstore.max_windows_undo":
+        this._max_windows_undo = this._prefBranch.getIntPref("sessionstore.max_windows_undo");
+        this._capClosedWindows();
+        break;
+      case "sessionstore.interval":
+        this._interval = this._prefBranch.getIntPref("sessionstore.interval");
+        // reset timer and save
+        if (this._saveTimer) {
+          this._saveTimer.cancel();
+          this._saveTimer = null;
+        }
+        this.saveStateDelayed(null, -1);
+        break;
+      case "sessionstore.resume_from_crash":
+        this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
+        // restore original resume_session_once preference if set in saveState
+        if (this._resume_session_once_on_shutdown != null) {
+          this._prefBranch.setBoolPref("sessionstore.resume_session_once",
+                                       this._resume_session_once_on_shutdown);
+          this._resume_session_once_on_shutdown = null;
+        }
+        // either create the file with crash recovery information or remove it
+        // (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
+        if (!this._resume_from_crash)
+          this._clearDisk();
+        this.saveState(true);
+        break;
+      case "sessionstore.restore_on_demand":
+        this._restoreOnDemand =
+          this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
+        break;
+      case "sessionstore.restore_hidden_tabs":
+        this._restoreHiddenTabs =
+          this._prefBranch.getBoolPref("sessionstore.restore_hidden_tabs");
+        break;
+      case "sessionstore.restore_pinned_tabs_on_demand":
+        this._restorePinnedTabsOnDemand =
+          this._prefBranch.getBoolPref("sessionstore.restore_pinned_tabs_on_demand");
+        break;
+    }
+  },
+
+  /**
+   * On timer callback
+   */
+  onTimerCallback: function sss_onTimerCallback() {
+    this._saveTimer = null;
+    this.saveState();
+  },
+
+  /**
+   * On private browsing
+   * @param aSubject
+   *        Window reference
+   * @param aData
+   *        String whether to enter or exit private browsing
+   */
+  onPrivateBrowsing: function sss_onPrivateBrowsing(aSubject, aData) {
+    switch (aData) {
+      case "enter":
+        this._inPrivateBrowsing = true;
+        break;
+      case "exit":
+        aSubject.QueryInterface(Ci.nsISupportsPRBool);
+        let quitting = aSubject.data;
+        if (quitting) {
+          // save the backed up state with session set to stopped,
+          // otherwise resuming next time would look like a crash.
+          // Whether we restore the session upon resume will be determined by the
+          // usual startup prefs, so we will have the same behavior regardless of
+          // whether the browser was closed while in normal or private browsing mode.
+          if ("_stateBackup" in this) {
+            var oState = this._stateBackup;
+            oState.session = { state: STATE_STOPPED_STR };
+
+            this._saveStateObject(oState);
+          }
+        }
+        else
+          this._inPrivateBrowsing = false;
+        delete this._stateBackup;
+        break;
+    }
+
+    this._clearRestoringWindows();
+  },
+
+  /**
+   * On private browsing change granted
+   * @param aData
+   *        String whether to enter or exit private browsing
+   */
+  onPrivateBrowsingChangeGranted: function sss_onPrivateBrowsingChangeGranted(aData) {
+    if (aData == "enter") {
+      this.saveState(true);
+      // We stringify & parse the current state so that we have have an object
+      // that won't change. _getCurrentState returns an object with references
+      // to objects that can change (specifically this._windows[x]).
+      this._stateBackup = JSON.parse(this._toJSONString(this._getCurrentState(true)));
+    }
+    // Make sure _tabsToRestore is cleared. It will be repopulated when
+    // entering/exiting private browsing (by calls to setBrowserState).
+    this._resetRestoringState();
+
+    this._clearRestoringWindows();
+  },
+
+  /**
    * set up listeners for a new tab
    * @param aWindow
    *        Window reference
    * @param aTab
    *        Tab reference
    * @param aNoNotification
    *        bool Do not save state if we're updating an existing tab
    */