Bug 1397426 - Expose renderLayers state via nsITabParent and lazily retrieve initial tab states in async tab switcher. r=billm draft
authorMike Conley <mconley@mozilla.com>
Tue, 19 Dec 2017 08:44:18 -0800
changeset 715465 f1faa794791a9c620a1cd7a28c67029134d63933
parent 715464 1c4b1ad28467fc6960eaa7cb744e47dd191b30f5
child 715466 76f2d740838d2666c2de66f3f0687a66b28f9dab
push id94165
push usermconley@mozilla.com
push dateWed, 03 Jan 2018 23:25:52 +0000
reviewersbillm
bugs1397426
milestone59.0a1
Bug 1397426 - Expose renderLayers state via nsITabParent and lazily retrieve initial tab states in async tab switcher. r=billm MozReview-Commit-ID: IIMmwrgJUV6
browser/base/content/tabbrowser.xml
dom/interfaces/base/nsITabParent.idl
dom/ipc/TabParent.cpp
toolkit/content/widgets/browser.xml
toolkit/content/widgets/remote-browser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4372,18 +4372,30 @@
 
             clearTimer(timer) {
               timer.cancel();
             },
 
             getTabState(tab) {
               let state = this.tabState.get(tab);
               if (state === undefined) {
-                return this.STATE_UNLOADED;
-              }
+                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;
+                  }
+                }
+              }
+
               return state;
             },
 
             setTabStateNoAction(tab, state) {
               if (state == this.STATE_UNLOADED) {
                 this.tabState.delete(tab);
               } else {
                 this.tabState.set(tab, state);
@@ -4398,17 +4410,17 @@
               if (state == this.STATE_LOADING) {
                 this.assert(!this.minimizedOrFullyOccluded);
 
                 if (!this.tabbrowser.tabWarmingEnabled) {
                   browser.docShellIsActive = true;
                 }
 
                 if (tabParent) {
-                  tabParent.renderLayers(true);
+                  browser.renderLayers = true;
                 } else {
                   this.onLayersReady(browser);
                 }
               } else if (state == this.STATE_UNLOADING) {
                 this.unwarmTab(tab);
                 // Setting the docShell to be inactive will also cause it
                 // to stop rendering layers.
                 browser.docShellIsActive = false;
@@ -4436,39 +4448,42 @@
             get minimizedOrFullyOccluded() {
               return window.windowState == window.STATE_MINIMIZED ||
                      window.isFullyOccluded;
             },
 
             init() {
               this.log("START");
 
-              // If we minimized the window before the switcher was activated,
-              // we might have set  the preserveLayers flag for the current
-              // browser. Let's clear it.
-              this.tabbrowser.mCurrentBrowser.preserveLayers(false);
-
               window.addEventListener("MozAfterPaint", this);
               window.addEventListener("MozLayerTreeReady", this);
               window.addEventListener("MozLayerTreeCleared", this);
               window.addEventListener("TabRemotenessChange", this);
               window.addEventListener("sizemodechange", this);
               window.addEventListener("occlusionstatechange", this);
               window.addEventListener("SwapDocShells", this, true);
               window.addEventListener("EndSwapDocShells", this, true);
 
-              let tab = this.requestedTab;
-              let browser = tab.linkedBrowser;
-              let tabIsLoaded = browser.renderingLayers;
+              let initialTab = this.requestedTab;
+              let initialBrowser = initialTab.linkedBrowser;
+
+              let tabIsLoaded = !initialBrowser.isRemoteBrowser ||
+                                initialBrowser.frameLoader.tabParent.hasLayers;
+
+              // If we minimized the window before the switcher was activated,
+              // we might have set  the preserveLayers flag for the current
+              // browser. Let's clear it.
+              initialBrowser.preserveLayers(false);
 
               if (!this.minimizedOrFullyOccluded) {
                 this.log("Initial tab is loaded?: " + tabIsLoaded);
-                this.setTabState(tab, tabIsLoaded ? this.STATE_LOADED
-                                                  : this.STATE_LOADING);
-              }
+                this.setTabState(initialTab, tabIsLoaded ? this.STATE_LOADED
+                                                         : this.STATE_LOADING);
+              }
+
               for (let ppBrowser of this.tabbrowser._printPreviewBrowsers) {
                 let ppTab = this.tabbrowser.getTabForBrowser(ppBrowser);
                 let state = ppBrowser.hasLayers ? this.STATE_LOADED
                                                 : this.STATE_LOADING;
                 this.setTabState(ppTab, state);
               }
             },
 
--- a/dom/interfaces/base/nsITabParent.idl
+++ b/dom/interfaces/base/nsITabParent.idl
@@ -20,22 +20,21 @@ interface nsITabParent : nsISupports
    * Manages the docshell active state of the remote browser. Setting the
    * docShell to be active will also cause it to render layers and upload
    * them to the compositor. Setting the docShell as not active will clear
    * those layers.
    */
   attribute boolean docShellIsActive;
 
   /**
-   * When aEnabled is set to true, this tells the child to paint and
-   * upload layers to the compositor. When aEnabled is set to false,
-   * previous layers are cleared from the compositor, but only if
-   * preserveLayers is also set to false.
+   * When set to true, this tells the child to paint and upload layers to
+   * the compositor. When set to false, previous layers are cleared from
+   * the compositor, but only if preserveLayers is also set to false.
    */
-  void renderLayers(in bool aEnabled);
+  attribute boolean renderLayers;
 
   /**
    * True if layers are being rendered and the compositor has reported
    * receiving them.
    */
   readonly attribute boolean hasLayers;
 
   /**
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2902,17 +2902,17 @@ TabParent::GetUseAsyncPanZoom(bool* useA
 
 // defined in nsITabParent
 NS_IMETHODIMP
 TabParent::SetDocShellIsActive(bool isActive)
 {
   // docshell is consider prerendered only if not active yet
   mIsPrerendered &= !isActive;
   mDocShellIsActive = isActive;
-  RenderLayers(isActive);
+  SetRenderLayers(isActive);
   Unused << SendSetDocShellIsActive(isActive);
 
   // update active accessible documents on windows
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   if (a11y::Compatibility::IsDolphin()) {
     if (a11y::DocAccessibleParent* tabDoc = GetTopLevelDocAccessible()) {
       HWND window = tabDoc->GetEmulatedWindowHandle();
       MOZ_ASSERT(window);
@@ -2944,17 +2944,17 @@ TabParent::GetDocShellIsActive(bool* aIs
 NS_IMETHODIMP
 TabParent::GetIsPrerendered(bool* aIsPrerendered)
 {
   *aIsPrerendered = mIsPrerendered;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TabParent::RenderLayers(bool aEnabled)
+TabParent::SetRenderLayers(bool aEnabled)
 {
   if (aEnabled == mRenderLayers) {
     if (aEnabled && mHasLayers && mPreserveLayers) {
       // RenderLayers might be called when we've been preserving layers,
       // and already had layers uploaded. In that case, the MozLayerTreeReady
       // event will not naturally arrive, which can confuse the front-end
       // layer. So we fire the event here.
       RefPtr<TabParent> self = this;
@@ -2990,16 +2990,23 @@ TabParent::RenderLayers(bool aEnabled)
     ContentParent* cp = Manager()->AsContentParent();
     cp->ForceTabPaint(this, mLayerTreeEpoch);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+TabParent::GetRenderLayers(bool* aResult)
+{
+  *aResult = mRenderLayers;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 TabParent::GetHasLayers(bool* aResult)
 {
   *aResult = mHasLayers;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabParent::PreserveLayers(bool aPreserveLayers)
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -299,16 +299,29 @@
 
       <method name="preserveLayers">
         <parameter name="preserve"/>
         <body>
           // Only useful for remote browsers.
         </body>
       </method>
 
+      <property name="renderLayers">
+        <getter>
+          <![CDATA[
+            return this.docShellIsActive;
+          ]]>
+        </getter>
+        <setter>
+          <![CDATA[
+            return this.docShellIsActive = val;
+          ]]>
+        </setter>
+      </property>
+
       <property name="hasLayers" readonly="true">
         <getter>
           <![CDATA[
             return this.docShellIsActive;
           ]]>
         </getter>
       </property>
 
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -255,16 +255,37 @@
         <body><![CDATA[
           let {frameLoader} = this;
           if (frameLoader.tabParent) {
             frameLoader.tabParent.preserveLayers(preserve);
           }
         ]]></body>
       </method>
 
+      <property name="renderLayers">
+        <getter>
+          <![CDATA[
+            let {frameLoader} = this;
+            if (frameLoader && frameLoader.tabParent) {
+              return frameLoader.tabParent.renderLayers;
+            }
+            return false;
+          ]]>
+        </getter>
+        <setter>
+          <![CDATA[
+            let {frameLoader} = this;
+            if (frameLoader && frameLoader.tabParent) {
+              return frameLoader.tabParent.renderLayers = val;
+            }
+            return false;
+          ]]>
+        </setter>
+      </property>
+
       <property name="hasLayers" readonly="true">
         <getter><![CDATA[
           let {frameLoader} = this;
           if (frameLoader.tabParent) {
             return frameLoader.tabParent.hasLayers;
           }
           return false;
         ]]></getter>