Bug 1136930 - Fix nsNPAPIPluginStreamListener so that destroystream calls are made during async plugin init. r=jimm, a=lsblakk
authorAaron Klotz <aklotz@mozilla.com>
Thu, 12 Mar 2015 11:45:31 -0600
changeset 248185 bf384c919c3342a7ae49fee94cb4ad216c61616b
parent 248184 9797a33e3b82d643a4db69b6f8b94c445f4c9ba7
child 248186 ead1bd9d09b0829e5a9fbc4bb626de66934b5349
push id7779
push userryanvm@gmail.com
push dateWed, 18 Mar 2015 16:52:00 +0000
treeherdermozilla-aurora@8a388fd12c53 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, lsblakk
bugs1136930
milestone38.0a2
Bug 1136930 - Fix nsNPAPIPluginStreamListener so that destroystream calls are made during async plugin init. r=jimm, a=lsblakk
dom/plugins/base/nsNPAPIPluginStreamListener.cpp
dom/plugins/base/nsNPAPIPluginStreamListener.h
--- a/dom/plugins/base/nsNPAPIPluginStreamListener.cpp
+++ b/dom/plugins/base/nsNPAPIPluginStreamListener.cpp
@@ -129,31 +129,31 @@ nsPluginStreamToFile::Close(void)
 // nsNPAPIPluginStreamListener Methods
 
 NS_IMPL_ISUPPORTS(nsNPAPIPluginStreamListener,
                   nsITimerCallback, nsIHTTPHeaderListener)
 
 nsNPAPIPluginStreamListener::nsNPAPIPluginStreamListener(nsNPAPIPluginInstance* inst, 
                                                          void* notifyData,
                                                          const char* aURL)
-: mStreamBuffer(nullptr),
-mNotifyURL(aURL ? PL_strdup(aURL) : nullptr),
-mInst(inst),
-mStreamBufferSize(0),
-mStreamBufferByteCount(0),
-mStreamType(NP_NORMAL),
-mStreamStarted(false),
-mStreamCleanedUp(false),
-mCallNotify(notifyData ? true : false),
-mIsSuspended(false),
-mIsPluginInitJSStream(mInst->mInPluginInitCall &&
-                      aURL && strncmp(aURL, "javascript:",
-                                      sizeof("javascript:") - 1) == 0),
-mRedirectDenied(false),
-mResponseHeaderBuf(nullptr)
+  : mStreamBuffer(nullptr)
+  , mNotifyURL(aURL ? PL_strdup(aURL) : nullptr)
+  , mInst(inst)
+  , mStreamBufferSize(0)
+  , mStreamBufferByteCount(0)
+  , mStreamType(NP_NORMAL)
+  , mStreamState(eStreamStopped)
+  , mStreamCleanedUp(false)
+  , mCallNotify(notifyData ? true : false)
+  , mIsSuspended(false)
+  , mIsPluginInitJSStream(mInst->mInPluginInitCall &&
+                          aURL && strncmp(aURL, "javascript:",
+                                          sizeof("javascript:") - 1) == 0)
+  , mRedirectDenied(false)
+  , mResponseHeaderBuf(nullptr)
 {
   mNPStreamWrapper = new nsNPAPIStreamWrapper(nullptr, this);
   mNPStreamWrapper->mNPStream.notifyData = notifyData;
 }
 
 nsNPAPIPluginStreamListener::~nsNPAPIPluginStreamListener()
 {
   // remove this from the plugin instance's stream list
@@ -203,17 +203,17 @@ nsNPAPIPluginStreamListener::CleanUpStre
   // Release any outstanding redirect callback.
   if (mHTTPRedirectCallback) {
     mHTTPRedirectCallback->OnRedirectVerifyCallback(NS_ERROR_FAILURE);
     mHTTPRedirectCallback = nullptr;
   }
 
   // Seekable streams have an extra addref when they are created which must
   // be matched here.
-  if (NP_SEEK == mStreamType && mStreamStarted)
+  if (NP_SEEK == mStreamType && mStreamState == eStreamTypeSet)
     NS_RELEASE_THIS();
 
   if (mStreamListenerPeer) {
     mStreamListenerPeer->CancelRequests(NS_BINDING_ABORTED);
     mStreamListenerPeer = nullptr;
   }
 
   if (!mInst || !mInst->CanFireNotifications())
@@ -225,32 +225,32 @@ nsNPAPIPluginStreamListener::CleanUpStre
   if (!plugin || !plugin->GetLibrary())
     return rv;
 
   NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
 
   NPP npp;
   mInst->GetNPP(&npp);
 
-  if (mStreamStarted && pluginFunctions->destroystream) {
+  if (mStreamState >= eNewStreamCalled && pluginFunctions->destroystream) {
     NPPAutoPusher nppPusher(npp);
 
     NPError error;
     NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->destroystream)(npp, &mNPStreamWrapper->mNPStream, reason), mInst,
                             NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
     
     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
                    ("NPP DestroyStream called: this=%p, npp=%p, reason=%d, return=%d, url=%s\n",
                     this, npp, reason, error, mNPStreamWrapper->mNPStream.url));
     
     if (error == NPERR_NO_ERROR)
       rv = NS_OK;
   }
   
