Mozilla Home
Privacy
Cookies
Legal
Bugzilla
Browse
Advanced Search
New Bug
Reports
Documentation
Log In
Log In with GitHub
or
Remember me
Browse
Advanced Search
New Bug
Reports
Documentation
Attachment 475436 Details for
Bug 586068
[patch]
Patch v0.6 (WIP)
bug-586068-0.6.patch (text/plain), 26.70 KB, created by
Paul O'Shannessy [:zpao] (not bugmail, email directly)
(
hide
)
Description:
Patch v0.6 (WIP)
Filename:
MIME Type:
Creator:
Paul O'Shannessy [:zpao] (not bugmail, email directly)
Size:
26.70 KB
patch
obsolete
># HG changeset patch ># User Paul OâShannessy <paul@oshannessy.com> ># Date 1284532171 25200 >Bug 586068 - Cascade page loads when restoring > >diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js >--- a/browser/app/profile/firefox.js >+++ b/browser/app/profile/firefox.js >@@ -788,16 +788,18 @@ pref("browser.sessionstore.privacy_level > // how many tabs can be reopened (per window) > pref("browser.sessionstore.max_tabs_undo", 10); > // how many windows can be reopened (per session) - on non-OS X platforms this > // pref may be ignored when dealing with pop-up windows to ensure proper startup > pref("browser.sessionstore.max_windows_undo", 3); > // number of crashes that can occur before the about:sessionrestore page is displayed > // (this pref has no effect if more than 6 hours have passed since the last crash) > pref("browser.sessionstore.max_resumed_crashes", 1); >+// number of tabs to restore concurrently >+pref("browser.sessionstore.max_concurrent_tabs", 3); > > // allow META refresh by default > pref("accessibility.blockautorefresh", false); > > // Whether history is enabled or not. > pref("places.history.enabled", true); > > // The percentage of system memory that the Places database can use. Out of the >diff --git a/browser/components/sessionstore/src/nsSessionStore.js b/browser/components/sessionstore/src/nsSessionStore.js >--- a/browser/components/sessionstore/src/nsSessionStore.js >+++ b/browser/components/sessionstore/src/nsSessionStore.js >@@ -109,16 +109,19 @@ const CAPABILITIES = [ > "Subframes", "Plugins", "Javascript", "MetaRedirects", "Images", > "DNSPrefetch", "Auth" > ]; > > // These keys are for internal use only - they shouldn't be part of the JSON > // that gets saved to disk nor part of the strings returned by the API. > const INTERNAL_KEYS = ["_tabStillLoading", "_hosts", "_formDataSaved"]; > >+// These are tab events that we listen to. >+const TAB_EVENTS = ["TabOpen", "TabClose", "TabSelect", "TabShow", "TabHide"]; >+ > #ifndef XP_WIN > #define BROKEN_WM_Z_ORDER > #endif > > Cu.import("resource://gre/modules/XPCOMUtils.jsm"); > Cu.import("resource://gre/modules/Services.jsm"); > > XPCOMUtils.defineLazyGetter(this, "NetUtil", function() { >@@ -196,16 +199,23 @@ SessionStoreService.prototype = { > _inPrivateBrowsing: false, > > // whether we clearing history on shutdown > _clearingOnShutdown: false, > > // whether the last window was closed and should be restored > _restoreLastWindow: false, > >+ // tabs to restore in order >+ _tabsToRestore: { visible: [], hidden: [] }, >+ _tabsRestoringCount: 0, >+ >+ // number of tabs to restore concurrently, pref controlled. >+ _maxConcurrentRestores: null, >+ > // The state from the previous session (after restoring pinned tabs) > _lastSessionState: null, > > /* ........ Public Getters .............. */ > > get canRestoreLastSession() { > // Always disallow restoring the previous session when in private browsing > return this._lastSessionState && !this._inPrivateBrowsing; >@@ -254,16 +264,25 @@ SessionStoreService.prototype = { > // observe prefs changes so we can modify stored data to match > this._prefBranch.addObserver("sessionstore.max_tabs_undo", this, true); > this._prefBranch.addObserver("sessionstore.max_windows_undo", this, true); > > // this pref is only read at startup, so no need to observe it > this._sessionhistory_max_entries = > this._prefBranch.getIntPref("sessionhistory.max_entries"); > >+ this._maxConcurrentRestores = >+ this._prefBranch.getIntPref("sessionstore.max_concurrent_tabs"); >+ >+ // Make sure gRestoreTabsProgressListener has a reference to sessionstore >+ // so that it can make calls back in >+ dump("\n\nGANGSTA - " + gRestoreTabsProgressListener.ss); >+ gRestoreTabsProgressListener.ss = this; >+ dump("\n\nGANGSTA - " + gRestoreTabsProgressListener.ss); >+ > // get file references > this._sessionFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile); > this._sessionFileBackup = this._sessionFile.clone(); > this._sessionFile.append("sessionstore.js"); > this._sessionFileBackup.append("sessionstore.bak"); > > // get string containing session state > var iniString; >@@ -343,16 +362,25 @@ SessionStoreService.prototype = { > /** > * Called on application shutdown, after notifications: > * quit-application-granted, quit-application > */ > _uninit: function sss_uninit() { > // save all data for session resuming > this.saveState(true); > >+ // clear out _tabsToRestore in case it's still holding refs >+ this._tabsToRestore = null; >+ >+ // remove the ref to us from the progress listener >+ dump("\n\nGANGSTA - " + gRestoreTabsProgressListener.ss); >+ gRestoreTabsProgressListener.ss = null; >+ dump("\n\nGANGSTA - " + gRestoreTabsProgressListener.ss); >+ // gRestoreTabsProgressListener = null; >+ > // Make sure to break our cycle with the save timer > if (this._saveTimer) { > this._saveTimer.cancel(); > this._saveTimer = null; > } > }, > > /** >@@ -398,16 +426,17 @@ SessionStoreService.prototype = { > 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.gBrowser.browsers, function(aBrowser) { > delete aBrowser.__SS_data; >+ delete aBrowser.__SS_needsRestore; > }); > 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 >@@ -502,16 +531,19 @@ SessionStoreService.prototype = { > case "sessionstore.resume_from_crash": > this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash"); > // 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.max_concurrent_tabs": >+ this._maxConcurrentRestores = >+ this._prefBranch.getIntPref("sessionstore.max_concurrent_tabs"); > } > break; > case "timer-callback": // timer call back for delayed saving > this._saveTimer = null; > this.saveState(); > break; > case "private-browsing": > switch (aData) { >@@ -542,16 +574,19 @@ SessionStoreService.prototype = { > 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._tabsToRestore = { visible: [], hidden: [] }; > break; > } > }, > > /* ........ Window Event Handlers .............. */ > > /** > * Implement nsIDOMEventListener for handling various window and tab events >@@ -585,16 +620,22 @@ SessionStoreService.prototype = { > if (!aEvent.detail) > this.onTabClose(win, aEvent.originalTarget); > this.onTabRemove(win, browser); > } > break; > case "TabSelect": > this.onTabSelect(win); > break; >+ case "TabShow": >+ this.onTabShow(aEvent.originalTarget); >+ break; >+ case "TabHide": >+ this.onTabHide(aEvent.originalTarget); >+ 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 > * - restart downloads >@@ -690,20 +731,20 @@ SessionStoreService.prototype = { > } > > var tabbrowser = aWindow.gBrowser; > > // add tab change listeners to all already existing tabs > for (let i = 0; i < tabbrowser.browsers.length; i++) { > this.onTabAdd(aWindow, tabbrowser.browsers[i], true); > } >- // notification of tab add/remove/selection >- tabbrowser.tabContainer.addEventListener("TabOpen", this, true); >- tabbrowser.tabContainer.addEventListener("TabClose", this, true); >- tabbrowser.tabContainer.addEventListener("TabSelect", this, true); >+ // notification of tab add/remove/selection/show/hide >+ TAB_EVENTS.forEach(function(aEvent) { >+ tabbrowser.tabContainer.addEventListener(aEvent, this, true); >+ }, this); > }, > > /** > * On window close... > * - remove event listeners from tabs > * - save all window data > * @param aWindow > * Window reference >@@ -725,19 +766,27 @@ SessionStoreService.prototype = { > } > > if (this.windowToFocus && this.windowToFocus == aWindow) { > delete this.windowToFocus; > } > > var tabbrowser = aWindow.gBrowser; > >- tabbrowser.tabContainer.removeEventListener("TabOpen", this, true); >- tabbrowser.tabContainer.removeEventListener("TabClose", this, true); >- tabbrowser.tabContainer.removeEventListener("TabSelect", this, true); >+ TAB_EVENTS.forEach(function(aEvent) { >+ tabbrowser.tabContainer.removeEventListener(aEvent, this, true); >+ }, this); >+ >+ // remove the progress listener for this window >+ dump("\n\nREMOVING PROGRESS LISTENER\n"); >+ dump(tabbrowser.mTabsProgressListeners.length + " - - " + >+ tabbrowser.mTabsProgressListeners.indexOf(gRestoreTabsProgressListener) + "\n\n"); >+ tabbrowser.removeTabsProgressListener(gRestoreTabsProgressListener); >+ dump(tabbrowser.mTabsProgressListeners.length + " - - " + >+ tabbrowser.mTabsProgressListeners.indexOf(gRestoreTabsProgressListener) + "\n\n"); > > 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 > this._collectWindowData(aWindow); > > if (isFullyLoaded) { > winData.title = aWindow.content.document.title || tabbrowser.selectedTab.label; >@@ -805,16 +854,21 @@ SessionStoreService.prototype = { > 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); > > delete aBrowser.__SS_data; >+ >+ // if (aBrowser.__SS_listener) { >+ // aBrowser.__SS_listener.remove(); >+ // this.restoreNextTab(true); >+ // } > > if (!aNoNotification) { > this.saveStateDelayed(aWindow); > } > }, > > /** > * When a tab closes, collect its properties >@@ -899,21 +953,54 @@ SessionStoreService.prototype = { > * When a tab is selected, save session data > * @param aWindow > * Window reference > */ > onTabSelect: function sss_onTabSelect(aWindow) { > if (this._loadState == STATE_RUNNING) { > this._windows[aWindow.__SSi].selected = aWindow.gBrowser.tabContainer.selectedIndex; > >+ let tab = aWindow.gBrowser.selectedTab; >+ // If __SS_needsRestore is still on the browser, then we haven't restored >+ // this tab yet. Explicitly call restoreTab to kick off the restore. >+ if (tab.linkedBrowser.__SS_needsRestore) { >+ // In theory, it should only be possible to select visible tabs, but >+ // make sure we look in the right place for the tab. >+ let tabsArr = tab.hidden ? this._tabsToRestore.hidden >+ : this._tabsToRestore.visible; >+ >+ let index = tabsArr.indexOf(tab); >+ // Use the index to restore the tab while also removing it from the array. >+ if (index > -1) >+ this.restoreTab(tabsArr.splice(index, 1)[0]); >+ } >+ > // attempt to update the current URL we send in a crash report > this._updateCrashReportURL(aWindow); > } > }, > >+ onTabShow: function sss_onTabShow(aTab) { >+ // If the tab hasn't been restored yet, move it into the right _tabsToRestore bucket >+ if (aTab.linkedBrowser.__SS_data) { >+ this._tabsToRestore.hidden.splice(this.tabsToRestore.hidden.indexOf(aTab)); >+ // Just put it at the end of the list of visible tabs; >+ this._tabsToRestore.visible.push(aTab); >+ } >+ }, >+ >+ onTabHide: function sss_onTabHide(aTab) { >+ // If the tab hasn't been restored yet, move it into the right _tabsToRestore bucket >+ if (aTab.linkedBrowser.__SS_data) { >+ this._tabsToRestore.visible.splice(this.tabsToRestore.visible.indexOf(aTab)); >+ // Just put it at the end of the list of hidden tabs; >+ this._tabsToRestore.hidden.push(aTab); >+ } >+ }, >+ > /* ........ nsISessionStore API .............. */ > > getBrowserState: function sss_getBrowserState() { > return this._toJSONString(this._getCurrentState()); > }, > > setBrowserState: function sss_setBrowserState(aState) { > this._handleClosedWindows(); >@@ -2142,16 +2229,20 @@ SessionStoreService.prototype = { > } > for (var key in winData.extData) { > this._windows[aWindow.__SSi].extData[key] = winData.extData[key]; > } > } > if (aOverwriteTabs || root._firstTabs) { > this._windows[aWindow.__SSi]._closedTabs = winData._closedTabs || []; > } >+ >+ // Add gRestoreTabsProgressListener to the tabbrowser >+ if (tabbrowser.mTabsProgressListeners.indexOf(gRestoreTabsProgressListener) == -1) >+ tabbrowser.addTabsProgressListener(gRestoreTabsProgressListener); > > this.restoreHistoryPrecursor(aWindow, tabs, winData.tabs, > (aOverwriteTabs ? (parseInt(winData.selected) || 1) : 0), 0, 0); > > // set smoothScroll back to the original value > tabstrip.smoothScroll = smoothScroll; > > this._sendRestoreCompletedNotifications(); >@@ -2214,27 +2305,31 @@ SessionStoreService.prototype = { > browser.contentDocument.location = "about:blank"; > continue; > } > > browser.stop(); // in case about:blank isn't done yet > > tab.setAttribute("busy", "true"); > tabbrowser.updateIcon(tab); >- tabbrowser.setTabTitleLoading(tab); > > // wall-paper fix for bug 439675: make sure that the URL to be loaded > // is always visible in the address bar > let activeIndex = (tabData.index || tabData.entries.length) - 1; > let activePageData = tabData.entries[activeIndex] || null; > browser.userTypedValue = activePageData ? activePageData.url || null : null; >- >+ >+ // If the page has a title, set it. >+ if (activePageData && activePageData.title) >+ tab.label = activePageData.title; >+ > // keep the data around to prevent dataloss in case > // a tab gets closed before it's been properly restored > browser.__SS_data = tabData; >+ browser.__SS_needsRestore = true; > } > > if (aTabs.length > 0) { > // Load hidden tabs last, by pushing them to the end of the list > let unhiddenTabs = aTabs.length; > for (let t = 0; t < unhiddenTabs; ) { > if (aTabs[t].hidden) { > aTabs = aTabs.concat(aTabs.splice(t, 1)); >@@ -2278,124 +2373,182 @@ SessionStoreService.prototype = { > // from now on, the data will come from the actual window > delete this._statesToRestore[aWindow.__SS_restoreID]; > delete aWindow.__SS_restoreID; > delete this._windows[aWindow.__SSi]._restoring; > } > > // helper hashes for ensuring unique frame IDs and unique document > // identifiers. >- var idMap = { used: {} }; >- var docIdentMap = {}; >- this.restoreHistory(aWindow, aTabs, aTabData, idMap, docIdentMap); >+ aWindow.setTimeout(function(self) { >+ self.restoreHistory(aWindow, aTabs, aTabData); >+ }, 0, this); >+ // var idMap = { used: {} }; >+ // var docIdentMap = {}; >+ // this.restoreHistory(aWindow, aTabs, aTabData, idMap, docIdentMap); > }, > > /** > * Restory history for a window > * @param aWindow > * Window reference > * @param aTabs > * Array of tab references > * @param aTabData > * Array of tab data > * @param aIdMap > * Hash for ensuring unique frame IDs > */ > restoreHistory: >- function sss_restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap) { >- var _this = this; >- while (aTabs.length > 0 && (!aTabData[0]._tabStillLoading || !aTabs[0].parentNode)) { >- aTabs.shift(); // this tab got removed before being completely restored >- aTabData.shift(); >+ function sss_restoreHistory(aWindow, aTabs, aTabData) { >+ >+ let idMap = { used: {} }; >+ let docIdentMap = { }; >+ >+ for(let i = 0; i < aTabs.length; i++) { >+ let tab = aTabs[i]; >+ let tabData = aTabData[i]; >+ >+ // Check if tab got removed before being completely restored >+ if (!tabData._tabStillLoading || !tab.parentNode) >+ continue; >+ >+ let browser = tab.linkedBrowser; >+ let history = browser.webNavigation.sessionHistory; >+ history.QueryInterface(Ci.nsISHistoryInternal); >+ >+ if (history.count > 0) >+ history.PurgeHistory(history.count); >+ >+ // Make sure we at least have an empty array of history entries >+ tabData.entries = tabData.entries || []; >+ >+ if (tabData.extData) >+ tab.__extData = tabData.extData; >+ else >+ delete tab.__extData; >+ >+ for (let i = 0; i < tabData.entries.length; i++) { >+ //XXXzpao Wallpaper patch for bug 514751 >+ if (!tabData.entries[i].url) >+ return; >+ history.addEntry(this._deserializeHistoryEntry(tabData.entries[i], >+ idMap, docIdentMap), true); >+ } >+ >+ >+ // make sure to reset the capabilities and attributes, in case this tab gets reused >+ let disallow = tabData.disallow ? tabData.disallow.split(",") : []; >+ CAPABILITIES.forEach(function(aCapability) { >+ browser.docShell["allow" + aCapability] = disallow.indexOf(aCapability) == -1; >+ }); >+ Array.forEach(tab.attributes, function(aAttr) { >+ if (this.xulAttributes.indexOf(aAttr.name) > -1) >+ tab.removeAttribute(aAttr, tab); >+ }, this); >+ for (let [name, val] in Iterator(tabData.attributes)) >+ tab.setAttribute(name, val); >+ >+ if (tabData.storage && browser.docShell instanceof Ci.nsIDocShell) >+ this._deserializeSessionStorage(tabData.storage, browser.docShell); >+ >+ // notify the tabbrowser that the tab chrome has been restored >+ var event = aWindow.document.createEvent("Events"); >+ event.initEvent("SSTabRestoring", true, false); >+ tab.dispatchEvent(event); >+ >+ // Put the tab into the right bucket >+ if (tabData.hidden) >+ this._tabsToRestore.hidden.push(tab); >+ else >+ this._tabsToRestore.visible.push(tab); >+ this.restoreNextTab(); > } >- if (aTabs.length == 0) { >- return; // no more tabs to restore >- } >+ }, >+ >+ restoreTab: function(aTab) { >+ let browser = aTab.linkedBrowser; >+ let tabData = browser.__SS_data; > >- var tab = aTabs.shift(); >- var tabData = aTabData.shift(); >- >- var browser = aWindow.gBrowser.getBrowserForTab(tab); >- var history = browser.webNavigation.sessionHistory; >- >- if (history.count > 0) { >- history.PurgeHistory(history.count); >- } >- history.QueryInterface(Ci.nsISHistoryInternal); >- >- if (!tabData.entries) { >- tabData.entries = []; >- } >- if (tabData.extData) { >- tab.__SS_extdata = {}; >- for (let key in tabData.extData) >- tab.__SS_extdata[key] = tabData.extData[key]; >- } >- else >- delete tab.__SS_extdata; >- >- for (var i = 0; i < tabData.entries.length; i++) { >- //XXXzpao Wallpaper patch for bug 514751 >- if (!tabData.entries[i].url) >- continue; >- history.addEntry(this._deserializeHistoryEntry(tabData.entries[i], >- aIdMap, aDocIdentMap), true); >- } >- >- // make sure to reset the capabilities and attributes, in case this tab gets reused >- var disallow = (tabData.disallow)?tabData.disallow.split(","):[]; >- CAPABILITIES.forEach(function(aCapability) { >- browser.docShell["allow" + aCapability] = disallow.indexOf(aCapability) == -1; >- }); >- Array.filter(tab.attributes, function(aAttr) { >- return (_this.xulAttributes.indexOf(aAttr.name) > -1); >- }).forEach(tab.removeAttribute, tab); >- for (let name in tabData.attributes) >- tab.setAttribute(name, tabData.attributes[name]); >- >- if (tabData.storage && browser.docShell instanceof Ci.nsIDocShell) >- this._deserializeSessionStorage(tabData.storage, browser.docShell); >- >- // notify the tabbrowser that the tab chrome has been restored >- var event = aWindow.document.createEvent("Events"); >- event.initEvent("SSTabRestoring", true, false); >- tab.dispatchEvent(event); >- >+ // Increase our internal count. >+ this._tabsRestoringCount++; >+ > let activeIndex = (tabData.index || tabData.entries.length) - 1; > if (activeIndex >= tabData.entries.length) > activeIndex = tabData.entries.length - 1; >- try { >- if (activeIndex >= 0) >- browser.webNavigation.gotoIndex(activeIndex); >- } >- catch (ex) { >- // ignore page load errors >- tab.removeAttribute("busy"); >- } >- >- if (tabData.entries.length > 0) { >- // restore those aspects of the currently active documents >- // which are not preserved in the plain history entries >- // (mainly scroll state and text data) >+ >+ // Attach data that will be restored on "load" event, after tab is restored. >+ if (activeIndex > -1) { >+ // restore those aspects of the currently active documents which are not >+ // preserved in the plain history entries (mainly scroll state and text data) > browser.__SS_restore_data = tabData.entries[activeIndex] || {}; > browser.__SS_restore_pageStyle = tabData.pageStyle || ""; >- browser.__SS_restore_tab = tab; >+ browser.__SS_restore_tab = aTab; >+ >+ try { >+ dump("\nrestoreTab\n" + tabData.entries[activeIndex].url + "\n\n"); >+ // Get the tab title (set in restoreHistoryPrecursor) for later >+ let label = aTab.label; >+ browser.webNavigation.gotoIndex(activeIndex); >+ // gotoIndex will force the "loading" string, so set the title >+ aTab.label = label; >+ } >+ catch (ex) { >+ // ignore page load errors >+ aTab.removeAttribute("busy"); >+ //XXXzpao is this needed? >+ this.restoreNextTab(true); >+ } > } >- >+ else { >+ // If there is no active index, then we'll never set __SS_restore_data >+ // and even if there is a load event, we won't kick of the next tab >+ // (restoreDocument won't get called), so do it ourselves. >+ this.restoreNextTab(true); >+ } >+ >+ //XXXzpao should this be higher? Can we get stuck not running this until >+ // much later (something about breadth-first...) > // Handle userTypedValue. Setting userTypedValue seems to update gURLbar >- // as needed. Calling loadURI will cancel form filling in restoreDocument_proxy >+ // as needed. Calling loadURI will cancel form filling in restoreDocument > if (tabData.userTypedValue) { > browser.userTypedValue = tabData.userTypedValue; > if (tabData.userTypedClear) > browser.loadURI(tabData.userTypedValue, null, null, true); > } >- >- aWindow.setTimeout(function(){ >- _this.restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap); >- }, 0); >+ }, >+ >+ restoreNextTab: function sss_restoreNextTab(aFromTabFinished) { >+ dump("\nentering restoreNextTab...\n"); >+ // If we call in here while quitting, we don't actually want to do anything >+ if (this._loadState == STATE_QUITTING) >+ return; >+ if (aFromTabFinished) >+ this._tabsRestoringCount--; >+ >+ // Look in visible, then hidden >+ let nextTabArray; >+ if (this._tabsToRestore.visible.length) >+ nextTabArray = this._tabsToRestore.visible; >+ else if (this._tabsToRestore.hidden.length) >+ nextTabArray = this._tabsToRestore.hidden; >+ else >+ return; >+ //XXXzpao maybe we should remove gRestoreTabsProgressListener from each window? >+ >+ dump(this._tabsRestoringCount + " -- " + this._maxConcurrentRestores + "\n\n"); >+ >+ if (this._maxConcurrentRestores < 1 || >+ this._tabsRestoringCount < this._maxConcurrentRestores) { >+ let tab = nextTabArray.shift(); >+ let browser = tab.linkedBrowser; >+ let tabData = browser.__SS_data; >+ dump("\nrestoreNextTab\n" + tabData.entries[(tabData.index || tabData.entries.length) - 1].url + "\n\n"); >+ this.restoreTab(tab); >+ } > }, > > /** > * expands serialized history data into a session-history-entry instance > * @param aEntry > * Object containing serialized history data for a URL > * @param aIdMap > * Hash for ensuring unique frame IDs >@@ -2616,16 +2769,19 @@ SessionStoreService.prototype = { > var event = aBrowser.ownerDocument.createEvent("Events"); > event.initEvent("SSTabRestored", true, false); > aBrowser.__SS_restore_tab.dispatchEvent(event); > } > > delete aBrowser.__SS_restore_data; > delete aBrowser.__SS_restore_pageStyle; > delete aBrowser.__SS_restore_tab; >+ >+ // this._tabsRestoringCount--; >+ // this.restoreNextTab(); > }, > > /** > * Restore visibility and dimension features to a window > * @param aWindow > * Window reference > * @param aWinData > * Object containing session data for the window >@@ -3424,16 +3580,37 @@ let XPathHelper = { > let formNodesXPath = "//textarea|//select|//xhtml:textarea|//xhtml:select|" + > "//input[" + ignore + "]|//xhtml:input[" + ignore + "]"; > > delete this.restorableFormNodes; > return (this.restorableFormNodes = formNodesXPath); > } > }; > >+ >+let gRestoreTabsProgressListener = { >+ ss: null, >+ onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { >+ // Ignore state changes on browsers that we've already restored >+ if (!aBrowser.__SS_needsRestore) >+ return; >+ >+ if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && >+ aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK && >+ aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) { >+ dump("\n\nYO DAWG\n\n"); >+ delete aBrowser.__SS_needsRestore; >+ //this.remove(); >+ this.ss.restoreNextTab(true); >+ dump("\n\nAN OCEAN OF TREES?\n\n"); >+ } >+ } >+} >+ >+ > // see nsPrivateBrowsingService.js > String.prototype.hasRootDomain = function hasRootDomain(aDomain) > { > let index = this.indexOf(aDomain); > if (index == -1) > return false; > > if (this == aDomain)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
|
Review
Attachments on
bug 586068
:
465120
|
465914
|
472746
|
474924
|
475436
|
475770
|
476079
|
476423