Bug 509625 - nsSessionStore.js should deal with browsers rather than tabpanels. r=zeniko
authorDão Gottwald <dao@mozilla.com>
Fri, 14 Aug 2009 23:16:11 +0200
changeset 31572 59cfe19eca0b921790ae9ba5d52ebb1d1503bf89
parent 31571 aff827e779e6e94e0a44deb465c79c02996e02fc
child 31573 73bb4a556e4f1c5634eb37262950d8959cdb7fb7
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerszeniko
bugs509625
milestone1.9.3a1pre
Bug 509625 - nsSessionStore.js should deal with browsers rather than tabpanels. r=zeniko
browser/components/sessionstore/src/nsSessionStore.js
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -357,18 +357,18 @@ SessionStoreService.prototype = {
         this._clearingOnShutdown = false;
       }
       this._loadState = STATE_QUITTING; // just to be sure
       this._uninit();
       break;
     case "browser:purge-session-history": // catch sanitization 
       let openWindows = {};
       this._forEachBrowserWindow(function(aWindow) {
-        Array.forEach(aWindow.getBrowser().browsers, function(aBrowser) {
-          delete aBrowser.parentNode.__SS_data;
+        Array.forEach(aWindow.gBrowser.browsers, function(aBrowser) {
+          delete aBrowser.__SS_data;
         });
         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
@@ -511,51 +511,45 @@ SessionStoreService.prototype = {
   },
 
 /* ........ Window Event Handlers .............. */
 
   /**
    * Implement nsIDOMEventListener for handling various window and tab events
    */
   handleEvent: function sss_handleEvent(aEvent) {
+    var win = aEvent.currentTarget.ownerDocument.defaultView;
     switch (aEvent.type) {
       case "load":
       case "pageshow":
-        this.onTabLoad(aEvent.currentTarget.ownerDocument.defaultView, aEvent.currentTarget, aEvent);
+        this.onTabLoad(win, aEvent.currentTarget, aEvent);
         break;
       case "change":
       case "input":
       case "DOMAutoComplete":
-        this.onTabInput(aEvent.currentTarget.ownerDocument.defaultView, aEvent.currentTarget);
+        this.onTabInput(win, aEvent.currentTarget);
         break;
       case "scroll":
-        this.onTabScroll(aEvent.currentTarget.ownerDocument.defaultView);
+        this.onTabScroll(win);
         break;
       case "TabOpen":
       case "TabClose":
-        let target = aEvent.originalTarget;
-        let panelID = target.linkedPanel;
-        let ownerDoc = target.ownerDocument;
-        let bindingParent = ownerDoc.getBindingParent(target);
-        let tabpanel =
-          ownerDoc.getAnonymousElementByAttribute(bindingParent, "id",
-                                                  panelID);
+        let browser = aEvent.originalTarget.linkedBrowser;
         if (aEvent.type == "TabOpen") {
-          this.onTabAdd(aEvent.currentTarget.ownerDocument.defaultView, tabpanel);
+          this.onTabAdd(win, browser);
         }
         else {
           // aEvent.detail determines if the tab was closed by moving to a different window
           if (!aEvent.detail)
-            this.onTabClose(aEvent.currentTarget.ownerDocument.defaultView, aEvent.originalTarget);
-          this.onTabRemove(aEvent.currentTarget.ownerDocument.defaultView, tabpanel);
+            this.onTabClose(win, aEvent.originalTarget);
+          this.onTabRemove(win, browser);
         }
         break;
       case "TabSelect":
-        var tabpanels = aEvent.currentTarget.mPanelContainer;
-        this.onTabSelect(aEvent.currentTarget.ownerDocument.defaultView, tabpanels);
+        this.onTabSelect(win);
         break;
     }
   },
 
   /**
    * If it's the first window load since app start...
    * - determine if we're reloading after a crash or a forced-restart
    * - restore window state
@@ -639,22 +633,21 @@ SessionStoreService.prototype = {
     if (this._restoreLastWindow && aWindow.toolbar.visible) {
       // always reset (if not a popup window)
       // we don't want to restore a window directly after, for example,
       // undoCloseWindow was executed.
       this._restoreLastWindow = false;
     }
 #endif
 
-    var tabbrowser = aWindow.getBrowser();
-    var tabpanels = tabbrowser.mPanelContainer;
+    var tabbrowser = aWindow.gBrowser;
     
     // add tab change listeners to all already existing tabs
-    for (var i = 0; i < tabpanels.childNodes.length; i++) {
-      this.onTabAdd(aWindow, tabpanels.childNodes[i], true);
+    for (let i = 0; i < tabbrowser.browsers.length; i++) {
+      this.onTabAdd(aWindow, tabbrowser.browsers[i], true);
     }
     // notification of tab add/remove/selection
     tabbrowser.addEventListener("TabOpen", this, true);
     tabbrowser.addEventListener("TabClose", this, true);
     tabbrowser.addEventListener("TabSelect", this, true);
   },
 
   /**
@@ -679,18 +672,17 @@ SessionStoreService.prototype = {
     if (!aWindow.__SSi || !this._windows[aWindow.__SSi]) {
       return;
     }
     
     if (this.windowToFocus && this.windowToFocus == aWindow) {
       delete this.windowToFocus;
     }
     
-    var tabbrowser = aWindow.getBrowser();
-    var tabpanels = tabbrowser.mPanelContainer;
+    var tabbrowser = aWindow.gBrowser;
 
     tabbrowser.removeEventListener("TabOpen", this, true);
     tabbrowser.removeEventListener("TabClose", this, true);
     tabbrowser.removeEventListener("TabSelect", this, true);
     
     let winData = this._windows[aWindow.__SSi];
     if (this._loadState == STATE_RUNNING) { // window not closed during a regular shut-down 
       // update all window data for a last time
@@ -712,78 +704,78 @@ SessionStoreService.prototype = {
       
       // clear this window from the list
       delete this._windows[aWindow.__SSi];
       
       // save the state without this window to disk
       this.saveStateDelayed();
     }
     
-    for (var i = 0; i < tabpanels.childNodes.length; i++) {
-      this.onTabRemove(aWindow, tabpanels.childNodes[i], true);
+    for (let i = 0; i < tabbrowser.browsers.length; i++) {
+      this.onTabRemove(aWindow, tabbrowser.browsers[i], true);
     }
     
     // cache the window state until the window is completely gone
     aWindow.__SS_dyingCache = winData;
     
     delete aWindow.__SSi;
   },
 
   /**
    * set up listeners for a new tab
    * @param aWindow
    *        Window reference
-   * @param aPanel
-   *        TabPanel reference
+   * @param aBrowser
+   *        Browser reference
    * @param aNoNotification
    *        bool Do not save state if we're updating an existing tab
    */
-  onTabAdd: function sss_onTabAdd(aWindow, aPanel, aNoNotification) {
-    aPanel.addEventListener("load", this, true);
-    aPanel.addEventListener("pageshow", this, true);
-    aPanel.addEventListener("change", this, true);
-    aPanel.addEventListener("input", this, true);
-    aPanel.addEventListener("DOMAutoComplete", this, true);
-    aPanel.addEventListener("scroll", this, true);
+  onTabAdd: function sss_onTabAdd(aWindow, aBrowser, aNoNotification) {
+    aBrowser.addEventListener("load", this, true);
+    aBrowser.addEventListener("pageshow", this, true);
+    aBrowser.addEventListener("change", this, true);
+    aBrowser.addEventListener("input", this, true);
+    aBrowser.addEventListener("DOMAutoComplete", this, true);
+    aBrowser.addEventListener("scroll", this, true);
     
     if (!aNoNotification) {
       this.saveStateDelayed(aWindow);
     }
   },
 
   /**
    * remove listeners for a tab
    * @param aWindow
    *        Window reference
-   * @param aPanel
-   *        TabPanel reference
+   * @param aBrowser
+   *        Browser reference
    * @param aNoNotification
    *        bool Do not save state if we're updating an existing tab
    */
-  onTabRemove: function sss_onTabRemove(aWindow, aPanel, aNoNotification) {
-    aPanel.removeEventListener("load", this, true);
-    aPanel.removeEventListener("pageshow", this, true);
-    aPanel.removeEventListener("change", this, true);
-    aPanel.removeEventListener("input", this, true);
-    aPanel.removeEventListener("DOMAutoComplete", this, true);
-    aPanel.removeEventListener("scroll", this, true);
+  onTabRemove: function sss_onTabRemove(aWindow, aBrowser, aNoNotification) {
+    aBrowser.removeEventListener("load", this, true);
+    aBrowser.removeEventListener("pageshow", this, true);
+    aBrowser.removeEventListener("change", this, true);
+    aBrowser.removeEventListener("input", this, true);
+    aBrowser.removeEventListener("DOMAutoComplete", this, true);
+    aBrowser.removeEventListener("scroll", this, true);
     
-    delete aPanel.__SS_data;
+    delete aBrowser.__SS_data;
     
     if (!aNoNotification) {
       this.saveStateDelayed(aWindow);
     }
   },
 
   /**
    * When a tab closes, collect its properties
    * @param aWindow
    *        Window reference
    * @param aTab
-   *        TabPanel reference
+   *        Tab reference
    */
   onTabClose: function sss_onTabClose(aWindow, aTab) {
     // notify the tabbrowser that the tab state will be retrieved for the last time
     // (so that extension authors can easily set data on soon-to-be-closed tabs)
     var event = aWindow.document.createEvent("Events");
     event.initEvent("SSTabClosing", true, false);
     aTab.dispatchEvent(event);
     
@@ -814,68 +806,66 @@ SessionStoreService.prototype = {
         this._windows[aWindow.__SSi]._closedTabs.splice(maxTabsUndo, length - maxTabsUndo);
     }
   },
 
   /**
    * When a tab loads, save state.
    * @param aWindow
    *        Window reference
-   * @param aPanel
-   *        TabPanel reference
+   * @param aBrowser
+   *        Browser reference
    * @param aEvent
    *        Event obj
    */
-  onTabLoad: function sss_onTabLoad(aWindow, aPanel, aEvent) { 
+  onTabLoad: function sss_onTabLoad(aWindow, aBrowser, aEvent) { 
     // react on "load" and solitary "pageshow" events (the first "pageshow"
     // following "load" is too late for deleting the data caches)
     if (aEvent.type != "load" && !aEvent.persisted) {
       return;
     }
     
-    delete aPanel.__SS_data;
+    delete aBrowser.__SS_data;
     this.saveStateDelayed(aWindow);
     
     // attempt to update the current URL we send in a crash report
     this._updateCrashReportURL(aWindow);
   },
 
   /**
-   * Called when a tabpanel sends the "input" notification 
+   * Called when a browser sends the "input" notification 
    * @param aWindow
    *        Window reference
-   * @param aPanel
-   *        TabPanel reference
+   * @param aBrowser
+   *        Browser reference
    */
-  onTabInput: function sss_onTabInput(aWindow, aPanel) {
-    if (aPanel.__SS_data)
-      delete aPanel.__SS_data._formDataSaved;
+  onTabInput: function sss_onTabInput(aWindow, aBrowser) {
+    if (aBrowser.__SS_data)
+      delete aBrowser.__SS_data._formDataSaved;
     
     this.saveStateDelayed(aWindow, 3000);
   },
 
   /**
-   * Called when a tabpanel sends a "scroll" notification 
+   * Called when a browser sends a "scroll" notification 
    * @param aWindow
    *        Window reference
    */
   onTabScroll: function sss_onTabScroll(aWindow) {
     this.saveStateDelayed(aWindow, 3000);
   },
 
   /**
    * When a tab is selected, save session data
    * @param aWindow
    *        Window reference
-   * @param aPanels
-   *        TabPanel reference
    */
-  onTabSelect: function sss_onTabSelect(aWindow, aPanels) {
+  onTabSelect: function sss_onTabSelect(aWindow) {
     if (this._loadState == STATE_RUNNING) {
-      this._windows[aWindow.__SSi].selected = aPanels.selectedIndex;
+      this._windows[aWindow.__SSi].selected = aWindow.gBrowser.tabContainer.selectedIndex;
       this.saveStateDelayed(aWindow);
 
       // attempt to update the current URL we send in a crash report
       this._updateCrashReportURL(aWindow);
     }
   },
 
 /* ........ nsISessionStore API .............. */
@@ -1151,43 +1141,43 @@ SessionStoreService.prototype = {
    */
   _collectTabData: function sss_collectTabData(aTab, aFullData) {
     var tabData = { entries: [] };
     var browser = aTab.linkedBrowser;
     
     if (!browser || !browser.currentURI)
       // can happen when calling this function right after .addTab()
       return tabData;
-    else if (browser.parentNode.__SS_data && browser.parentNode.__SS_data._tabStillLoading)
+    else if (browser.__SS_data && browser.__SS_data._tabStillLoading)
       // use the data to be restored when the tab hasn't been completely loaded
-      return browser.parentNode.__SS_data;
+      return browser.__SS_data;
     
     var history = null;
     try {
       history = browser.sessionHistory;
     }
     catch (ex) { } // this could happen if we catch a tab during (de)initialization
     
     // XXXzeniko anchor navigation doesn't reset __SS_data, so we could reuse
     //           data even when we shouldn't (e.g. Back, different anchor)
-    if (history && browser.parentNode.__SS_data &&
-        browser.parentNode.__SS_data.entries[history.index] &&
+    if (history && browser.__SS_data &&
+        browser.__SS_data.entries[history.index] &&
         history.index < this._sessionhistory_max_entries - 1 && !aFullData) {
-      tabData = browser.parentNode.__SS_data;
+      tabData = browser.__SS_data;
       tabData.index = history.index + 1;
     }
     else if (history && history.count > 0) {
       for (var j = 0; j < history.count; j++)
         tabData.entries.push(this._serializeHistoryEntry(history.getEntryAtIndex(j, false),
                                                          aFullData));
       tabData.index = history.index + 1;
 
       // make sure not to cache privacy sensitive data which shouldn't get out
       if (!aFullData)
-        browser.parentNode.__SS_data = tabData;
+        browser.__SS_data = tabData;
     }
     else if (browser.currentURI.spec != "about:blank" ||
              browser.contentDocument.body.hasChildNodes()) {
       tabData.entries[0] = { url: browser.currentURI.spec };
       tabData.index = 1;
     }
     
     var disallow = [];
@@ -1403,18 +1393,18 @@ SessionStoreService.prototype = {
    * @param aWindow
    *        Window reference
    */
   _updateTextAndScrollData: function sss_updateTextAndScrollData(aWindow) {
     var browsers = aWindow.getBrowser().browsers;
     for (var i = 0; i < browsers.length; i++) {
       try {
         var tabData = this._windows[aWindow.__SSi].tabs[i];
-        if (browsers[i].parentNode.__SS_data &&
-            browsers[i].parentNode.__SS_data._tabStillLoading)
+        if (browsers[i].__SS_data &&
+            browsers[i].__SS_data._tabStillLoading)
           continue; // ignore incompletely initialized tabs
         this._updateTextAndScrollDataForTab(aWindow, browsers[i], tabData);
       }
       catch (ex) { debug(ex); } // get as much data as possible, ignore failures (might succeed the next time)
     }
   },
 
   /**
@@ -1965,17 +1955,17 @@ SessionStoreService.prototype = {
       // wall-paper fix for bug 439675: make sure that the URL to be loaded
       // is always visible in the address bar
       let activeIndex = (aTabData[t].index || aTabData[t].entries.length) - 1;
       let activePageData = aTabData[t].entries[activeIndex] || null;
       browser.userTypedValue = activePageData ? activePageData.url || null : null;
       
       // keep the data around to prevent dataloss in case
       // a tab gets closed before it's been properly restored
-      browser.parentNode.__SS_data = aTabData[t];
+      browser.__SS_data = aTabData[t];
     }
     
     if (aTabs.length > 0) {
       // Determine if we can optimize & load visible tabs first
       let maxVisibleTabs = Math.ceil(tabbrowser.tabContainer.mTabstrip.scrollClientSize /
                                      aTabs[0].clientWidth);
 
       // make sure we restore visible tabs first, if there are enough