-  mStreamStarted = false;
+  mStreamState = eStreamStopped;
   
   // fire notification back to plugin, just like before
   CallURLNotify(reason);
   
   return rv;
 }
 
 void
@@ -362,17 +362,17 @@ nsNPAPIPluginStreamListener::SetStreamTy
       // plugin calls NPN_DestroyStream (CleanUpStream). If the plugin never
       // calls NPN_DestroyStream the stream will be destroyed before the plugin
       // instance is destroyed.
       NS_ADDREF_THIS();
       break;
     default:
       return false;
   }
-  mStreamStarted = true;
+  mStreamState = eStreamTypeSet;
   if (aNeedsResume) {
     if (mStreamListenerPeer) {
       mStreamListenerPeer->OnStreamTypeSet(mStreamType);
     }
     ResumeRequest();
   }
   return true;
 }
@@ -586,17 +586,17 @@ nsNPAPIPluginStreamListener::OnDataAvail
         
         NS_TRY_SAFE_CALL_RETURN(numtowrite, (*pluginFunctions->writeready)(npp, &mNPStreamWrapper->mNPStream), mInst,
                                 NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
         NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
                        ("NPP WriteReady called: this=%p, npp=%p, "
                         "return(towrite)=%d, url=%s\n",
                         this, npp, numtowrite, mNPStreamWrapper->mNPStream.url));
         
-        if (!mStreamStarted) {
+        if (mStreamState == eStreamStopped) {
           // The plugin called NPN_DestroyStream() from within
           // NPP_WriteReady(), kill the stream.
           
           return NS_BINDING_ABORTED;
         }
         
         // if WriteReady returned 0, the plugin is not ready to handle
         // the data, suspend the stream (if it isn't already
@@ -638,17 +638,17 @@ nsNPAPIPluginStreamListener::OnDataAvail
                               NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
       
       NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
                      ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, "
                       "buf=%s, return(written)=%d,  url=%s\n",
                       this, npp, streamPosition, numtowrite,
                       ptrStreamBuffer, writeCount, mNPStreamWrapper->mNPStream.url));
       
-      if (!mStreamStarted) {
+      if (mStreamState == eStreamStopped) {
         // The plugin called NPN_DestroyStream() from within
         // NPP_Write(), kill the stream.
         return NS_BINDING_ABORTED;
       }
       
       if (writeCount > 0) {
         NS_ASSERTION(writeCount <= mStreamBufferByteCount,
                      "Plugin read past the end of the available data!");
@@ -809,17 +809,17 @@ nsNPAPIPluginStreamListener::Notify(nsIT
   
   if (NS_FAILED(rv)) {
     // We ran into an error, no need to keep firing this timer then.
     aTimer->Cancel();
     return NS_OK;
   }
   
   if (mStreamBufferByteCount != oldStreamBufferByteCount &&
-      ((mStreamStarted && mStreamBufferByteCount < 1024) ||
+      ((mStreamState == eStreamTypeSet && mStreamBufferByteCount < 1024) ||
        mStreamBufferByteCount == 0)) {
         // The plugin read some data and we've got less than 1024 bytes in
         // our buffer (or its empty and the stream is already
         // done). Resume the request so that we get more data off the
         // network.
         ResumeRequest();
         // Necko will pump data now that we've resumed the request.
         StopDataPump();
--- a/dom/plugins/base/nsNPAPIPluginStreamListener.h
+++ b/dom/plugins/base/nsNPAPIPluginStreamListener.h
@@ -100,25 +100,33 @@ public:
   void SetStreamListenerPeer(nsPluginStreamListenerPeer* aPeer) { mStreamListenerPeer = aPeer; }
 
   // Returns true if the redirect will be handled by NPAPI, false otherwise.
   bool HandleRedirectNotification(nsIChannel *oldChannel, nsIChannel *newChannel,
                                   nsIAsyncVerifyRedirectCallback* callback);
   void URLRedirectResponse(NPBool allow);
 
 protected:
+
+  enum StreamState
+  {
+    eStreamStopped = 0, // The stream is stopped
+    eNewStreamCalled,   // NPP_NewStream was called but has not completed yet
+    eStreamTypeSet      // The stream is fully initialized
+  };
+
   virtual ~nsNPAPIPluginStreamListener();
   char* mStreamBuffer;
   char* mNotifyURL;
   nsRefPtr<nsNPAPIPluginInstance> mInst;
   nsNPAPIStreamWrapper *mNPStreamWrapper;
   uint32_t mStreamBufferSize;
   int32_t mStreamBufferByteCount;
   int32_t mStreamType;
-  bool mStreamStarted;
+  StreamState mStreamState;
   bool mStreamCleanedUp;
   bool mCallNotify;
   bool mIsSuspended;
   bool mIsPluginInitJSStream;
   bool mRedirectDenied;
   nsCString mResponseHeaders;
   char* mResponseHeaderBuf;
   nsCOMPtr<nsITimer> mDataPumpTimer;