diff --git a/browser/components/sessionstore/ContentRestore.jsm b/browser/components/sessionstore/ContentRestore.jsm index 258f7c3480c5..e6e8179db623 100644 --- a/browser/components/sessionstore/ContentRestore.jsm +++ b/browser/components/sessionstore/ContentRestore.jsm @@ -8,6 +8,7 @@ this.EXPORTED_SYMBOLS = ["ContentRestore"]; const Cu = Components.utils; const Ci = Components.interfaces; +const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); @@ -182,8 +183,19 @@ ContentRestoreInternal.prototype = { let webNavigation = this.docShell.QueryInterface(Ci.nsIWebNavigation); let history = webNavigation.sessionHistory; - // Listen for the tab to finish loading. - this.restoreTabContentStarted(finishCallback); + // Wait for the tab load to complete or fail + this.restoreTabContentStarted((status) => { + // If loadArgument is not null then we're attempting to load a new url + // that required us to switch process. If that load is cancelled (for + // example by a content handler) we want to restore the current history + // entry. + if (loadArguments && (status == Cr.NS_BINDING_ABORTED)) { + this._tabData = tabData; + this.restoreTabContent(null, finishCallback); + } else { + finishCallback(); + } + }); // Reset the current URI to about:blank. We changed it above for // switch-to-tab, but now it must go back to the correct value before the @@ -248,22 +260,26 @@ ContentRestoreInternal.prototype = { */ restoreTabContentStarted(finishCallback) { // The reload listener is no longer needed. - this._historyListener.uninstall(); - this._historyListener = null; + if (this._historyListener) { + this._historyListener.uninstall(); + this._historyListener = null; + } // Remove the old progress listener. - this._progressListener.uninstall(); + if (this._progressListener) { + this._progressListener.uninstall(); + } // We're about to start a load. This listener will be called when the load // has finished getting everything from the network. this._progressListener = new ProgressListener(this.docShell, { - onStopRequest: () => { + onStopRequest: (status) => { // Call resetRestore() to reset the state back to normal. The data // needed for restoreDocument() (which hasn't happened yet) will // remain in _restoringDocument. this.resetRestore(); - finishCallback(); + finishCallback(status); } }); }, @@ -415,7 +431,7 @@ ProgressListener.prototype = { } if (stateFlags & STATE_STOP && this.callbacks.onStopRequest) { - this.callbacks.onStopRequest(); + this.callbacks.onStopRequest(status); } }, diff --git a/browser/components/sessionstore/test/browser_switch_remoteness.js b/browser/components/sessionstore/test/browser_switch_remoteness.js index e670c37b3822..d90252124726 100644 --- a/browser/components/sessionstore/test/browser_switch_remoteness.js +++ b/browser/components/sessionstore/test/browser_switch_remoteness.js @@ -45,3 +45,53 @@ add_task(function* () { // Cleanup. gBrowser.removeTab(tab); }); + +add_task(function* () { + // Add a new non-remote tab. + let tab = gBrowser.addTab("about:robots"); + let browser = tab.linkedBrowser; + yield promiseBrowserLoaded(browser); + ok(!browser.isRemoteBrowser, "browser is not remote"); + + // Wait for the tab to change to remote before adding the progress listener + tab.addEventListener("TabRemotenessChange", function listener() { + tab.removeEventListener("TabRemotenessChange", listener); + + ContentTask.spawn(browser, URL, function*(url) { + Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + + let wp = docShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebProgress); + + wp.addProgressListener({ + onStateChange: function(progress, request, stateFlags, status) { + if (!(request instanceof Ci.nsIChannel)) + return; + + if (request.URI.spec == url) { + request.cancel(Cr.NS_BINDING_ABORTED); + wp.removeProgressListener(this); + } + }, + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIWebProgressListener, + Ci.nsISupportsWeakReference + ]) + }, Ci.nsIWebProgress.NOTIFY_ALL); + }); + }); + + // Load a new remote URI and when we see the load start cancel it + browser.loadURI(URL); + yield promiseTabRestored(tab); + + let count = yield countHistoryEntries(browser); + is(count, 1, "Should only be the one history entry."); + + is(browser.currentURI.spec, "about:robots", "Should be back to the original URI"); + ok(!browser.isRemoteBrowser, "Should have gone back to a remote browser"); + + // Cleanup. + gBrowser.removeTab(tab); +});