Bug 975098 - Checks for stopping a plugin should consider that we might be nested inside InstantiatePluginInstance. r=bsmedberg
authorJohn Schoenick <jschoenick@mozilla.com>
Thu, 20 Feb 2014 13:34:06 -0800
changeset 173207 25de9f31826128f85ebd541e25ecefef4f1a5e77
parent 173206 e8036c3e0a7b242a3dbaa51d9308973635d83a2a
child 173208 65d3cda9a1a95f9587f41a4c0803ee3c6c1c665c
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbsmedberg
bugs975098
milestone30.0a1
Bug 975098 - Checks for stopping a plugin should consider that we might be nested inside InstantiatePluginInstance. r=bsmedberg
content/base/src/nsObjectLoadingContent.cpp
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -698,17 +698,17 @@ nsObjectLoadingContent::UnbindFromTree(b
   nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
 
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
   MOZ_ASSERT(thisContent);
   nsIDocument* ownerDoc = thisContent->OwnerDoc();
   ownerDoc->RemovePlugin(this);
 
-  if (mType == eType_Plugin && mInstanceOwner) {
+  if (mType == eType_Plugin && (mInstanceOwner || mInstantiating)) {
     // we'll let the plugin continue to run at least until we get back to
     // the event loop. If we get back to the event loop and the node
     // has still not been added back to the document then we tear down the
     // plugin
     QueueCheckPluginStopEvent();
   } else if (mType != eType_Image) {
     // nsImageLoadingContent handles the image case.
     // Reset state and clear pending events
@@ -739,17 +739,17 @@ nsObjectLoadingContent::nsObjectLoadingC
 nsObjectLoadingContent::~nsObjectLoadingContent()
 {
   // Should have been unbound from the tree at this point, and
   // CheckPluginStopEvent keeps us alive
   if (mFrameLoader) {
     NS_NOTREACHED("Should not be tearing down frame loaders at this point");
     mFrameLoader->Destroy();
   }
-  if (mInstanceOwner) {
+  if (mInstanceOwner || mInstantiating) {
     // This is especially bad as delayed stop will try to hold on to this
     // object...
     NS_NOTREACHED("Should not be tearing down a plugin at this point!");
     StopPluginInstance();
   }
   DestroyImageLoadingContent();
 }
 
@@ -904,17 +904,17 @@ nsObjectLoadingContent::InstantiatePlugi
 void
 nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged()
 {
   // XXX(johns): We cannot touch plugins or run arbitrary script from this call,
   //             as nsDocument is in a non-reentrant state.
 
   // If we have a plugin we want to queue an event to stop it unless we are
   // moved into an active document before returning to the event loop.
-  if (mInstanceOwner)
+  if (mInstanceOwner || mInstantiating)
     QueueCheckPluginStopEvent();
 }
 
 // nsIRequestObserver
 NS_IMETHODIMP
 nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
                                        nsISupports *aContext)
 {
@@ -1068,18 +1068,20 @@ nsObjectLoadingContent::HasNewFrame(nsIO
   if (mType != eType_Plugin) {
     return NS_OK;
   }
 
   if (!aFrame) {
     // Lost our frame. If we aren't going to be getting a new frame, e.g. we've
     // become display:none, we'll want to stop the plugin. Queue a
     // CheckPluginStopEvent
-    if (mInstanceOwner) {
-      mInstanceOwner->SetFrame(nullptr);
+    if (mInstanceOwner || mInstantiating) {
+      if (mInstanceOwner) {
+        mInstanceOwner->SetFrame(nullptr);
+      }
       QueueCheckPluginStopEvent();
     }
     return NS_OK;
   }
 
   // Have a new frame
 
   if (!mInstanceOwner) {
@@ -2821,16 +2823,20 @@ nsObjectLoadingContent::DoStopPlugin(nsP
 
 NS_IMETHODIMP
 nsObjectLoadingContent::StopPluginInstance()
 {
   // Clear any pending events
   mPendingInstantiateEvent = nullptr;
   mPendingCheckPluginStopEvent = nullptr;
 
+  // If we're currently instantiating, clearing this will cause
+  // InstantiatePluginInstance's re-entrance check to destroy the created plugin
+  mInstantiating = false;
+
   if (!mInstanceOwner) {
     return NS_OK;
   }
 
   if (mChannel) {
     // The plugin has already used data from this channel, we'll need to
     // re-open it to handle instantiating again, even if we don't invalidate
     // our loaded state.