Landing fix for bug 347805. Add support for passing information about failed HTTP streams to plugins. Patch by dbalev@adobe.com, r+sr=jst@mozilla.org
authorJohnny Stenback <jst@mozilla.com>
Mon, 04 Aug 2008 14:17:55 -0700
changeset 16367 b3954e41f988b83caba80c29150c41ebc7b422c3
parent 16366 1bef2be14d0f7b17926bd2cd904f74a39bb9f50f
child 16368 3884f94377536b4c2fcdf7854631d3282ddb1da0
push idunknown
push userunknown
push dateunknown
bugs347805
milestone1.9.1a2pre
Landing fix for bug 347805. Add support for passing information about failed HTTP streams to plugins. Patch by dbalev@adobe.com, r+sr=jst@mozilla.org
modules/plugin/base/public/npapi.h
modules/plugin/base/public/nsplugindefs.h
modules/plugin/base/src/ns4xPlugin.cpp
modules/plugin/base/src/ns4xPluginInstance.cpp
modules/plugin/base/src/ns4xPluginInstance.h
modules/plugin/base/src/nsPluginHostImpl.cpp
--- a/modules/plugin/base/public/npapi.h
+++ b/modules/plugin/base/public/npapi.h
@@ -115,17 +115,17 @@
 #	endif
 #endif
 
 /*----------------------------------------------------------------------*/
 /*                        Plugin Version Constants                      */
 /*----------------------------------------------------------------------*/
 
 #define NP_VERSION_MAJOR 0
-#define NP_VERSION_MINOR 19
+#define NP_VERSION_MINOR 20
 
 
 /* The OS/2 version of Netscape uses RC_DATA to define the
    mime types, file extensions, etc that are required.
    Use a vertical bar to separate types, end types with \0.
    FileVersion and ProductVersion are 32bit ints, all other
    entries are strings the MUST be terminated wwith a \0.
 
@@ -406,17 +406,24 @@ typedef enum {
    */
   NPPVpluginScriptableNPObject  = 15,
 
   /* Get the plugin value (as \0-terminated UTF-8 string data) for
    * form submission if the plugin is part of a form. Use
    * NPN_MemAlloc() to allocate memory for the string data. Introduced
    * in Mozilla 1.8b2 (NPAPI minor version 15).
    */
-  NPPVformValue = 16
+  NPPVformValue = 16,
+  
+  NPPVpluginUrlRequestsDisplayedBool = 17,
+  
+  /* Checks if the plugin is interested in receiving the http body of
+   * all http requests (including failed ones, http status != 200).
+   */
+  NPPVpluginWantsAllNetworkStreams = 18
 #ifdef XP_MACOSX
   /* Used for negotiating drawing models */
   , NPPVpluginDrawingModel = 1000
 #endif
 } NPPVariable;
 
 /*
  * List of variable names for which NPN_GetValue is implemented by Mozilla
@@ -653,16 +660,17 @@ enum NPEventType {
 #define NPVERS_HAS_WINDOWLESS               11
 #define NPVERS_HAS_XPCONNECT_SCRIPTING      13
 #define NPVERS_HAS_NPRUNTIME_SCRIPTING      14
 #define NPVERS_HAS_FORM_VALUES              15
 #define NPVERS_HAS_POPUPS_ENABLED_STATE     16
 #define NPVERS_HAS_RESPONSE_HEADERS         17
 #define NPVERS_HAS_NPOBJECT_ENUM            18
 #define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
+#define NPVERS_HAS_ALL_NETWORK_STREAMS      20
 
 /*----------------------------------------------------------------------*/
 /*                        Function Prototypes                           */
 /*----------------------------------------------------------------------*/
 
 #if defined(_WINDOWS) && !defined(WIN32)
 #define NP_LOADDS  _loadds
 #else
