Bug 1331402 - Update plugins' clipRects when hiding a tab. r=jimm,mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Tue, 17 Jan 2017 18:07:05 +0100
changeset 375019 6587e676b76d68462cacdb567e4c39fff1057194
parent 375018 60dcbc3c90267f6bd083c6a43be48a744d103b2c
child 375020 b69accee20b4a38ba050768729f86f8d21ee0d3f
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, mattwoodrow
bugs1331402
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1331402 - Update plugins' clipRects when hiding a tab. r=jimm,mattwoodrow In non-e10s, all tabs of a window would share one nsRootPresContext. When switching tabs, the tab switch paint would trigger a call to nsRootPresContext::ComputePluginGeometryUpdates, which would call SetEmptyWidgetConfiguration on all registered nsPluginFrames, notably also those inside the tab that was hidden. With e10s, every tab has its own nsRootPresContext, and paints in one tab do not trigger calls to nsRootPresContext::ComputePluginGeometryUpdates on the root pres contexts of other tabs. So when painting the new tab, the registered plugin frames in the old tab were not notified that they were now hidden. This patch now does that in TabChild::MakeHidden. MozReview-Commit-ID: LlW9dKKFqZE
dom/ipc/TabChild.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2725,16 +2725,26 @@ TabChild::MakeHidden()
   }
 
   CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
 
   // Clear cached resources directly. This avoids one extra IPC
   // round-trip from CompositorBridgeChild to CompositorBridgeParent.
   compositor->RecvClearCachedResources(mLayersId);
 
+  // Hide all plugins in this tab.
+  if (nsCOMPtr<nsIPresShell> shell = GetPresShell()) {
+    if (nsPresContext* presContext = shell->GetPresContext()) {
+      nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
+      nsIFrame* rootFrame = shell->FrameConstructor()->GetRootFrame();
+      rootPresContext->ComputePluginGeometryUpdates(rootFrame, nullptr, nullptr);
+      rootPresContext->ApplyPluginGeometryUpdates();
+    }
+  }
+
   if (mPuppetWidget) {
     mPuppetWidget->Show(false);
   }
 }
 
 NS_IMETHODIMP
 TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
 {
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2958,29 +2958,32 @@ nsRootPresContext::ComputePluginGeometry
     }
     if (!nsLayoutUtils::IsAncestorFrameCrossDoc(aFrame, f)) {
       // f is not managed by this frame so we should ignore it.
       continue;
     }
     f->SetEmptyWidgetConfiguration();
   }
 
-  nsIFrame* rootFrame = FrameManager()->GetRootFrame();
-
-  if (rootFrame && aBuilder->ContainsPluginItem()) {
-    aBuilder->SetForPluginGeometry();
-    aBuilder->SetAccurateVisibleRegions();
-    // Merging and flattening has already been done and we should not do it
-    // again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
-    // again.
-    aBuilder->SetAllowMergingAndFlattening(false);
-    nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
-    // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
-    // widget configuration for the plugin, if it's visible.
-    aList->ComputeVisibilityForRoot(aBuilder, &region);
+  if (aBuilder) {
+    MOZ_ASSERT(aList);
+    nsIFrame* rootFrame = FrameManager()->GetRootFrame();
+
+    if (rootFrame && aBuilder->ContainsPluginItem()) {
+      aBuilder->SetForPluginGeometry();
+      aBuilder->SetAccurateVisibleRegions();
+      // Merging and flattening has already been done and we should not do it
+      // again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
+      // again.
+      aBuilder->SetAllowMergingAndFlattening(false);
+      nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
+      // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
+      // widget configuration for the plugin, if it's visible.
+      aList->ComputeVisibilityForRoot(aBuilder, &region);
+    }
   }
 
 #ifdef XP_MACOSX
   // We control painting of Mac plugins, so just apply geometry updates now.
   // This is not happening during a paint event.
   ApplyPluginGeometryUpdates();
 #else
   if (XRE_IsParentProcess()) {
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1519,16 +1519,18 @@ public:
   /**
    * Compute geometry updates for each plugin given that aList is the display
    * list for aFrame. The updates are not yet applied;
    * ApplyPluginGeometryUpdates is responsible for that. In the meantime they
    * are stored on each nsPluginFrame.
    * This needs to be called even when aFrame is a popup, since although
    * windowed plugins aren't allowed in popups, windowless plugins are
    * and ComputePluginGeometryUpdates needs to be called for them.
+   * aBuilder and aList can be null. This indicates that all plugins are
+   * hidden because we're in a background tab.
    */
   void ComputePluginGeometryUpdates(nsIFrame* aFrame,
                                     nsDisplayListBuilder* aBuilder,
                                     nsDisplayList* aList);
 
   /**
    * Apply the stored plugin geometry updates. This should normally be called
    * in DidPaint so the plugins are moved/clipped immediately after we've