Bug 1331402 - Update plugins' clipRects when hiding a tab. r?jimm, r?mattwoodrow draft
authorMarkus Stange <mstange@themasta.com>
Tue, 17 Jan 2017 18:07:05 +0100
changeset 462519 d71c022e2449bead7fde714c91cbee2f5e17bc37
parent 462518 954280201b3b1164601444dd3f7a05074bb8a14f
child 542430 b1c31ee8eb6235c0a2d4d9aca297911fdd3e9580
push id41790
push userbmo:mstange@themasta.com
push dateTue, 17 Jan 2017 17:08:13 +0000
reviewersjimm, mattwoodrow
bugs1331402
milestone53.0a1
Bug 1331402 - Update plugins' clipRects when hiding a tab. r?jimm, r?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
@@ -2660,16 +2660,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