Bug 1432509 - Allow async tab switcher to load requested tabs that are still warming. r?Gijs draft
authorMike Conley <mconley@mozilla.com>
Mon, 26 Feb 2018 17:23:57 -0500
changeset 760161 6d758b34ad0fab939147952501b3936a426e38b8
parent 759663 02aa9c921aedfd0e768a92a6a8c5cba1b14191c1
push id100559
push usermconley@mozilla.com
push dateMon, 26 Feb 2018 22:52:11 +0000
reviewersGijs
bugs1432509
milestone60.0a1
Bug 1432509 - Allow async tab switcher to load requested tabs that are still warming. r?Gijs This patch makes the following changes: 1. When layers are ready for a tab, we remove it from the warming list. We used to do this once a tab was requested, but it actually makes more sense to keep the "warming" state for the tab around until the layers have arrived. 2. In postActions, when choosing which tab to try to load layers for next, allow for the possibility that the requested tab is being warmed (and therefore in STATE_LOADING). If the tab is warming, loadRequestedTab won't re-request layers, but will at least create the loadTimer which is necessary so that updateDisplay knows that we're _trying_ to load the warmed tab, and that we should at least wait for the loadTimer to finish before showing the tab switch spinner. MozReview-Commit-ID: WdYRTdzAoz
browser/base/content/tabbrowser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4405,43 +4405,53 @@
             },
 
             clearTimer(timer) {
               timer.cancel();
             },
 
             getTabState(tab) {
               let state = this.tabState.get(tab);
+
+              // As an optimization, we lazily evaluate the state of tabs
+              // that we've never seen before. Once we've figured it out,
+              // we stash it in our state map.
               if (state === undefined) {
                 state = this.STATE_UNLOADED;
 
                 if (tab && tab.linkedPanel) {
                   let b = tab.linkedBrowser;
                   if (b.renderLayers && b.hasLayers) {
                     state = this.STATE_LOADED;
                   } else if (b.renderLayers && !b.hasLayers) {
                     state = this.STATE_LOADING;
                   } else if (!b.renderLayers && b.hasLayers) {
                     state = this.STATE_UNLOADING;
                   }
                 }
+
+                this.setTabStateNoAction(tab, state);
               }
 
               return state;
             },
 
             setTabStateNoAction(tab, state) {
               if (state == this.STATE_UNLOADED) {
                 this.tabState.delete(tab);
               } else {
                 this.tabState.set(tab, state);
               }
             },
 
             setTabState(tab, state) {
+              if (state == this.getTabState(tab)) {
+                return;
+              }
+
               this.setTabStateNoAction(tab, state);
 
               let browser = tab.linkedBrowser;
               let {tabParent} = browser.frameLoader;
               if (state == this.STATE_LOADING) {
                 this.assert(!this.minimizedOrFullyOccluded);
 
                 if (!this.tabbrowser.tabWarmingEnabled) {
@@ -4805,20 +4815,22 @@
                 this.loadingTab = null;
                 if (this.loadTimer) {
                   this.clearTimer(this.loadTimer);
                   this.loadTimer = null;
                 }
               }
 
               // If we're not loading anything, try loading the requested tab.
-              let requestedState = this.getTabState(this.requestedTab);
+              let stateOfRequestedTab = this.getTabState(this.requestedTab);
               if (!this.loadTimer && !this.minimizedOrFullyOccluded &&
-                  (requestedState == this.STATE_UNLOADED ||
-                   requestedState == this.STATE_UNLOADING)) {
+                  (stateOfRequestedTab == this.STATE_UNLOADED ||
+                   stateOfRequestedTab == this.STATE_UNLOADING ||
+                   this.warmingTabs.has(this.requestedTab))) {
+                this.assert(stateOfRequestedTab != this.STATE_LOADED);
                 this.loadRequestedTab();
               }
 
               // See how many tabs still have work to do.
               let numPending = 0;
               let numWarming = 0;
               for (let [tab, state] of this.tabState) {
                 // Skip print preview browsers since they shouldn't affect tab switching.
@@ -4927,16 +4939,17 @@
                 return;
               }
 
               this.logState(`onLayersReady(${tab._tPos}, ${browser.isRemoteBrowser})`);
 
               this.assert(this.getTabState(tab) == this.STATE_LOADING ||
                           this.getTabState(tab) == this.STATE_LOADED);
               this.setTabState(tab, this.STATE_LOADED);
+              this.unwarmTab(tab);
 
               if (this.loadingTab === tab) {
                 this.clearTimer(this.loadTimer);
                 this.loadTimer = null;
                 this.loadingTab = null;
               }
             },
 
@@ -5148,18 +5161,16 @@
                   }
                 } else if (this.canWarmTab(tab)) {
                   warmingState = "notWarmed";
                 }
 
                 Services.telemetry
                         .getHistogramById("FX_TAB_SWITCH_REQUEST_TAB_WARMING_STATE")
                         .add(warmingState);
-
-                this.unwarmTab(tab);
               }
 
               this._requestingTab = true;
               this.logState("requestTab " + this.tinfo(tab));
               this.startTabSwitch();
 
               this.requestedTab = tab;