Bug 874533 - Part 1: Speculative connect when users hover mouse on a tab or when restoring tabs automatically. r?mikedeboer
MozReview-Commit-ID: aJUyM4z3Nh
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -3273,18 +3273,18 @@ var SessionStoreInternal = {
if (overwriteTabs) {
for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) {
if (!tabbrowser.tabs[i].selected) {
tabbrowser.removeTab(tabbrowser.tabs[i]);
}
}
}
- let restoreTabsLazily = this._prefBranch.getBoolPref("sessionstore.restore_tabs_lazily") &&
- this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
+ let restoreOnDemand = this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
+ let restoreTabsLazily = this._prefBranch.getBoolPref("sessionstore.restore_tabs_lazily") && restoreOnDemand;
for (var t = 0; t < newTabCount; t++) {
let tabData = winData.tabs[t];
let userContextId = tabData.userContextId;
let select = t == selectTab - 1;
let tab;
@@ -3327,16 +3327,23 @@ var SessionStoreInternal = {
userContextId,
skipBackgroundNotify: true });
if (select) {
let leftoverTab = tabbrowser.selectedTab;
tabbrowser.selectedTab = tab;
tabbrowser.removeTab(leftoverTab);
}
+
+ // Prepare connection to the host when users hover mouse over this
+ // tab. If we're not restoring on demand, we'll prepare connection
+ // when we're restoring next tab.
+ if (!tabData.pinned && restoreOnDemand) {
+ this.speculativeConnectOnTabHover(tab, url);
+ }
}
tabs.push(tab);
if (tabData.hidden) {
tabbrowser.hideTab(tab);
}
@@ -3412,16 +3419,52 @@ var SessionStoreInternal = {
this._sendWindowRestoredNotification(aWindow);
Services.obs.notifyObservers(aWindow, NOTIFY_SINGLE_WINDOW_RESTORED);
this._sendRestoreCompletedNotifications();
},
/**
+ * Prepare connection to host beforehand.
+ *
+ * @param url
+ * URL of a host.
+ * @returns a flag indicates whether a connection has been made
+ */
+ prepareConnectionToHost(url) {
+ if (!url.startsWith("about:")) {
+ let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
+ let uri = Services.io.newURI(url);
+ sc.speculativeConnect(uri, null, null);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Make a connection to a host when users hover mouse on a tab.
+ *
+ * @param tab
+ * A tab to set up a hover listener.
+ * @param url
+ * URL of a host.
+ */
+ speculativeConnectOnTabHover(tab, url) {
+ tab.addEventListener("mouseover", () => {
+ let prepared = this.prepareConnectionToHost(url);
+ // This is used to test if a connection has been made beforehand.
+ if (gDebuggingEnabled) {
+ tab.__test_connection_prepared = prepared;
+ tab.__test_connection_url = url;
+ }
+ }, {once: true});
+ },
+
+ /**
* Restore multiple windows using the provided state.
* @param aWindow
* Window reference to the first window to use for restoration.
* Additionally required windows will be opened.
* @param aState
* JS object or JSON string
* @param aOptions
* {overwriteTabs: true} to overwrite existing tabs w/ new ones
@@ -3677,16 +3720,29 @@ var SessionStoreInternal = {
this._sendRestoreHistory(browser, {tabData, epoch, loadArguments});
// This could cause us to ignore MAX_CONCURRENT_TAB_RESTORES a bit, but
// it ensures each window will have its selected tab loaded.
if (willRestoreImmediately) {
this.restoreTabContent(tab, options);
} else if (!forceOnDemand) {
TabRestoreQueue.add(tab);
+ // Check if a tab is in queue and will be restored
+ // after the currently loading tabs. If so, prepare
+ // a connection to host to speed up page loading.
+ if (TabRestoreQueue.willRestoreSoon(tab)) {
+ if (activeIndex in tabData.entries) {
+ let url = tabData.entries[activeIndex].url;
+ let prepared = this.prepareConnectionToHost(url);
+ if (gDebuggingEnabled) {
+ tab.__test_connection_prepared = prepared;
+ tab.__test_connection_url = url;
+ }
+ }
+ }
this.restoreNextTab();
}
} else {
// __SS_lazyData holds data for lazy-browser tabs to proxy for
// data unobtainable from the unbound browser. This only applies to lazy
// browsers and will be removed once the browser is inserted in the document.
// This must preceed `updateTabLabelAndIcon` call for required data to be present.
let url = "about:blank";