Bug 874533 - Part 1: Speculative connect when users hover mouse on a tab or when restoring tabs automatically. r?mikedeboer draft
authorBeekill95 <nnn_bikiu0707@yahoo.com>
Fri, 23 Jun 2017 10:27:32 +0700
changeset 610984 46c45d83bd2ce05eecdeb64949751c52e3270630
parent 609403 13a2e506992ccf07c1358d9f22cbf2dfdcb0120f
child 610985 6902c3a6f947171b5b9f518d5703aaba1796c41a
push id69076
push userbmo:nnn_bikiu0707@yahoo.com
push dateWed, 19 Jul 2017 01:48:52 +0000
reviewersmikedeboer
bugs874533
milestone56.0a1
Bug 874533 - Part 1: Speculative connect when users hover mouse on a tab or when restoring tabs automatically. r?mikedeboer MozReview-Commit-ID: aJUyM4z3Nh
browser/components/sessionstore/SessionStore.jsm
--- 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";