Bug 458100. Make sure that we'll also instantiate the plug-in even if the nsPluginDocument has no presshell yet at OnStartRequest time. Thanks to Evgeny <evg.salmin@gmail.com> for pointing out the problem. r+sr=jst
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 07 Oct 2008 14:53:23 -0400
changeset 20110 9395c3a493b2136290adbd9bd7132f7662a93774
parent 20109 97d43a4491acb065ec7e7659198c9053946e4caf
child 20111 3132bea80ac95b06eba915dcd6ba70e1bbade582
push idunknown
push userunknown
push dateunknown
bugs458100
milestone1.9.1b2pre
Bug 458100. Make sure that we'll also instantiate the plug-in even if the nsPluginDocument has no presshell yet at OnStartRequest time. Thanks to Evgeny <evg.salmin@gmail.com> for pointing out the problem. r+sr=jst
content/base/src/nsObjectLoadingContent.cpp
content/html/document/src/nsPluginDocument.cpp
layout/generic/nsObjectFrame.cpp
modules/plugin/base/public/nsIPluginDocument.idl
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -793,17 +793,21 @@ nsObjectLoadingContent::HasNewFrame(nsIO
     // This can go away once plugin loading moves to content
     // This must be done asynchronously to ensure that the frame is correctly
     // initialized (has a view etc)
 
     // When in a plugin document, the document will take care of calling
     // instantiate
     nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(GetOurDocument()));
     if (pDoc) {
-      return NS_OK;
+      PRBool willHandleInstantiation;
+      pDoc->GetWillHandleInstantiation(&willHandleInstantiation);
+      if (willHandleInstantiation) {
+        return NS_OK;
+      }
     }
 
     nsCOMPtr<nsIRunnable> event =
         new nsAsyncInstantiateEvent(this, aFrame, mContentType, mURI);
     if (!event) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
--- a/content/html/document/src/nsPluginDocument.cpp
+++ b/content/html/document/src/nsPluginDocument.cpp
@@ -66,22 +66,31 @@ public:
                                      nsIContentSink*     aSink = nsnull);
 
   virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
   virtual PRBool CanSavePresentation(nsIRequest *aNewRequest);
 
   const nsCString& GetType() const { return mMimeType; }
   nsIContent*      GetPluginContent() { return mPluginContent; }
 
+  void SkippedInstantiation() {
+    mWillHandleInstantiation = PR_FALSE;
+  }
+
 protected:
   nsresult CreateSyntheticPluginDocument();
 
   nsCOMPtr<nsIContent>                     mPluginContent;
   nsRefPtr<nsMediaDocumentStreamListener>  mStreamListener;
   nsCString                                mMimeType;
+
+  // Hack to handle the fact that plug-in loading lives in frames and that the
+  // frames may not be around when we need to instantiate.  Once plug-in
+  // loading moves to content, this can all go away.
+  PRBool                                   mWillHandleInstantiation;
 };
 
 class nsPluginStreamListener : public nsMediaDocumentStreamListener
 {
   public:
     nsPluginStreamListener(nsPluginDocument* doc) :
        nsMediaDocumentStreamListener(doc),  mPluginDoc(doc) {}
     NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt);
@@ -99,32 +108,35 @@ nsPluginStreamListener::OnStartRequest(n
   }
 
   nsCOMPtr<nsIContent> embed = mPluginDoc->GetPluginContent();
 
   // Now we have a frame for our <embed>, start the load
   nsIPresShell* shell = mDocument->GetPrimaryShell();
   if (!shell) {
     // Can't instantiate w/o a shell
+    mPluginDoc->SkippedInstantiation();
     return NS_BINDING_ABORTED;
   }
 
   // Flush out layout before we go to instantiate, because some
   // plug-ins depend on NPP_SetWindow() being called early enough and
   // nsObjectFrame does that at the end of reflow.
   shell->FlushPendingNotifications(Flush_Layout);
 
   nsIFrame* frame = shell->GetPrimaryFrameFor(embed);
   if (!frame) {
+    mPluginDoc->SkippedInstantiation();
     return rv;
   }
 
   nsIObjectFrame* objFrame;
   CallQueryInterface(frame, &objFrame);
   if (!objFrame) {
+    mPluginDoc->SkippedInstantiation();
     return NS_ERROR_UNEXPECTED;
   }
 
   rv = objFrame->Instantiate(mPluginDoc->GetType().get(),
                              mDocument->nsIDocument::GetDocumentURI());
   if (NS_FAILED(rv)) {
     return rv;
   }
@@ -133,16 +145,17 @@ nsPluginStreamListener::OnStartRequest(n
   return mNextStream->OnStartRequest(request, ctxt);
 }
 
 
   // NOTE! nsDocument::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
 nsPluginDocument::nsPluginDocument()
+  : mWillHandleInstantiation(PR_TRUE)
 {
 }
 
 nsPluginDocument::~nsPluginDocument()
 {
 }
 
 // XXXbz shouldn't this participate in cycle collection?  It's got
@@ -318,16 +331,23 @@ nsPluginDocument::Print()
 
       pi->Print(&npprint);
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsPluginDocument::GetWillHandleInstantiation(PRBool* aWillHandle)
+{
+  *aWillHandle = mWillHandleInstantiation;
+  return NS_OK;
+}
+
 nsresult
 NS_NewPluginDocument(nsIDocument** aResult)
 {
   nsPluginDocument* doc = new nsPluginDocument();
   if (!doc) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -873,19 +873,23 @@ nsObjectFrame::InstantiatePlugin(nsIPlug
   if (appShell) {
     appShell->SuspendNative();
   }
 
   NS_ASSERTION(mContent, "We should have a content node.");
 
   nsIDocument* doc = mContent->GetOwnerDoc();
   nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc));
+  PRBool fullPageMode = PR_FALSE;
+  if (pDoc) {
+    pDoc->GetWillHandleInstantiation(&fullPageMode);
+  }
 
   nsresult rv;
-  if (pDoc) {  /* full-page mode */
+  if (fullPageMode) {  /* full-page mode */
     nsCOMPtr<nsIStreamListener> stream;
     rv = aPluginHost->InstantiateFullPagePlugin(aMimeType, aURI,
           /* resulting stream listener */       *getter_AddRefs(stream),
                                                 mInstanceOwner);
     if (NS_SUCCEEDED(rv))
       pDoc->SetStreamListener(stream);
   } else {   /* embedded mode */
     rv = aPluginHost->InstantiateEmbeddedPlugin(aMimeType, aURI,
--- a/modules/plugin/base/public/nsIPluginDocument.idl
+++ b/modules/plugin/base/public/nsIPluginDocument.idl
@@ -33,22 +33,29 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsIStreamListener.idl"
 
-[uuid(0d8129f1-5a55-4eaa-851f-15e43ce3d183)]
+[uuid(e4be1d0a-9f24-4d69-bec5-245726ab85fb)]
 interface nsIPluginDocument : nsISupports
 {
  /**
   * Sets the stream listener for this plugin document 
   */
   void setStreamListener(in nsIStreamListener aStreamListener);
 
   
  /**
   * Causes the plugin to print in full-page mode
   */
   void print();
+
+  /**
+   * Check whether the document is planning to handle plug-in instantiation
+   * itself.  If not, then the plugin content node should do it.
+   */
+  // XXXbz once we move plug-in loading to content, this can go away.
+  readonly attribute boolean willHandleInstantiation;
 };