Bug 753448 - Part 1 - Add BrowserNewTabPreloader.jsm; r=gavin

This commit is contained in:
Tim Taubert 2012-08-13 09:30:18 -07:00
parent 885b612cd1
commit 344804aa6b
4 changed files with 230 additions and 33 deletions

View File

@ -1136,6 +1136,8 @@ pref("browser.panorama.animate_zoom", true);
// Defines the url to be used for new tabs.
pref("browser.newtab.url", "about:newtab");
// Activates preloading of the new tab url.
pref("browser.newtab.preload", false);
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
pref("browser.newtabpage.enabled", true);

View File

@ -1813,6 +1813,33 @@
</body>
</method>
<method name="swapNewTabWithBrowser">
<parameter name="aNewTab"/>
<parameter name="aBrowser"/>
<body>
<![CDATA[
// The browser must be standalone.
if (aBrowser.getTabBrowser())
throw Cr.NS_ERROR_INVALID_ARG;
// The tab is definitely not loading.
aNewTab.removeAttribute("busy");
if (aNewTab == this.selectedTab) {
this.mIsBusy = false;
}
this._swapBrowserDocShells(aNewTab, aBrowser);
// Update the new tab's title.
this.setTabTitle(aNewTab);
if (aNewTab == this.selectedTab) {
this.updateCurrentBrowser(true);
}
]]>
</body>
</method>
<method name="swapBrowsersAndCloseOther">
<parameter name="aOurTab"/>
<parameter name="aOtherTab"/>
@ -1827,29 +1854,10 @@
if (!remoteBrowser._beginRemoveTab(aOtherTab, true, true))
return;
// Unhook our progress listener
var ourIndex = aOurTab._tPos;
const filter = this.mTabFilters[ourIndex];
var tabListener = this.mTabListeners[ourIndex];
var ourBrowser = this.getBrowserForTab(aOurTab);
ourBrowser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(tabListener);
var tabListenerBlank = tabListener.mBlank;
var otherBrowser = aOtherTab.linkedBrowser;
// Restore current registered open URI.
if (ourBrowser.registeredOpenURI) {
this._placesAutocomplete.unregisterOpenPage(ourBrowser.registeredOpenURI);
delete ourBrowser.registeredOpenURI;
}
if (otherBrowser.registeredOpenURI) {
ourBrowser.registeredOpenURI = otherBrowser.registeredOpenURI;
delete otherBrowser.registeredOpenURI;
}
// Workarounds for bug 458697
// Icon might have been set on DOMLinkAdded, don't override that.
let ourBrowser = this.getBrowserForTab(aOurTab);
let otherBrowser = aOtherTab.linkedBrowser;
if (!ourBrowser.mIconURL && otherBrowser.mIconURL)
this.setIcon(aOurTab, otherBrowser.mIconURL);
var isBusy = aOtherTab.hasAttribute("busy");
@ -1860,22 +1868,11 @@
this.mIsBusy = true;
}
// Swap the docshells
ourBrowser.swapDocShells(otherBrowser);
this._swapBrowserDocShells(aOurTab, otherBrowser);
// Finish tearing down the tab that's going away.
remoteBrowser._endRemoveTab(aOtherTab);
// Restore the progress listener
tabListener = this.mTabProgressListener(aOurTab, ourBrowser,
tabListenerBlank);
this.mTabListeners[ourIndex] = tabListener;
filter.addProgressListener(tabListener,
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
ourBrowser.webProgress.addProgressListener(filter,
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
if (isBusy)
this.setTabTitleLoading(aOurTab);
else
@ -1889,6 +1886,43 @@
</body>
</method>
<method name="_swapBrowserDocShells">
<parameter name="aOurTab"/>
<parameter name="aOtherBrowser"/>
<body>
<![CDATA[
// Unhook our progress listener
let index = aOurTab._tPos;
const filter = this.mTabFilters[index];
let tabListener = this.mTabListeners[index];
let ourBrowser = this.getBrowserForTab(aOurTab);
ourBrowser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(tabListener);
// Restore current registered open URI.
if (ourBrowser.registeredOpenURI) {
this._placesAutocomplete.unregisterOpenPage(ourBrowser.registeredOpenURI);
delete ourBrowser.registeredOpenURI;
}
if (aOtherBrowser.registeredOpenURI) {
ourBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
delete aOtherBrowser.registeredOpenURI;
}
// Swap the docshells
ourBrowser.swapDocShells(aOtherBrowser);
// Restore the progress listener
this.mTabListeners[index] = tabListener =
this.mTabProgressListener(aOurTab, ourBrowser, false);
const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
filter.addProgressListener(tabListener, notifyAll);
ourBrowser.webProgress.addProgressListener(filter, notifyAll);
]]>
</body>
</method>
<method name="reloadAllTabs">
<body>
<![CDATA[

View File

@ -0,0 +1,160 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let EXPORTED_SYMBOLS = ["BrowserNewTabPreloader"];
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
const PREF_NEWTAB_URL = "browser.newtab.url";
const PREF_NEWTAB_PRELOAD = "browser.newtab.preload";
function BrowserNewTabPreloader() {
}
BrowserNewTabPreloader.prototype = {
_url: null,
_window: null,
_browser: null,
_enabled: null,
init: function Preloader_init(aWindow) {
if (this._window) {
return;
}
this._window = aWindow;
this._enabled = Preferences.enabled;
this._url = Preferences.url;
Preferences.addObserver(this);
if (this._enabled) {
this._createBrowser();
}
},
uninit: function Preloader_uninit() {
if (!this._window) {
return;
}
if (this._browser) {
this._browser.parentNode.removeChild(this._browser);
this._browser = null;
}
this._window = null;
Preferences.removeObserver(this);
},
newTab: function Preloader_newTab(aTab) {
if (!this._window || !this._enabled) {
return;
}
let tabbrowser = this._window.gBrowser;
if (tabbrowser && this._isPreloaded()) {
tabbrowser.swapNewTabWithBrowser(aTab, this._browser);
}
},
observe: function Preloader_observe(aEnabled, aURL) {
if (this._url != aURL) {
this._url = aURL;
if (this._enabled && aEnabled) {
// We're still enabled but the newtab URL has changed.
this._browser.setAttribute("src", aURL);
return;
}
}
if (this._enabled && !aEnabled) {
// We got disabled. Remove the browser.
this._browser.parentNode.removeChild(this._browser);
this._browser = null;
this._enabled = false;
} else if (!this._enabled && aEnabled) {
// We got enabled. Create a browser and start preloading.
this._createBrowser();
this._enabled = true;
}
},
_createBrowser: function Preloader_createBrowser() {
let document = this._window.document;
this._browser = document.createElement("browser");
this._browser.setAttribute("type", "content");
this._browser.setAttribute("src", this._url);
this._browser.collapsed = true;
let panel = document.getElementById("browser-panel");
panel.appendChild(this._browser);
},
_isPreloaded: function Preloader_isPreloaded() {
return this._browser &&
this._browser.contentDocument &&
this._browser.contentDocument.readyState == "complete" &&
this._browser.currentURI.spec == this._url;
}
};
let Preferences = {
_observers: [],
get _branch() {
delete this._branch;
return this._branch = Services.prefs.getBranch("browser.newtab.");
},
get enabled() {
if (!this._branch.getBoolPref("preload")) {
return false;
}
if (this._branch.prefHasUserValue("url")) {
return false;
}
let url = this.url;
return url && url != "about:blank";
},
get url() {
return this._branch.getCharPref("url");
},
addObserver: function Preferences_addObserver(aObserver) {
let index = this._observers.indexOf(aObserver);
if (index == -1) {
if (this._observers.length == 0) {
this._branch.addObserver("", this, false);
}
this._observers.push(aObserver);
}
},
removeObserver: function Preferences_removeObserver(aObserver) {
let index = this._observers.indexOf(aObserver);
if (index > -1) {
if (this._observers.length == 1) {
this._branch.removeObserver("", this);
}
this._observers.splice(index, 1);
}
},
observe: function Preferences_observe(aSubject, aTopic, aData) {
let url = this.url;
let enabled = this.enabled;
for (let obs of this._observers) {
obs.observe(enabled, url);
}
}
};

View File

@ -14,6 +14,7 @@ include $(topsrcdir)/config/config.mk
TEST_DIRS += test
EXTRA_JS_MODULES = \
BrowserNewTabPreloader.jsm \
openLocationLastURL.jsm \
NetworkPrioritizer.jsm \
NewTabUtils.jsm \