--- a/modules/plugin/base/public/nsplugindefs.h
+++ b/modules/plugin/base/public/nsplugindefs.h
@@ -196,17 +196,18 @@ enum nsPluginInstancePeerVariable {
 
 enum nsPluginInstanceVariable {
     nsPluginInstanceVariable_WindowlessBool          = 3,
     nsPluginInstanceVariable_TransparentBool         = 4,
     nsPluginInstanceVariable_DoCacheBool             = 5,
     nsPluginInstanceVariable_CallSetWindowAfterDestroyBool = 6,
     nsPluginInstanceVariable_ScriptableInstance      = 10,
     nsPluginInstanceVariable_ScriptableIID           = 11,
-    nsPluginInstanceVariable_NeedsXEmbed             = 14
+    nsPluginInstanceVariable_NeedsXEmbed             = 14,
+    nsPluginInstanceVariable_WantsAllNetworkStreams  = 18
 #ifdef XP_MACOSX
     , nsPluginInstanceVariable_DrawingModel          = 20
 #endif
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
 enum nsPluginMode {
--- a/modules/plugin/base/src/ns4xPlugin.cpp
+++ b/modules/plugin/base/src/ns4xPlugin.cpp
@@ -2452,17 +2452,22 @@ NPError NP_CALLBACK
         return NS_SUCCEEDED(rv) ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
       }
       break;
 
     case NPPVpluginKeepLibraryInMemory: {
       NPBool bCached = (result != nsnull);
       return inst->SetCached(bCached);
     }
-      
+
+    case NPPVpluginWantsAllNetworkStreams: {
+      PRBool bWantsAllNetworkStreams = (result != nsnull);
+      return inst->SetWantsAllNetworkStreams(bWantsAllNetworkStreams);
+    }
+
 #ifdef XP_MACOSX
     case NPPVpluginDrawingModel: {
       if (inst) {
         int dModelValue = (int)result;
         inst->SetDrawingModel((NPDrawingModel)dModelValue);
         return NPERR_NO_ERROR;
       }
       else {
--- a/modules/plugin/base/src/ns4xPluginInstance.cpp
+++ b/modules/plugin/base/src/ns4xPluginInstance.cpp
@@ -828,16 +828,17 @@ ns4xPluginInstance::ns4xPluginInstance(N
     mDrawingModel(NPDrawingModelQuickDraw),
 #endif
 #endif
     mWindowless(PR_FALSE),
     mTransparent(PR_FALSE),
     mStarted(PR_FALSE),
     mCached(PR_FALSE),
     mIsJavaPlugin(PR_FALSE),
+    mWantsAllNetworkStreams(PR_FALSE),
     mInPluginInitCall(PR_FALSE),
     fLibrary(aLibrary),
     mStreams(nsnull)
 {
   NS_ASSERTION(fCallbacks != NULL, "null callbacks");
 
   // Initialize the NPP structure.
 
@@ -1432,16 +1433,23 @@ NPError ns4xPluginInstance::SetWindowles
 
 ////////////////////////////////////////////////////////////////////////
 NPError ns4xPluginInstance::SetTransparent(PRBool aTransparent)
 {
   mTransparent = aTransparent;
   return NPERR_NO_ERROR;
 }
 
+////////////////////////////////////////////////////////////////////////
+NPError ns4xPluginInstance::SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams)
+{
+  mWantsAllNetworkStreams = aWantsAllNetworkStreams;
+  return NPERR_NO_ERROR;
+}
+
 #ifdef XP_MACOSX
 ////////////////////////////////////////////////////////////////////////
 void ns4xPluginInstance::SetDrawingModel(NPDrawingModel aModel)
 {
   mDrawingModel = aModel;
 }
 
 
--- a/modules/plugin/base/src/ns4xPluginInstance.h
+++ b/modules/plugin/base/src/ns4xPluginInstance.h
@@ -110,16 +110,18 @@ public:
      * Return the callbacks for the plugin instance.
      */
     nsresult GetCallbacks(const NPPluginFuncs ** aCallbacks);
 
     NPError SetWindowless(PRBool aWindowless);
 
     NPError SetTransparent(PRBool aTransparent);
 
+    NPError SetWantsAllNetworkStreams(PRBool aWantsAllNetworkStreams);
+
 #ifdef XP_MACOSX
     void SetDrawingModel(NPDrawingModel aModel);
     NPDrawingModel GetDrawingModel();
 #endif
 
     nsresult NewNotifyStream(nsIPluginStreamListener** listener, 
                              void* notifyData, 
                              PRBool aCallNotify,
@@ -182,16 +184,17 @@ protected:
     //these are used to store the windowless properties
     //which the browser will later query
 
     PRPackedBool  mWindowless;
     PRPackedBool  mTransparent;
     PRPackedBool  mStarted;
     PRPackedBool  mCached;
     PRPackedBool  mIsJavaPlugin;
+    PRPackedBool  mWantsAllNetworkStreams;
 
 public:
     // True while creating the plugin, or calling NPP_SetWindow() on
     // it.
     PRPackedBool  mInPluginInitCall;
     PRLibrary* fLibrary;
     nsInstanceStream *mStreams;
 
--- a/modules/plugin/base/src/nsPluginHostImpl.cpp
+++ b/modules/plugin/base/src/nsPluginHostImpl.cpp
@@ -1307,16 +1307,18 @@ public:
                              nsIPluginInstanceOwner *aOwner = nsnull,
                              nsIPluginHost *aHost = nsnull);
 
   nsresult InitializeFullPage(nsIPluginInstance *aInstance);
 
   nsresult OnFileAvailable(nsIFile* aFile);
 
   nsresult ServeStreamAsFile(nsIRequest *request, nsISupports *ctxt);
+  
+  nsIPluginInstance *GetPluginInstance() { return mInstance; }
 
 private:
   nsresult SetUpCache(nsIURI* aURL); // todo: see about removing this...
   nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
   nsresult SetupPluginCacheFile(nsIChannel* channel);
 
   nsIURI                  *mURL;
   nsIPluginInstanceOwner  *mOwner;
@@ -2025,24 +2027,34 @@ nsPluginStreamListenerPeer::OnStartReque
   NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
 
   // deal with 404 (Not Found) HTTP response,
   // just return, this causes the request to be ignored.
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
     PRUint32 responseCode = 0;
     rv = httpChannel->GetResponseStatus(&responseCode);
-    if (NS_FAILED(rv) || responseCode > 206) { // not normal
+    if (NS_FAILED(rv)) {
       // NPP_Notify() will be called from OnStopRequest
       // in ns4xPluginStreamListener::CleanUpStream
       // return error will cancel this request
       // ...and we also need to tell the plugin that
       mRequestFailed = PR_TRUE;
       return NS_ERROR_FAILURE;
     }
+
+    if (responseCode > 206) { // not normal
+      PRBool bWantsAllNetworkStreams = PR_FALSE;
+      mInstance->GetValue(nsPluginInstanceVariable_WantsAllNetworkStreams,
+                          (void *)&bWantsAllNetworkStreams);
+      if(!bWantsAllNetworkStreams) {
+        mRequestFailed = PR_TRUE;
+        return NS_ERROR_FAILURE;
+      }
+    }
   }
 
   // do a little sanity check to make sure our frame isn't gone
   // by getting the tag type and checking for an error, we can determine if
   // the frame is gone
   if (mOwner) {
     nsCOMPtr<nsIPluginTagInfo2> pti2 = do_QueryInterface(mOwner);
     NS_ENSURE_TRUE(pti2, NS_ERROR_FAILURE);
@@ -7117,28 +7129,39 @@ nsPluginByteRangeStreamListener::OnStart
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
   if (!httpChannel) {
     return NS_ERROR_FAILURE;
   }
 
   PRUint32 responseCode = 0;
   rv = httpChannel->GetResponseStatus(&responseCode);
-  if (NS_FAILED(rv) || responseCode != 200) {
+  if (NS_FAILED(rv)) {
     return NS_ERROR_FAILURE;
   }
+  
+  // get nsPluginStreamListenerPeer* ptr from finalStreamListener
+  nsPluginStreamListenerPeer *pslp =
+    reinterpret_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get());
+
+  if (responseCode != 200) {
+    PRBool bWantsAllNetworkStreams = PR_FALSE;
+    pslp->GetPluginInstance()->
+      GetValue(nsPluginInstanceVariable_WantsAllNetworkStreams,
+               (void *)&bWantsAllNetworkStreams);
+    if (!bWantsAllNetworkStreams){
+      return NS_ERROR_FAILURE;
+    }
+  }
 
   // if server cannot continue with byte range (206 status) and sending us whole object (200 status)
   // reset this seekable stream & try serve it to plugin instance as a file
   mStreamConverter = finalStreamListener;
   mRemoveMagicNumber = PR_TRUE;
 
-  //get nsPluginStreamListenerPeer* ptr from finalStreamListener
-  nsPluginStreamListenerPeer *pslp = reinterpret_cast<nsPluginStreamListenerPeer*>
-                                                     (finalStreamListener.get());
   rv = pslp->ServeStreamAsFile(request, ctxt);
   return rv;
 }
 
 NS_IMETHODIMP
 nsPluginByteRangeStreamListener::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
                               nsresult status)
 {