Bug 1397426 - TabChild::MakeHidden shouldn't cause script to run. r=billm draft
authorMike Conley <mconley@mozilla.com>
Tue, 21 Nov 2017 16:52:48 -0500
changeset 715464 1c4b1ad28467fc6960eaa7cb744e47dd191b30f5
parent 715463 4ca9f692635e3a3a1ec8e626d0db24f2e512ec9a
child 715465 f1faa794791a9c620a1cd7a28c67029134d63933
push id94165
push usermconley@mozilla.com
push dateWed, 03 Jan 2018 23:25:52 +0000
reviewersbillm
bugs1397426
milestone59.0a1
Bug 1397426 - TabChild::MakeHidden shouldn't cause script to run. r=billm Calling GetPresShell() might create a content viewer, which might cause script to run. This is bad if there's a ForcePaint message queued up, because it could mean running the force painting code while we're still in the midst of making a tab hidden, which would put us in an inconsistent state. MozReview-Commit-ID: 3rw2wGllGdk
dom/ipc/TabChild.cpp
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3057,25 +3057,31 @@ TabChild::MakeHidden()
   // it's possible to be told to become hidden before we're finished
   // setting up a layer manager. We should skip clearing cached layers
   // in that case, since doing so might accidentally put is into
   // BasicLayers mode.
   if (mPuppetWidget && mPuppetWidget->HasLayerManager()) {
     ClearCachedResources();
   }
 
-  // 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();
+  nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
+  if (docShell) {
+    // Hide all plugins in this tab. We don't use TabChildBase::GetPresShell()
+    // here because that would create a content viewer if one doesn't exist yet.
+    // Creating a content viewer can cause JS to run, which we want to avoid.
+    // nsIDocShell::GetPresShell returns null if no content viewer exists yet.
+    if (nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell()) {
+      if (nsPresContext* presContext = presShell->GetPresContext()) {
+        nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
+        nsIFrame* rootFrame = presShell->FrameConstructor()->GetRootFrame();
+        rootPresContext->ComputePluginGeometryUpdates(rootFrame, nullptr, nullptr);
+        rootPresContext->ApplyPluginGeometryUpdates();
+      }
+      presShell->SetIsActive(false);
     }
-    shell->SetIsActive(false);
   }
 
   if (mPuppetWidget) {
     mPuppetWidget->Show(false);
   }
 }
 
 bool