diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp index 2c804122c8d..7ce893c13de 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp @@ -65,6 +65,12 @@ #include "gtkxtbin.h" #endif +// POST/GET stream type +enum eNPPStreamTypeInternal { + eNPPStreamTypeInternal_Get, + eNPPStreamTypeInternal_Post +}; + //////////////////////////////////////////////////////////////////////// // CID's && IID's static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); @@ -656,6 +662,52 @@ ns4xPlugin::GetValue(nsPluginVariable variable, void *value) } } +// Create a new NPP GET or POST url stream that may have a notify callback +NPError MakeNew4xStreamInternal (NPP npp, + const char *relativeURL, + const char *target, + eNPPStreamTypeInternal type, /* GET or POST */ + PRBool bDoNotify = PR_FALSE, + void *notifyData = nsnull, + uint32 len = 0, + const char *buf = nsnull, + NPBool file = PR_FALSE) +{ + if(!npp) return NPERR_INVALID_INSTANCE_ERROR; + + nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; + + NS_ASSERTION(inst != NULL, "null instance"); + if (inst == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + nsCOMPtr pm = do_GetService(kPluginManagerCID); + NS_ASSERTION(pm, "failed to get plugin manager"); + if (!pm) return NPERR_GENERIC_ERROR; + + nsIPluginStreamListener* listener = nsnull; + if(target == nsnull) + ((ns4xPluginInstance*)inst)->NewNotifyStream(&listener, notifyData, bDoNotify); + + switch (type) { + case eNPPStreamTypeInternal_Get: + { + if(NS_FAILED(pm->GetURL(inst, relativeURL, target, listener))) + return NPERR_GENERIC_ERROR; + break; + } + case eNPPStreamTypeInternal_Post: + { + if(NS_FAILED(pm->PostURL(inst, relativeURL, len, buf, file, target, listener))) + return NPERR_GENERIC_ERROR; + break; + } + default: + NS_ASSERTION(0, "how'd I get here"); + } + + return NPERR_NO_ERROR; +} //////////////////////////////////////////////////////////////////////// // @@ -668,33 +720,7 @@ _geturl(NPP npp, const char* relativeURL, const char* target) NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetURL: npp=%p, target=%s, url=%s\n", (void *)npp, target, relativeURL)); - if(!npp) - return NPERR_INVALID_INSTANCE_ERROR; - - nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; - - NS_ASSERTION(inst != NULL, "null instance"); - NS_ASSERTION(gServiceMgr != NULL, "null service manager"); - - if (inst == NULL) - return NPERR_INVALID_INSTANCE_ERROR; - - if(gServiceMgr == nsnull) - return NPERR_GENERIC_ERROR; - - nsIPluginStreamListener* listener = nsnull; - if(target == nsnull) - inst->NewStream(&listener); - - nsIPluginManager * pm; - gServiceMgr->GetService(kPluginManagerCID, kIPluginManagerIID, (nsISupports**)&pm); - - if(pm->GetURL(inst, relativeURL, target, listener) != NS_OK) - return NPERR_GENERIC_ERROR; - - NS_RELEASE(pm); - - return NPERR_NO_ERROR; + return MakeNew4xStreamInternal (npp, relativeURL, target, eNPPStreamTypeInternal_Get); } @@ -705,33 +731,7 @@ _geturlnotify(NPP npp, const char* relativeURL, const char* target, void* notify NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetURLNotify: npp=%p, target=%s, notify=%p, url=%s\n", (void*)npp, target, notifyData, relativeURL)); - if(!npp) - return NPERR_INVALID_INSTANCE_ERROR; - - nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; - - NS_ASSERTION(inst != NULL, "null instance"); - NS_ASSERTION(gServiceMgr != NULL, "null service manager"); - - if (inst == NULL) - return NPERR_INVALID_INSTANCE_ERROR; - - if(gServiceMgr == nsnull) - return NPERR_GENERIC_ERROR; - - nsIPluginStreamListener* listener = nsnull; - if(target == nsnull) - ((ns4xPluginInstance*)inst)->NewNotifyStream(&listener, notifyData); - - nsIPluginManager * pm; - gServiceMgr->GetService(kPluginManagerCID, kIPluginManagerIID, (nsISupports**)&pm); - - if(pm->GetURL(inst, relativeURL, target, listener) != NS_OK) - return NPERR_GENERIC_ERROR; - - NS_RELEASE(pm); - - return NPERR_NO_ERROR; + return MakeNew4xStreamInternal (npp, relativeURL, target, eNPPStreamTypeInternal_Get, PR_TRUE, notifyData); } @@ -744,33 +744,8 @@ _posturlnotify(NPP npp, const char *relativeURL, const char *target, ("NPN_PostURLNotify: npp=%p, target=%s, len=%d, file=%d, notify=%p, url=%s, buf=%s\n", (void*)npp, target, len, file, notifyData, relativeURL, buf)); - if(!npp) - return NPERR_INVALID_INSTANCE_ERROR; - - nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; - - NS_ASSERTION(inst != NULL, "null instance"); - NS_ASSERTION(gServiceMgr != NULL, "null service manager"); - - if (inst == NULL) - return NPERR_INVALID_INSTANCE_ERROR; - - if(gServiceMgr == nsnull) - return NPERR_GENERIC_ERROR; - - nsIPluginStreamListener* listener = nsnull; - if(target == nsnull) - ((ns4xPluginInstance*)inst)->NewNotifyStream(&listener, notifyData); - - nsIPluginManager * pm; - gServiceMgr->GetService(kPluginManagerCID, kIPluginManagerIID, (nsISupports**)&pm); - - if(pm->PostURL(inst, relativeURL, len, buf, file, target, listener) != NS_OK) - return NPERR_GENERIC_ERROR; - - NS_RELEASE(pm); - - return NPERR_NO_ERROR; + return MakeNew4xStreamInternal (npp, relativeURL, target, eNPPStreamTypeInternal_Post, + PR_TRUE, notifyData, len, buf, file); } @@ -783,33 +758,8 @@ _posturl(NPP npp, const char *relativeURL, const char *target, ("NPN_PostURL: npp=%p, target=%s, file=%d, len=%d, url=%s, buf=%s\n", (void*)npp, target, file, len, relativeURL, buf)); - if(!npp) - return NPERR_INVALID_INSTANCE_ERROR; - - nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; - - NS_ASSERTION(inst != NULL, "null instance"); - NS_ASSERTION(gServiceMgr != NULL, "null service manager"); - - if (inst == NULL) - return NPERR_INVALID_INSTANCE_ERROR; - - if(gServiceMgr == nsnull) - return NPERR_GENERIC_ERROR; - - nsIPluginStreamListener* listener = nsnull; - if(target == nsnull) - inst->NewStream(&listener); - - nsIPluginManager * pm; - gServiceMgr->GetService(kPluginManagerCID, kIPluginManagerIID, (nsISupports**)&pm); - - if(pm->PostURL(inst, relativeURL, len, buf, file, target, listener) != NS_OK) - return NPERR_GENERIC_ERROR; - - NS_RELEASE(pm); - - return NPERR_NO_ERROR; + return MakeNew4xStreamInternal (npp, relativeURL, target, eNPPStreamTypeInternal_Post, + PR_FALSE, nsnull, len, buf, file); } diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp index 13805cadd37..4595c1ad312 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp @@ -82,7 +82,8 @@ ns4xPluginStreamListener::ns4xPluginStreamListener(nsIPluginInstance* inst, : mNotifyData(notifyData), mStreamStarted(PR_FALSE), mStreamCleanedUp(PR_FALSE), - mStreamInfo(nsnull) + mStreamInfo(nsnull), + mCallNotify(PR_FALSE) { NS_INIT_REFCNT(); mInst = (ns4xPluginInstance*) inst; @@ -100,12 +101,13 @@ ns4xPluginStreamListener::ns4xPluginStreamListener(nsIPluginInstance* inst, ns4xPluginStreamListener::~ns4xPluginStreamListener(void) { // remove itself from the instance stream list - if(mInst) { + ns4xPluginInstance *inst = mInst; + if(inst) { nsInstanceStream * prev = nsnull; - for(nsInstanceStream *is = mInst->mStreams; is != nsnull; is = is->mNext) { + for(nsInstanceStream *is = inst->mStreams; is != nsnull; is = is->mNext) { if(is->mPluginStreamListener == this) { if(prev == nsnull) - mInst->mStreams = is->mNext; + inst->mStreams = is->mNext; else prev->mNext = is->mNext; @@ -115,7 +117,13 @@ ns4xPluginStreamListener::~ns4xPluginStreamListener(void) prev = is; } } - NS_IF_RELEASE(mInst); + + // For those cases when NewStream is never called, we still may need to fire a + // notification callback. Return network error as fallback reason because for other + // cases, notify should have already been called for other reasons elsewhere. + CallURLNotify(NPRES_NETWORK_ERR); + + NS_IF_RELEASE(inst); } /////////////////////////////////////////////////////////////////////////////// @@ -155,22 +163,6 @@ nsresult ns4xPluginStreamListener::CleanUpStream(NPReason reason) rv = NS_OK; } - // check to see if we have a callback - if (callbacks->urlnotify && mNotifyData) { - PRLibrary* lib = nsnull; - lib = mInst->fLibrary; - - NS_TRY_SAFE_CALL_VOID(CallNPP_URLNotifyProc(callbacks->urlnotify, - npp, - mNPStream.url, - nsPluginReason_Done, - mNotifyData), lib); - - NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL, - ("NPP URLNotify called: this=%p, npp=%p, notify=%p, url=%s\n", - this, npp, mNotifyData, mNPStream.url)); - } - // lets get rid of the buffer if we made one globally if (mStreamBuffer) { @@ -180,10 +172,51 @@ nsresult ns4xPluginStreamListener::CleanUpStream(NPReason reason) mStreamCleanedUp = PR_TRUE; mStreamStarted = PR_FALSE; + + // fire notification back to plugin, just like before + CallURLNotify(reason); + return rv; } +/////////////////////////////////////////////////////////////////////////////// +void ns4xPluginStreamListener::CallURLNotify(NPReason reason) +{ + if(!mCallNotify || !mInst || !mInst->IsStarted()) + return; + + mCallNotify = PR_FALSE; // only do this ONCE and prevent recursion + + const NPPluginFuncs *callbacks = nsnull; + mInst->GetCallbacks(&callbacks); + if(!callbacks) + return; + + NPP npp; + mInst->GetNPP(&npp); + + if (callbacks->urlnotify) { + PRLibrary* lib = mInst->fLibrary; + + NS_TRY_SAFE_CALL_VOID(CallNPP_URLNotifyProc(callbacks->urlnotify, + npp, + mNPStream.url, + reason, + mNotifyData), lib); + + NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL, + ("NPP URLNotify called: this=%p, npp=%p, notify=%p, reason=%d, url=%s\n", + this, npp, mNotifyData, reason, mNPStream.url)); + } + + // Let's not leak this stream listener. Release the reference to the stream listener + // added for the notify callback in NewNotifyStream. + // Note: This may destroy us if we are not being destroyed already. + NS_RELEASE_THIS(); +} + + /////////////////////////////////////////////////////////////////////////////// NS_IMETHODIMP ns4xPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo) @@ -762,13 +795,17 @@ NS_IMETHODIMP ns4xPluginInstance::Stop(void) // clean up open streams for(nsInstanceStream *is = mStreams; is != nsnull;) { - if(is->mPluginStreamListener) - is->mPluginStreamListener->CleanUpStream(NPRES_USER_BREAK); + ns4xPluginStreamListener * listener = is->mPluginStreamListener; nsInstanceStream *next = is->mNext; delete is; is = next; mStreams = is; + + // Clean up our stream after removing it from the list because + // it may be released and destroyed at this point. + if(listener) + listener->CleanUpStream(NPRES_USER_BREAK); } NS_TRY_SAFE_CALL_RETURN(error, CallNPP_DestroyProc(fCallbacks->destroy, &fNPP, &sdata), fLibrary); @@ -1039,7 +1076,7 @@ NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d], return=%d\n", - this, &fNPP, window->x, window->y, window->width, window->height, + this, window->x, window->y, window->width, window->height, window->clipRect.top, window->clipRect.bottom, window->clipRect.left, window->clipRect.right, error)); // XXX In the old code, we'd just ignore any errors coming @@ -1052,29 +1089,30 @@ NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) //////////////////////////////////////////////////////////////////////// /* NOTE: the caller must free the stream listener */ +// Create a normal stream, one without a urlnotify callback NS_IMETHODIMP ns4xPluginInstance::NewStream(nsIPluginStreamListener** listener) { - return NewNotifyStream(listener, nsnull); + return NewNotifyStream(listener, nsnull, PR_FALSE); } //////////////////////////////////////////////////////////////////////// -nsresult ns4xPluginInstance::NewNotifyStream(nsIPluginStreamListener** listener, void* notifyData) +// Create a stream that will notify when complete +nsresult ns4xPluginInstance::NewNotifyStream(nsIPluginStreamListener** listener, + void* notifyData, + PRBool aCallNotify) { ns4xPluginStreamListener* stream = new ns4xPluginStreamListener(this, notifyData); - - if(stream == nsnull) - return NS_ERROR_OUT_OF_MEMORY; + NS_ENSURE_TRUE(stream, NS_ERROR_OUT_OF_MEMORY); // add it to the list nsInstanceStream * is = new nsInstanceStream(); - - if(!is) - return NS_ERROR_FAILURE; + NS_ENSURE_TRUE(is, NS_ERROR_OUT_OF_MEMORY); is->mNext = mStreams; is->mPluginStreamListener = stream; mStreams = is; + stream->SetCallNotify(aCallNotify); // set flag in stream to call URLNotify NS_ADDREF(stream); // Stabilize diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.h b/mozilla/modules/plugin/base/src/ns4xPluginInstance.h index 050c9bda4a4..b8687aa2329 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.h +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.h @@ -133,7 +133,7 @@ public: nsresult SetTransparent(PRBool aTransparent); - nsresult NewNotifyStream(nsIPluginStreamListener** listener, void* notifyData); + nsresult NewNotifyStream(nsIPluginStreamListener** listener, void* notifyData, PRBool aCallNotify); /** * Construct a new 4.x plugin instance with the specified peer diff --git a/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h b/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h index 94710ca7c4a..238ac477fff 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h +++ b/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h @@ -64,6 +64,8 @@ public: virtual ~ns4xPluginStreamListener(); PRBool IsStarted(); nsresult CleanUpStream(NPReason reason); + void CallURLNotify(NPReason reason); + void SetCallNotify(PRBool aCallNotify) { mCallNotify = aCallNotify; } protected: void* mNotifyData; @@ -75,6 +77,7 @@ protected: nsPluginStreamType mStreamType; PRBool mStreamStarted; PRBool mStreamCleanedUp; + PRBool mCallNotify; public: nsIPluginStreamInfo * mStreamInfo;