From 1f48854fb7b04431f5460cb1708940c5b0dc7393 Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Sat, 27 Feb 2010 17:36:54 -0500 Subject: [PATCH] Backed out changeset f829f942873d - bug 548217 because of topcrash bug 549112 --- .../base/public/nsIPluginInstanceOwner.idl | 7 - modules/plugin/base/src/nsNPAPIPlugin.cpp | 9 +- .../plugin/base/src/nsNPAPIPluginInstance.cpp | 38 +- modules/plugin/base/src/nsPluginHost.cpp | 409 +++++++++++++----- modules/plugin/test/testplugin/nptest.cpp | 3 + 5 files changed, 329 insertions(+), 137 deletions(-) diff --git a/modules/plugin/base/public/nsIPluginInstanceOwner.idl b/modules/plugin/base/public/nsIPluginInstanceOwner.idl index 17cc7d5a3f02..1bf17d4f0743 100644 --- a/modules/plugin/base/public/nsIPluginInstanceOwner.idl +++ b/modules/plugin/base/public/nsIPluginInstanceOwner.idl @@ -63,13 +63,6 @@ interface nsIPluginInstanceOwner : nsISupports */ void getInstance(in nsIPluginInstanceRef aInstance); -%{C++ - // make getter_AddRefs work - inline nsresult GetInstance(nsIPluginInstance** aInstance) { - return GetInstance(*aInstance); - } -%} - /** * Get a handle to the window structure of the owner. * This pointer cannot be made persistent by the caller. diff --git a/modules/plugin/base/src/nsNPAPIPlugin.cpp b/modules/plugin/base/src/nsNPAPIPlugin.cpp index f157da454aea..92843fff99f2 100644 --- a/modules/plugin/base/src/nsNPAPIPlugin.cpp +++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp @@ -2379,13 +2379,8 @@ _requestread(NPStream *pstream, NPByteRange *rangeList) if (streamtype != NP_SEEK) return NPERR_STREAM_NOT_SEEKABLE; - if (!streamlistener->mStreamInfo) - return NPERR_GENERIC_ERROR; - - nsresult rv = streamlistener->mStreamInfo - ->RequestRead((NPByteRange *)rangeList); - if (NS_FAILED(rv)) - return NPERR_GENERIC_ERROR; + if (streamlistener->mStreamInfo) + streamlistener->mStreamInfo->RequestRead((NPByteRange *)rangeList); return NS_OK; } diff --git a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp index 5bfe6bb76a1b..fab1f581efc5 100644 --- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp +++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp @@ -256,20 +256,9 @@ nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason) if (mStreamCleanedUp) return NS_OK; - mStreamCleanedUp = PR_TRUE; - - StopDataPump(); - - // Seekable streams have an extra addref when they are created which must - // be matched here. - if (NP_SEEK == mStreamType) - NS_RELEASE_THIS(); - if (!mInst || !mInst->IsRunning()) return rv; - mStreamInfo = NULL; - PluginDestructionGuard guard(mInst); const NPPluginFuncs *callbacks = nsnull; @@ -296,7 +285,10 @@ nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason) rv = NS_OK; } - mStreamStarted = PR_FALSE; + mStreamCleanedUp = PR_TRUE; + mStreamStarted = PR_FALSE; + + StopDataPump(); // fire notification back to plugin, just like before CallURLNotify(reason); @@ -393,12 +385,6 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo) break; case NP_SEEK: mStreamType = NP_SEEK; - // Seekable streams should continue to exist even after OnStopRequest - // is fired, so we AddRef ourself an extra time and Release when the - // 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 NS_ERROR_FAILURE; @@ -808,13 +794,19 @@ nsNPAPIPluginStreamListener::OnStopBinding(nsIPluginStreamInfo* pluginInfo, // check if the stream is of seekable type and later its destruction // see bug 91140 nsresult rv = NS_OK; - NPReason reason = NS_FAILED(status) ? NPRES_NETWORK_ERR : NPRES_DONE; - if (mStreamType != NP_SEEK || - (NP_SEEK == mStreamType && NS_BINDING_ABORTED == status)) { + if (mStreamType != NP_SEEK) { + NPReason reason = NPRES_DONE; + + if (NS_FAILED(status)) + reason = NPRES_NETWORK_ERR; // since the stream failed, we need to tell the plugin that + rv = CleanUpStream(reason); } - return rv; + if (rv != NPERR_NO_ERROR) + return NS_ERROR_FAILURE; + + return NS_OK; } NS_IMETHODIMP @@ -1019,7 +1011,7 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Stop() // clean up open streams for (nsInstanceStream *is = mStreams; is != nsnull;) { - nsRefPtr listener = is->mPluginStreamListener; + nsNPAPIPluginStreamListener * listener = is->mPluginStreamListener; nsInstanceStream *next = is->mNext; delete is; diff --git a/modules/plugin/base/src/nsPluginHost.cpp b/modules/plugin/base/src/nsPluginHost.cpp index bbce962b235c..a4da7ac9d65c 100644 --- a/modules/plugin/base/src/nsPluginHost.cpp +++ b/modules/plugin/base/src/nsPluginHost.cpp @@ -138,7 +138,7 @@ #include "nsPluginManifestLineReader.h" #include "nsDefaultPlugin.h" -#include "nsIWeakReferenceUtils.h" +#include "nsWeakReference.h" #include "nsIDOMElement.h" #include "nsIDOMHTMLObjectElement.h" #include "nsIDOMHTMLEmbedElement.h" @@ -345,11 +345,97 @@ nsresult nsPluginHost::PostPluginUnloadEvent(PRLibrary* aLibrary) return NS_ERROR_FAILURE; } +class nsPluginStreamListenerPeer; + +class nsPluginStreamInfo : public nsINPAPIPluginStreamInfo +{ +public: + nsPluginStreamInfo(); + virtual ~nsPluginStreamInfo(); + + NS_DECL_ISUPPORTS + + // nsINPAPIPluginStreamInfo interface + + NS_IMETHOD + GetContentType(char **result); + + NS_IMETHOD + IsSeekable(PRBool* result); + + NS_IMETHOD + GetLength(PRUint32* result); + + NS_IMETHOD + GetLastModified(PRUint32* result); + + NS_IMETHOD + GetURL(const char** result); + + NS_IMETHOD + RequestRead(NPByteRange* rangeList); + + NS_IMETHOD + GetStreamOffset(PRInt32 *result); + + NS_IMETHOD + SetStreamOffset(PRInt32 result); + + // local methods + + void + SetContentType(const char* contentType); + + void + SetSeekable(const PRBool seekable); + + void + SetLength(const PRUint32 length); + + void + SetLastModified(const PRUint32 modified); + + void + SetURL(const char* url); + + void + SetPluginInstance(nsIPluginInstance * aPluginInstance); + + void + SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer); + + void + MakeByteRangeString(NPByteRange* aRangeList, nsACString &string, PRInt32 *numRequests); + + PRBool + UseExistingPluginCacheFile(nsPluginStreamInfo* psi); + + void + SetStreamComplete(const PRBool complete); + + void + SetRequest(nsIRequest *request) + { + mRequest = request; + } + +private: + + char* mContentType; + char* mURL; + PRBool mSeekable; + PRUint32 mLength; + PRUint32 mModified; + nsIPluginInstance * mPluginInstance; + nsPluginStreamListenerPeer * mPluginStreamListenerPeer; + PRInt32 mStreamOffset; + PRBool mStreamComplete; +}; + class nsPluginStreamListenerPeer : public nsIStreamListener, public nsIProgressEventSink, public nsIHttpHeaderVisitor, - public nsSupportsWeakReference, - public nsINPAPIPluginStreamInfo + public nsSupportsWeakReference { public: nsPluginStreamListenerPeer(); @@ -361,15 +447,6 @@ public: NS_DECL_NSISTREAMLISTENER NS_DECL_NSIHTTPHEADERVISITOR - // nsINPAPIPluginStreamInfo interface - NS_DECL_NSIPLUGINSTREAMINFO - - // Called by RequestRead - void - MakeByteRangeString(NPByteRange* aRangeList, nsACString &string, PRInt32 *numRequests); - - PRBool UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi); - // Called by GetURL and PostURL (via NewStream) nsresult Initialize(nsIURI *aURL, nsIPluginInstance *aInstance, @@ -392,11 +469,11 @@ private: nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL); nsresult SetupPluginCacheFile(nsIChannel* channel); - nsCOMPtr mURL; - nsCString mURLSpec; // Have to keep this member because GetURL hands out char* - nsCOMPtr mOwner; - nsCOMPtr mInstance; - nsCOMPtr mPStreamListener; + nsIURI *mURL; + nsIPluginInstanceOwner *mOwner; + nsIPluginInstance *mInstance; + nsIPluginStreamListener *mPStreamListener; + nsRefPtr mPluginStreamInfo; // Set to PR_TRUE if we request failed (like with a HTTP response of 404) PRPackedBool mRequestFailed; @@ -410,22 +487,16 @@ private: PRPackedBool mStartBinding; PRPackedBool mHaveFiredOnStartRequest; // these get passed to the plugin stream listener + char *mMIMEType; PRUint32 mLength; PRInt32 mStreamType; // local cached file, we save the content into local cache if browser cache is not available, // or plugin asks stream as file and it expects file extension until bug 90558 got fixed - nsCOMPtr mLocalCachedFile; + nsIFile *mLocalCachedFile; nsCOMPtr mFileCacheOutputStream; nsHashtable *mDataForwardToRequest; - nsCString mContentType; - PRBool mSeekable; - PRUint32 mModified; - nsCOMPtr mPluginInstance; - PRInt32 mStreamOffset; - PRBool mStreamComplete; - public: PRBool mAbort; PRInt32 mPendingRequests; @@ -448,44 +519,70 @@ private: PRBool mRemoveMagicNumber; }; -NS_IMETHODIMP -nsPluginStreamListenerPeer::GetContentType(char** result) +nsPluginStreamInfo::nsPluginStreamInfo() { - *result = const_cast(mContentType.get()); + mPluginInstance = nsnull; + mPluginStreamListenerPeer = nsnull; + + mContentType = nsnull; + mURL = nsnull; + mSeekable = PR_FALSE; + mLength = 0; + mModified = 0; + mStreamOffset = 0; + mStreamComplete = PR_FALSE; +} + +nsPluginStreamInfo::~nsPluginStreamInfo() +{ + if (mContentType) + PL_strfree(mContentType); + if (mURL) + PL_strfree(mURL); + + NS_IF_RELEASE(mPluginInstance); +} + +NS_IMPL_ISUPPORTS2(nsPluginStreamInfo, nsIPluginStreamInfo, + nsINPAPIPluginStreamInfo) + +NS_IMETHODIMP +nsPluginStreamInfo::GetContentType(char **result) +{ + *result = mContentType; return NS_OK; } NS_IMETHODIMP -nsPluginStreamListenerPeer::IsSeekable(PRBool* result) +nsPluginStreamInfo::IsSeekable(PRBool* result) { *result = mSeekable; return NS_OK; } NS_IMETHODIMP -nsPluginStreamListenerPeer::GetLength(PRUint32* result) +nsPluginStreamInfo::GetLength(PRUint32* result) { *result = mLength; return NS_OK; } NS_IMETHODIMP -nsPluginStreamListenerPeer::GetLastModified(PRUint32* result) +nsPluginStreamInfo::GetLastModified(PRUint32* result) { *result = mModified; return NS_OK; } NS_IMETHODIMP -nsPluginStreamListenerPeer::GetURL(const char** result) +nsPluginStreamInfo::GetURL(const char** result) { - *result = mURLSpec.get(); + *result = mURL; return NS_OK; } void -nsPluginStreamListenerPeer::MakeByteRangeString(NPByteRange* aRangeList, nsACString &rangeRequest, - PRInt32 *numRequests) +nsPluginStreamInfo::MakeByteRangeString(NPByteRange* aRangeList, nsACString &rangeRequest, PRInt32 *numRequests) { rangeRequest.Truncate(); *numRequests = 0; @@ -520,22 +617,36 @@ nsPluginStreamListenerPeer::MakeByteRangeString(NPByteRange* aRangeList, nsACStr } NS_IMETHODIMP -nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList) +nsPluginStreamInfo::RequestRead(NPByteRange* rangeList) { nsCAutoString rangeString; PRInt32 numRequests; + //first of all lets see if mPluginStreamListenerPeer is still alive + nsCOMPtr suppWeakRef( + do_QueryInterface((nsISupportsWeakReference *)(mPluginStreamListenerPeer))); + if (!suppWeakRef) + return NS_ERROR_FAILURE; + + nsCOMPtr pWeakRefPluginStreamListenerPeer = + do_GetWeakReference(suppWeakRef); + if (!pWeakRefPluginStreamListenerPeer) + return NS_ERROR_FAILURE; + MakeByteRangeString(rangeList, rangeString, &numRequests); if (numRequests == 0) return NS_ERROR_FAILURE; nsresult rv = NS_OK; + nsCOMPtr url; - nsCOMPtr callbacks = do_QueryReferent(mWeakPtrChannelCallbacks); - nsCOMPtr loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup); + rv = NS_NewURI(getter_AddRefs(url), nsDependentCString(mURL)); + + nsCOMPtr callbacks = do_QueryReferent(mPluginStreamListenerPeer->mWeakPtrChannelCallbacks); + nsCOMPtr loadGroup = do_QueryReferent(mPluginStreamListenerPeer->mWeakPtrChannelLoadGroup); nsCOMPtr channel; - rv = NS_NewChannel(getter_AddRefs(channel), mURL, nsnull, loadGroup, callbacks); + rv = NS_NewChannel(getter_AddRefs(channel), url, nsnull, loadGroup, callbacks); if (NS_FAILED(rv)) return rv; @@ -545,29 +656,28 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList) httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, PR_FALSE); - mAbort = PR_TRUE; // instruct old stream listener to cancel - // the request on the next ODA. + mPluginStreamListenerPeer->mAbort = PR_TRUE; // instruct old stream listener to cancel + // the request on the next ODA. nsCOMPtr converter; if (numRequests == 1) { - converter = this; + converter = mPluginStreamListenerPeer; + // set current stream offset equal to the first offset in the range list // it will work for single byte range request // for multy range we'll reset it in ODA SetStreamOffset(rangeList->offset); } else { - nsWeakPtr weakpeer = - do_GetWeakReference(static_cast(this)); nsPluginByteRangeStreamListener *brrListener = - new nsPluginByteRangeStreamListener(weakpeer); + new nsPluginByteRangeStreamListener(pWeakRefPluginStreamListenerPeer); if (brrListener) converter = brrListener; else return NS_ERROR_OUT_OF_MEMORY; } - mPendingRequests += numRequests; + mPluginStreamListenerPeer->mPendingRequests += numRequests; nsCOMPtr container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv); if (NS_FAILED(rv)) @@ -580,19 +690,68 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList) } NS_IMETHODIMP -nsPluginStreamListenerPeer::GetStreamOffset(PRInt32* result) +nsPluginStreamInfo::GetStreamOffset(PRInt32 *result) { *result = mStreamOffset; return NS_OK; } NS_IMETHODIMP -nsPluginStreamListenerPeer::SetStreamOffset(PRInt32 value) +nsPluginStreamInfo::SetStreamOffset(PRInt32 offset) { - mStreamOffset = value; + mStreamOffset = offset; return NS_OK; } +void +nsPluginStreamInfo::SetContentType(const char* contentType) +{ + if (mContentType != nsnull) + PL_strfree(mContentType); + + mContentType = PL_strdup(contentType); +} + +void +nsPluginStreamInfo::SetSeekable(const PRBool seekable) +{ + mSeekable = seekable; +} + +void +nsPluginStreamInfo::SetLength(const PRUint32 length) +{ + mLength = length; +} + +void +nsPluginStreamInfo::SetLastModified(const PRUint32 modified) +{ + mModified = modified; +} + +void +nsPluginStreamInfo::SetURL(const char* url) +{ + if (mURL) + PL_strfree(mURL); + + mURL = PL_strdup(url); +} + +void +nsPluginStreamInfo::SetPluginInstance(nsIPluginInstance * aPluginInstance) +{ + NS_IF_ADDREF(mPluginInstance = aPluginInstance); +} + +void +nsPluginStreamInfo::SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer) +{ + // not addref'd - nsPluginStreamInfo is owned by mPluginStreamListenerPeer + mPluginStreamListenerPeer = aPluginStreamListenerPeer; +} + class nsPluginCacheListener : public nsIStreamListener { public: @@ -659,6 +818,10 @@ nsPluginCacheListener::OnStopRequest(nsIRequest *request, nsPluginStreamListenerPeer::nsPluginStreamListenerPeer() { + mURL = nsnull; + mOwner = nsnull; + mInstance = nsnull; + mPStreamListener = nsnull; mStreamType = NP_NORMAL; mStartBinding = PR_FALSE; mAbort = PR_FALSE; @@ -667,20 +830,24 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer() mPendingRequests = 0; mHaveFiredOnStartRequest = PR_FALSE; mDataForwardToRequest = nsnull; - - mSeekable = PR_FALSE; - mModified = 0; - mStreamOffset = 0; - mStreamComplete = 0; + mLocalCachedFile = nsnull; } nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer() { #ifdef PLUGIN_LOGGING + nsCAutoString urlSpec; + if (mURL != nsnull) mURL->GetSpec(urlSpec); + PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL, - ("nsPluginStreamListenerPeer::dtor this=%p, url=%s%c",this, mURLSpec.get(), mLocalCachedFile?',':'\n')); + ("nsPluginStreamListenerPeer::dtor this=%p, url=%s%c",this, urlSpec.get(), mLocalCachedFile?',':'\n')); #endif + NS_IF_RELEASE(mURL); + NS_IF_RELEASE(mOwner); + NS_IF_RELEASE(mInstance); + NS_IF_RELEASE(mPStreamListener); + // close FD of mFileCacheOutputStream if it's still open // or we won't be able to remove the cache file if (mFileCacheOutputStream) @@ -702,19 +869,18 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer() if (refcnt == 1) { mLocalCachedFile->Remove(PR_FALSE); + NS_RELEASE(mLocalCachedFile); } } delete mDataForwardToRequest; } -NS_IMPL_ISUPPORTS6(nsPluginStreamListenerPeer, +NS_IMPL_ISUPPORTS4(nsPluginStreamListenerPeer, nsIStreamListener, nsIRequestObserver, nsIHttpHeaderVisitor, - nsISupportsWeakReference, - nsIPluginStreamInfo, - nsINPAPIPluginStreamInfo) + nsISupportsWeakReference) // Called as a result of GetURL and PostURL nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL, @@ -733,9 +899,20 @@ nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL, #endif mURL = aURL; + NS_ADDREF(mURL); mInstance = aInstance; + NS_ADDREF(mInstance); + mPStreamListener = aListener; + NS_ADDREF(mPStreamListener); + + mPluginStreamInfo = new nsPluginStreamInfo(); + if (!mPluginStreamInfo) + return NS_ERROR_OUT_OF_MEMORY; + + mPluginStreamInfo->SetPluginInstance(aInstance); + mPluginStreamInfo->SetPluginStreamListenerPeer(this); mPendingRequests = requestCount; @@ -767,14 +944,24 @@ nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL, #endif mURL = aURL; + NS_ADDREF(mURL); if (aInstance) { NS_ASSERTION(mInstance == nsnull, "nsPluginStreamListenerPeer::InitializeEmbedded mInstance != nsnull"); mInstance = aInstance; + NS_ADDREF(mInstance); } else { mOwner = aOwner; + NS_IF_ADDREF(mOwner); } + mPluginStreamInfo = new nsPluginStreamInfo(); + if (!mPluginStreamInfo) + return NS_ERROR_OUT_OF_MEMORY; + + mPluginStreamInfo->SetPluginInstance(aInstance); + mPluginStreamInfo->SetPluginStreamListenerPeer(this); + mDataForwardToRequest = new nsHashtable(16, PR_FALSE); if (!mDataForwardToRequest) return NS_ERROR_FAILURE; @@ -791,6 +978,14 @@ nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIPluginInstance *aInst NS_ASSERTION(mInstance == nsnull, "nsPluginStreamListenerPeer::InitializeFullPage mInstance != nsnull"); mInstance = aInstance; + NS_ADDREF(mInstance); + + mPluginStreamInfo = new nsPluginStreamInfo(); + if (!mPluginStreamInfo) + return NS_ERROR_OUT_OF_MEMORY; + + mPluginStreamInfo->SetPluginInstance(aInstance); + mPluginStreamInfo->SetPluginStreamListenerPeer(this); mDataForwardToRequest = new nsHashtable(16, PR_FALSE); if (!mDataForwardToRequest) @@ -824,10 +1019,11 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel) while (--cnt >= 0) { nsPluginStreamListenerPeer *lp = reinterpret_cast(instanceTag->mStreams->ElementAt(cnt)); - if (lp && lp->mLocalCachedFile) { - useExistingCacheFile = lp->UseExistingPluginCacheFile(this); + if (lp && lp->mLocalCachedFile && lp->mPluginStreamInfo) { + useExistingCacheFile = lp->mPluginStreamInfo->UseExistingPluginCacheFile(mPluginStreamInfo); if (useExistingCacheFile) { mLocalCachedFile = lp->mLocalCachedFile; + NS_ADDREF(mLocalCachedFile); break; } NS_RELEASE(lp); @@ -877,9 +1073,8 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel) return rv; // save the file. - - mLocalCachedFile = pluginTmp; - // Addref to add one extra refcnt, we can use NS_RELEASE2(mLocalCachedFile...) in dtor + CallQueryInterface(pluginTmp, &mLocalCachedFile); // no need to check return value, just addref + // add one extra refcnt, we can use NS_RELEASE2(mLocalCachedFile...) in dtor // to remove this file when refcnt == 1 NS_ADDREF(mLocalCachedFile); } @@ -979,13 +1174,13 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, mRequestFailed = PR_TRUE; return NS_ERROR_FAILURE; } - mLength = 0; + mPluginStreamInfo->SetLength(PRUint32(0)); } else { - mLength = length; + mPluginStreamInfo->SetLength(length); } - mRequest = request; + mPluginStreamInfo->SetRequest(request); nsCAutoString aContentType; // XXX but we already got the type above! rv = channel->GetContentType(aContentType); @@ -997,15 +1192,17 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, if (NS_FAILED(rv)) return rv; - aURL->GetSpec(mURLSpec); + nsCAutoString urlSpec; + aURL->GetSpec(urlSpec); + mPluginStreamInfo->SetURL(urlSpec.get()); if (!aContentType.IsEmpty()) - mContentType = aContentType; + mPluginStreamInfo->SetContentType(aContentType.get()); #ifdef PLUGIN_LOGGING PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n", - this, request, aContentType.get(), mURLSpec.get())); + this, request, aContentType.get(), urlSpec.get())); PR_LogFlush(); #endif @@ -1020,8 +1217,7 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, // NOTE: we don't want to try again if we didn't get the MIME type this time if (!mInstance && mOwner && !aContentType.IsEmpty()) { - mOwner->GetInstance(getter_AddRefs(mInstance)); - + mOwner->GetInstance(mInstance); mOwner->GetWindow(window); if (!mInstance && window) { nsRefPtr pluginHost = dont_AddRef(nsPluginHost::GetInst()); @@ -1035,7 +1231,8 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner); if (NS_OK == rv) { - mOwner->GetInstance(getter_AddRefs(mInstance)); + // GetInstance() adds a ref + mOwner->GetInstance(mInstance); if (mInstance) { mInstance->Start(); mOwner->CreateWidget(); @@ -1116,13 +1313,13 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, nsresult rv = NS_OK; - if (!mPStreamListener) + if (!mPStreamListener || !mPluginStreamInfo) return NS_ERROR_FAILURE; - mRequest = request; + mPluginStreamInfo->SetRequest(request); const char * url = nsnull; - GetURL(&url); + mPluginStreamInfo->GetURL(&url); PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnDataAvailable this=%p request=%p, offset=%d, length=%d, url=%s\n", @@ -1155,7 +1352,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, NS_PTR_TO_INT32(mDataForwardToRequest->Get(&key)); mDataForwardToRequest->Put(&key, NS_INT32_TO_PTR(amtForwardToPlugin + aLength)); - SetStreamOffset(absoluteOffset + amtForwardToPlugin); + mPluginStreamInfo->SetStreamOffset(absoluteOffset + amtForwardToPlugin); } nsCOMPtr stream = aIStream; @@ -1170,7 +1367,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, return rv; } - rv = mPStreamListener->OnDataAvailable(this, + rv = mPStreamListener->OnDataAvailable(mPluginStreamInfo, stream, aLength); @@ -1259,7 +1456,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, return rv; if (!aContentType.IsEmpty()) - mContentType = aContentType; + mPluginStreamInfo->SetContentType(aContentType.get()); // set error status if stream failed so we notify the plugin if (mRequestFailed) @@ -1268,13 +1465,13 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, if (NS_FAILED(aStatus)) { // on error status cleanup the stream // and return w/o OnFileAvailable() - mPStreamListener->OnStopBinding(this, aStatus); + mPStreamListener->OnStopBinding(mPluginStreamInfo, aStatus); return NS_OK; } // call OnFileAvailable if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly if (mStreamType >= NP_ASFILE) { - nsCOMPtr localFile = mLocalCachedFile; + nsCOMPtr localFile = do_QueryInterface(mLocalCachedFile); if (!localFile) { nsCOMPtr cacheChannel = do_QueryInterface(request); if (cacheChannel) { @@ -1295,17 +1492,15 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, if (mStartBinding) { // On start binding has been called - mPStreamListener->OnStopBinding(this, aStatus); + mPStreamListener->OnStopBinding(mPluginStreamInfo, aStatus); } else { // OnStartBinding hasn't been called, so complete the action. - mPStreamListener->OnStartBinding(this); - mPStreamListener->OnStopBinding(this, aStatus); + mPStreamListener->OnStartBinding(mPluginStreamInfo); + mPStreamListener->OnStopBinding(mPluginStreamInfo, aStatus); } - if (NS_SUCCEEDED(aStatus)) { - mStreamComplete = PR_TRUE; - } - mRequest = NULL; + if (NS_SUCCEEDED(aStatus)) + mPluginStreamInfo->SetStreamComplete(PR_TRUE); return NS_OK; } @@ -1321,7 +1516,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request, // with GetURL or PostURL (i.e. it's the initial stream we // send to the plugin as determined by the SRC or DATA attribute) if (!mPStreamListener && mInstance) - rv = mInstance->NewStreamToPlugin(getter_AddRefs(mPStreamListener)); + rv = mInstance->NewStreamToPlugin(&mPStreamListener); if (NS_FAILED(rv)) return rv; @@ -1379,7 +1574,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request, // Also provide all HTTP response headers to our listener. httpChannel->VisitResponseHeaders(this); - mSeekable = PR_FALSE; + PRBool bSeekable = PR_FALSE; // first we look for a content-encoding header. If we find one, we tell the // plugin that stream is not seekable, because the plugin always sees // uncompressed data, so it can't make meaningful range requests on a @@ -1395,12 +1590,15 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request, // set seekability (seekable if the stream has a known length and if the // http server accepts byte ranges). PRUint32 length; - GetLength(&length); + mPluginStreamInfo->GetLength(&length); if (length) { nsCAutoString range; if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("accept-ranges"), range)) && range.Equals(NS_LITERAL_CSTRING("bytes"), nsCaseInsensitiveCStringComparator())) { - mSeekable = PR_TRUE; + bSeekable = PR_TRUE; + // nsPluginStreamInfo.mSeekable intitialized by PR_FALSE in ctor of nsPluginStreamInfo + // so we reset it only here. + mPluginStreamInfo->SetSeekable(bSeekable); } } } @@ -1416,11 +1614,11 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request, // Convert PRTime to unix-style time_t, i.e. seconds since the epoch double fpTime; LL_L2D(fpTime, time64); - mModified = (PRUint32)(fpTime * 1e-6 + 0.5); + mPluginStreamInfo->SetLastModified((PRUint32)(fpTime * 1e-6 + 0.5)); } } - rv = mPStreamListener->OnStartBinding(this); + rv = mPStreamListener->OnStartBinding(mPluginStreamInfo); mStartBinding = PR_TRUE; @@ -1464,7 +1662,7 @@ nsPluginStreamListenerPeer::OnFileAvailable(nsIFile* aFile) return NS_OK; } - rv = mPStreamListener->OnFileAvailable(this, path.get()); + rv = mPStreamListener->OnFileAvailable(mPluginStreamInfo, path.get()); return rv; } @@ -5173,9 +5371,9 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request, } } - mSeekable = PR_FALSE; - mPStreamListener->OnStartBinding(this); - mStreamOffset = 0; + mPluginStreamInfo->SetSeekable(0); + mPStreamListener->OnStartBinding(mPluginStreamInfo); + mPluginStreamInfo->SetStreamOffset(0); // force the plugin to use stream as file mStreamType = NP_ASFILE; @@ -5311,7 +5509,7 @@ nsPluginByteRangeStreamListener::OnDataAvailable(nsIRequest *request, nsISupport } PRBool -nsPluginStreamListenerPeer::UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi) +nsPluginStreamInfo::UseExistingPluginCacheFile(nsPluginStreamInfo* psi) { NS_ENSURE_ARG_POINTER(psi); @@ -5319,13 +5517,24 @@ nsPluginStreamListenerPeer::UseExistingPluginCacheFile(nsPluginStreamListenerPee if ( psi->mLength == mLength && psi->mModified == mModified && mStreamComplete && - mURLSpec.Equals(psi->mURLSpec)) + !PL_strcmp(psi->mURL, mURL)) { return PR_TRUE; } return PR_FALSE; } +void +nsPluginStreamInfo::SetStreamComplete(const PRBool complete) +{ + mStreamComplete = complete; + + if (complete) { + // We're done, release the request. + SetRequest(nsnull); + } +} + // Runnable that does an async destroy of a plugin. class nsPluginDestroyRunnable : public nsRunnable, diff --git a/modules/plugin/test/testplugin/nptest.cpp b/modules/plugin/test/testplugin/nptest.cpp index 2dcdb80ebbbb..64b96f09f931 100644 --- a/modules/plugin/test/testplugin/nptest.cpp +++ b/modules/plugin/test/testplugin/nptest.cpp @@ -1014,6 +1014,9 @@ NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buf if (err != NPERR_NO_ERROR) { instanceData->err << "Error: NPN_DestroyStream returned " << err; } + if (instanceData->frame.length() > 0) { + sendBufferToFrame(instance); + } } } else {