Bug 893061 - Prevent the default homepage from loading if we're going to restore a session; r=dao

This commit is contained in:
Tim Taubert 2013-07-26 13:16:29 +02:00
parent 1a6dcad173
commit a0f140ad02
3 changed files with 81 additions and 71 deletions

View File

@ -728,18 +728,6 @@ const gFormSubmitObserver = {
var gBrowserInit = {
onLoad: function() {
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
// nsISupportsStrings to load, or a xul:tab of
// a tabbrowser, which will be replaced by this
// window (for this case, all other arguments are
// ignored).
// [1]: character set (string)
// [2]: referrer (nsIURI)
// [3]: postData (nsIInputStream)
// [4]: allowThirdPartyFixup (bool)
if ("arguments" in window && window.arguments[0])
var uriToLoad = window.arguments[0];
gMultiProcessBrowser = gPrefService.getBoolPref("browser.tabs.remote");
var mustLoadSidebar = false;
@ -780,6 +768,7 @@ var gBrowserInit = {
new nsBrowserAccess();
// set default character set if provided
// window.arguments[1]: character set (string)
if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
if (window.arguments[1].startsWith("charset=")) {
var arrayArgComponents = window.arguments[1].split("=");
@ -946,7 +935,7 @@ var gBrowserInit = {
retrieveToolbarIconsizesFromTheme();
// Wait until chrome is painted before executing code not critical to making the window visible
this._boundDelayedStartup = this._delayedStartup.bind(this, uriToLoad, mustLoadSidebar);
this._boundDelayedStartup = this._delayedStartup.bind(this, mustLoadSidebar);
window.addEventListener("MozAfterPaint", this._boundDelayedStartup);
this._loadHandled = true;
@ -957,7 +946,7 @@ var gBrowserInit = {
this._boundDelayedStartup = null;
},
_delayedStartup: function(uriToLoad, mustLoadSidebar) {
_delayedStartup: function(mustLoadSidebar) {
let tmp = {};
Cu.import("resource://gre/modules/TelemetryTimestamps.jsm", tmp);
let TelemetryTimestamps = tmp.TelemetryTimestamps;
@ -976,6 +965,7 @@ var gBrowserInit = {
socialBrowser.addEventListener("MozApplicationManifest",
OfflineApps, false);
let uriToLoad = this._getUriToLoad();
var isLoadingBlank = isBlankPageURL(uriToLoad);
// This pageshow listener needs to be registered before we may call
@ -1012,6 +1002,9 @@ var gBrowserInit = {
gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, uriToLoad);
}
// window.arguments[2]: referrer (nsIURI)
// [3]: postData (nsIInputStream)
// [4]: allowThirdPartyFixup (bool)
else if (window.arguments.length >= 3) {
loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null,
window.arguments[4] || false);
@ -1293,6 +1286,31 @@ var gBrowserInit = {
TelemetryTimestamps.add("delayedStartupFinished");
},
// Returns the URI(s) to load at startup.
_getUriToLoad: function () {
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
// nsISupportsStrings to load, or a xul:tab of
// a tabbrowser, which will be replaced by this
// window (for this case, all other arguments are
// ignored).
if (!window.arguments || !window.arguments[0])
return null;
let uri = window.arguments[0];
let sessionStartup = Cc["@mozilla.org/browser/sessionstartup;1"]
.getService(Ci.nsISessionStartup);
let defaultArgs = Cc["@mozilla.org/browser/clh;1"]
.getService(Ci.nsIBrowserHandler)
.defaultArgs;
// If the given URI matches defaultArgs (the default homepage) we want
// to block its load if we're going to restore a session anyway.
if (uri == defaultArgs && sessionStartup.willOverrideHomepage)
return null;
return uri;
},
onUnload: function() {
// In certain scenarios it's possible for unload to be fired before onload,
// (e.g. if the window is being closed after browser.js loads but before the

View File

@ -10,7 +10,7 @@
* - and allows to restore everything into one window.
*/
[scriptable, uuid(35235b39-7098-4b3b-8e28-cd004a88b06f)]
[scriptable, uuid(51f4b9f0-f3d2-11e2-bb62-2c24dd830245)]
interface nsISessionStartup: nsISupports
{
/**
@ -23,10 +23,24 @@ interface nsISessionStartup: nsISupports
readonly attribute jsval state;
/**
* Determine if session should be restored
* Determines whether there is a pending session restore and makes sure that
* we're initialized before returning. If we're not yet this will read the
* session file synchronously.
*/
boolean doRestore();
/**
* Returns whether we will restore a session that ends up replacing the
* homepage. The browser uses this to not start loading the homepage if
* we're going to stop its load anyway shortly after.
*
* This is meant to be an optimization for the average case that loading the
* session file finishes before we may want to start loading the default
* homepage. Should this be called before the session file has been read it
* will just return false.
*/
readonly attribute bool willOverrideHomepage;
/**
* What type of session we're restoring.
* NO_SESSION There is no data available from the previous session

View File

@ -162,15 +162,6 @@ SessionStartup.prototype = {
else
this._initialState = null; // reset the state
// wait for the first browser window to open
// Don't reset the initial window's default args (i.e. the home page(s))
// if all stored tabs are pinned.
if (this.doRestore() &&
(!this._initialState.windows ||
!this._initialState.windows.every(function (win)
win.tabs.every(function (tab) tab.pinned))))
Services.obs.addObserver(this, "domwindowopened", true);
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
@ -204,14 +195,6 @@ SessionStartup.prototype = {
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
Services.obs.removeObserver(this, "browser:purge-session-history");
break;
case "domwindowopened":
var window = aSubject;
var self = this;
window.addEventListener("load", function() {
self._onWindowOpened(window);
window.removeEventListener("load", arguments.callee, false);
}, false);
break;
case "sessionstore-windows-restored":
Services.obs.removeObserver(this, "sessionstore-windows-restored");
// free _initialState after nsSessionStore is done with it
@ -225,43 +208,6 @@ SessionStartup.prototype = {
}
},
/**
* Removes the default arguments from the first browser window
* (and removes the "domwindowopened" observer afterwards).
*/
_onWindowOpened: function sss_onWindowOpened(aWindow) {
var wType = aWindow.document.documentElement.getAttribute("windowtype");
if (wType != "navigator:browser")
return;
/**
* Note: this relies on the fact that nsBrowserContentHandler will return
* a different value the first time its getter is called after an update,
* due to its needHomePageOverride() logic. We don't want to remove the
* default arguments in the update case, since they include the "What's
* New" page.
*
* Since we're garanteed to be at least the second caller of defaultArgs
* (nsBrowserContentHandler calls it to determine which arguments to pass
* at startup), we know that if the window's arguments don't match the
* current defaultArguments, we're either in the update case, or we're
* launching a non-default browser window, so we shouldn't remove the
* window's arguments.
*/
var defaultArgs = Cc["@mozilla.org/browser/clh;1"].
getService(Ci.nsIBrowserHandler).defaultArgs;
if (aWindow.arguments && aWindow.arguments[0] &&
aWindow.arguments[0] == defaultArgs)
aWindow.arguments[0] = null;
try {
Services.obs.removeObserver(this, "domwindowopened");
} catch (e) {
// This might throw if we're removing the observer multiple times,
// but this is safe to ignore.
}
},
/* ........ Public API ................*/
get onceInitialized() {
@ -277,15 +223,47 @@ SessionStartup.prototype = {
},
/**
* Determine whether there is a pending session restore.
* Determines whether there is a pending session restore and makes sure that
* we're initialized before returning. If we're not yet this will read the
* session file synchronously.
* @returns bool
*/
doRestore: function sss_doRestore() {
this._ensureInitialized();
return this._willRestore();
},
/**
* Determines whether there is a pending session restore.
* @returns bool
*/
_willRestore: function () {
return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
},
/**
* Returns whether we will restore a session that ends up replacing the
* homepage. The browser uses this to not start loading the homepage if
* we're going to stop its load anyway shortly after.
*
* This is meant to be an optimization for the average case that loading the
* session file finishes before we may want to start loading the default
* homepage. Should this be called before the session file has been read it
* will just return false.
*
* @returns bool
*/
get willOverrideHomepage() {
if (this._initialState && this._willRestore()) {
let windows = this._initialState.windows || null;
// If there are valid windows with not only pinned tabs, signal that we
// will override the default homepage by restoring a session.
return windows && windows.some(w => w.tabs.some(t => !t.pinned));
}
return false;
},
/**
* Get the type of pending session store, if any.
*/