From 854e1b0716a4150daf804f0de4230875ff24b261 Mon Sep 17 00:00:00 2001 From: "serge%netscape.com" Date: Thu, 29 Aug 2002 22:00:20 +0000 Subject: [PATCH] fix 145054, Plugins may starve when cached data they read from is removed too soon; r=av,sr=darin git-svn-id: svn://10.0.0.236/trunk@128491 18797224-902f-48f8-a5cc-f745e15eee43 --- .../plugin/base/src/nsPluginHostImpl.cpp | 441 ++++++++---------- .../plugin/base/src/nsPluginHostImpl.h | 5 +- 2 files changed, 204 insertions(+), 242 deletions(-) diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index 45b30947a92..a7e37e58980 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -276,6 +276,7 @@ static const char *hashValue = "value"; */ #define NS_MIME_TYPES_HASH_NUM (20) +static nsActivePluginList *gActivePluginList; //////////////////////////////////////////////////////////////////////// void DisplayNoDefaultPluginDialog(const char *mimeType, nsIPrompt *prompt) @@ -485,7 +486,6 @@ nsActivePlugin::nsActivePlugin(nsPluginTag* aPluginTag, mDefaultPlugin = aDefaultPlugin; mStopped = PR_FALSE; mllStopTime = LL_ZERO; - mStreams = new nsVoidArray(); // create a new stream array } @@ -493,14 +493,6 @@ nsActivePlugin::nsActivePlugin(nsPluginTag* aPluginTag, nsActivePlugin::~nsActivePlugin() { mPluginTag = nsnull; - - // free our streams array - if (mStreams) - { - delete mStreams; - mStreams = nsnull; - } - if(mInstance != nsnull) { if(mPeer) @@ -533,24 +525,9 @@ void nsActivePlugin::setStopped(PRBool stopped) { mStopped = stopped; if(mStopped) // plugin instance is told to stop - { mllStopTime = PR_Now(); - - // Since we are "stopped", we should clear our our streams array - if (mStreams) - while (mStreams->Count() > 0 ) // simple loop, always removing the first element - { - nsIStreamListener * s = (nsIStreamListener *) mStreams->ElementAt(0); // XXX nasty cast! - if (s) - { - NS_RELEASE(s); // should cause stream destructions (and prevent leaks!) - mStreams->RemoveElementAt(0); - } - } - } else mllStopTime = LL_ZERO; - } @@ -1287,30 +1264,18 @@ public: void MakeByteRangeString(nsByteRange* aRangeList, nsACString &string, PRInt32 *numRequests); - void - SetLocalCachedFile(nsIFile *file); - - void - GetLocalCachedFile(nsIFile** file); - - void - SetLocalCachedFileStream(nsIOutputStream *stream); - - void - GetLocalCachedFileStream(nsIOutputStream **stream); + PRBool + nsPluginStreamInfo::UseExistingPluginCacheFile(nsPluginStreamInfo* psi, nsIFile* file); private: char* mContentType; char* mURL; - nsCOMPtr mCachedFile; PRBool mSeekable; PRUint32 mLength; PRUint32 mModified; nsIPluginInstance * mPluginInstance; nsPluginStreamListenerPeer * mPluginStreamListenerPeer; - nsCOMPtr mFileCacheOutputStream; - PRBool mLocallyCached; PRInt32 mStreamOffset; }; @@ -1349,8 +1314,6 @@ public: nsILoadGroup* GetLoadGroup(); - nsresult SetLocalFile(nsIFile* aFile); - nsresult ServeStreamAsFile(nsIRequest *request, nsISupports *ctxt); private: @@ -1359,8 +1322,6 @@ private: nsresult SetupPluginCacheFile(nsIChannel* channel); nsIURI *mURL; - - nsIPluginInstanceOwner *mOwner; nsIPluginInstance *mInstance; nsIPluginStreamListener *mPStreamListener; @@ -1384,8 +1345,10 @@ private: nsPluginStreamType mStreamType; nsIPluginHost *mHost; - // local file which was used to post data and which should be deleted after that - nsCOMPtr mLocalFile; + // 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 + nsIFile *mLocalCachedFile; + nsCOMPtr mFileCacheOutputStream; nsHashtable *mDataForwardToRequest; public: @@ -1429,7 +1392,6 @@ nsPluginStreamInfo::nsPluginStreamInfo() mSeekable = PR_FALSE; mLength = 0; mModified = 0; - mLocallyCached = PR_FALSE; mStreamOffset = 0; } @@ -1442,17 +1404,6 @@ nsPluginStreamInfo::~nsPluginStreamInfo() if(mURL != nsnull) PL_strfree(mURL); - // close FD of mFileCacheOutputStream if it's still open - // or we won't be able to remove the cache file - if (mFileCacheOutputStream) - mFileCacheOutputStream->Close(); - - // ONLY delete our cached file if we created it - if(mLocallyCached && mCachedFile) - { - mCachedFile->Remove(PR_FALSE); - } - NS_IF_RELEASE(mPluginInstance); } @@ -1705,42 +1656,6 @@ nsPluginStreamInfo::SetURL(const char* url) mURL = PL_strdup(url); } - -//////////////////////////////////////////////////////////////////////// -void -nsPluginStreamInfo::SetLocalCachedFile(nsIFile* file) -{ - file->Clone(getter_AddRefs(mCachedFile)); -} - - -//////////////////////////////////////////////////////////////////////// -void -nsPluginStreamInfo::GetLocalCachedFile(nsIFile** file) -{ - *file = mCachedFile; - NS_IF_ADDREF(*file); -} - - -//////////////////////////////////////////////////////////////////////// -void -nsPluginStreamInfo::SetLocalCachedFileStream(nsIOutputStream *stream) -{ - mFileCacheOutputStream = stream; - mLocallyCached = PR_TRUE; -} - - -//////////////////////////////////////////////////////////////////////// -void -nsPluginStreamInfo::GetLocalCachedFileStream(nsIOutputStream **stream) -{ - if (!stream) return; - NS_IF_ADDREF(*stream = mFileCacheOutputStream); -} - - //////////////////////////////////////////////////////////////////////// void nsPluginStreamInfo::SetPluginInstance(nsIPluginInstance * aPluginInstance) @@ -1858,6 +1773,7 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer() mPendingRequests = 0; mHaveFiredOnStartRequest = PR_FALSE; mDataForwardToRequest = nsnull; + mLocalCachedFile = nsnull; } @@ -1868,13 +1784,8 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer() nsCAutoString urlSpec; if(mURL != nsnull) (void)mURL->GetSpec(urlSpec); - nsCAutoString filePath; - if(mLocalFile != nsnull) (void)mLocalFile->GetNativePath(filePath); - PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL, - ("nsPluginStreamListenerPeer::dtor this=%p, url=%s, POST_file=%s\n",this, urlSpec.get(), filePath.get())); - - PR_LogFlush(); + ("nsPluginStreamListenerPeer::dtor this=%p, url=%s%c",this, urlSpec.get(), mLocalCachedFile?',':'\n')); #endif NS_IF_RELEASE(mURL); @@ -1884,10 +1795,30 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer() NS_IF_RELEASE(mHost); NS_IF_RELEASE(mPluginStreamInfo); - // if we have mLocalFile (temp file used to post data) it should be - // safe to delete it now, and hopefully the owner doesn't hold it. - if(mLocalFile) - mLocalFile->Remove(PR_FALSE); + // close FD of mFileCacheOutputStream if it's still open + // or we won't be able to remove the cache file + if (mFileCacheOutputStream) + mFileCacheOutputStream = nsnull; + + // if we have mLocalCachedFile lets release it + // and it'll be fiscally remove if refcnt == 1 + if (mLocalCachedFile) { + nsrefcnt refcnt; + NS_RELEASE2(mLocalCachedFile, refcnt); + +#ifdef PLUGIN_LOGGING + nsCAutoString filePath; + mLocalCachedFile->GetNativePath(filePath); + + PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL, + ("LocalyCachedFile=%s has %d refcnt and will %s be deleted now\n",filePath.get(),refcnt,refcnt==1?"":"NOT")); +#endif + + if (refcnt == 1) { + mLocalCachedFile->Remove(PR_FALSE); + NS_RELEASE(mLocalCachedFile); + } + } delete mDataForwardToRequest; } @@ -2037,10 +1968,40 @@ nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIPluginInstance *aInst nsresult nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel) { - nsresult rv; - - // Is this the best place to put this temp file? + nsresult rv = NS_OK; + // lets try to reused a file if we already have in the local plugin cache + // we loop through all of active plugins + // and call |nsPluginStreamInfo::UseExistingPluginCacheFile()| on opened stream + // will return RP_TRUE if file exisrs + // and some conditions are matched, in this case that file will be use + // in |::OnFileAvailable()| calls w/o rewriting the file again. + // The file will be deleted in |nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer| + PRBool useExistingCacheFile = PR_FALSE; + nsActivePlugin *pActivePlugins = gActivePluginList->mFirst; + while (pActivePlugins && pActivePlugins->mStreams && !useExistingCacheFile) { + // most recent streams are at the end of list + PRInt32 cnt; + pActivePlugins->mStreams->Count((PRUint32*)&cnt); + while (--cnt >= 0 && !useExistingCacheFile) { + nsPluginStreamListenerPeer *lp = + NS_REINTERPRET_CAST(nsPluginStreamListenerPeer *, pActivePlugins->mStreams->ElementAt(cnt)); + if (lp) { + if (lp->mLocalCachedFile && + lp->mPluginStreamInfo && + (useExistingCacheFile = + lp->mPluginStreamInfo->UseExistingPluginCacheFile(mPluginStreamInfo,lp->mLocalCachedFile))) + { + NS_ADDREF(mLocalCachedFile = lp->mLocalCachedFile); + } + NS_RELEASE(lp); + } + } + pActivePlugins = pActivePlugins->mNext; + } + + if (!useExistingCacheFile) { nsCOMPtr pluginTmp; + // Is this the best place to put this temp file? rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(pluginTmp)); if (NS_FAILED(rv)) return rv; @@ -2048,7 +2009,7 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel) if (NS_FAILED(rv)) return rv; (void) pluginTmp->Create(nsIFile::DIRECTORY_TYPE,0777); - + // Get the filename from the channel nsCOMPtr uri; rv = channel->GetURI(getter_AddRefs(uri)); @@ -2057,29 +2018,50 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel) nsCOMPtr url(do_QueryInterface(uri)); if(!url) return NS_ERROR_FAILURE; - + nsCAutoString filename; url->GetFileName(filename); - if (NS_FAILED(rv)) return rv; - + if (NS_FAILED(rv)) + return rv; + // Create a file to save our stream into. Should we scramble the name? rv = pluginTmp->AppendNative(filename); - if (NS_FAILED(rv)) return rv; + if (NS_FAILED(rv)) + return rv; // Yes, make it unique. - rv = pluginTmp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0777); - if (NS_FAILED(rv)) return rv; + rv = pluginTmp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); + if (NS_FAILED(rv)) + return rv; - // save the file. - mPluginStreamInfo->SetLocalCachedFile(pluginTmp); - // create a file output stream to write to... nsCOMPtr outstream; - rv = NS_NewLocalFileOutputStream(getter_AddRefs(outstream), pluginTmp, -1, 00600); - if (NS_FAILED(rv)) return rv; + rv = NS_NewLocalFileOutputStream(getter_AddRefs(mFileCacheOutputStream), pluginTmp, -1, 00600); + if (NS_FAILED(rv)) + return rv; - mPluginStreamInfo->SetLocalCachedFileStream(outstream); - return NS_OK; + // save the file. + 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); + } + + // add this listenerPeer to list of stream peers for this instance + // it'll delay release of listenerPeer until nsActivePlugin::~nsActivePlugin + // and the temp file is going to stay alive until then + pActivePlugins = gActivePluginList->find(mInstance); + if (pActivePlugins) { + if (!pActivePlugins->mStreams && + (NS_FAILED(rv = NS_NewISupportsArray(getter_AddRefs(pActivePlugins->mStreams))))) { + return rv; + } + + nsISupports* supports = NS_STATIC_CAST(nsISupports*, (NS_STATIC_CAST(nsIStreamListener*, this))); + pActivePlugins->mStreams->AppendElement(supports); + } + + return rv; } @@ -2111,10 +2093,7 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo // deal with 404 (Not Found) HTTP response, // just return, this causes the request to be ignored. - // Also deal with content-encoding nsCOMPtr httpChannel(do_QueryInterface(channel)); - PRBool useCacheAsFile = PR_TRUE; - if (httpChannel) { PRUint32 responseCode = 0; rv = httpChannel->GetResponseStatus(&responseCode); @@ -2127,17 +2106,6 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo return NS_ERROR_FAILURE; } - // Now we look for a content-encoding header. If we find one, - // we can't use the cache as a file - nsCAutoString contentEncoding; - rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"), - contentEncoding); - if (NS_SUCCEEDED(rv) && - !contentEncoding.Equals("identity", - nsCaseInsensitiveCStringComparator())) { - useCacheAsFile = PR_FALSE; - } - // Get the notification callbacks from the channel and save it as week ref // we'll use it in nsPluginStreamInfo::RequestRead() // when we'll create channel for byte range request. @@ -2152,24 +2120,6 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo mWeakPtrChannelLoadGroup = getter_AddRefs(NS_GetWeakReference(loadGroup)); } - if (useCacheAsFile) { - nsCOMPtr cacheChannel = do_QueryInterface(channel, &rv); - if (cacheChannel) - rv = cacheChannel->SetCacheAsFile(PR_TRUE); - else { - // do not cache if this is a file channel, - // just overwrite rv here - nsCOMPtr fileChannel = do_QueryInterface(channel, &rv); - } - } - - if (!useCacheAsFile || NS_FAILED(rv)) { - // The channel doesn't want to do our bidding, lets cache it to disk ourselves - rv = SetupPluginCacheFile(channel); - if (NS_FAILED(rv)) - NS_WARNING("No Cache Aval. Some plugins wont work OR we don't have a URL"); - } - nsCAutoString aContentType; rv = channel->GetContentType(aContentType); if (NS_FAILED(rv)) @@ -2311,6 +2261,9 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, PRUint32 sourceOffset, PRUint32 aLength) { + if (mRequestFailed) + return NS_ERROR_FAILURE; + if(mAbort) { PRUint32 magicNumber = 0; // set it to something that is not the magic number. @@ -2368,10 +2321,8 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, // the data as the plugin read from the stream. We do this by the magic // of an input stream tee. - nsCOMPtr outStream; - mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream)); - if (outStream) { - rv = NS_NewInputStreamTee(getter_AddRefs(stream), aIStream, outStream); + if (mFileCacheOutputStream) { + rv = NS_NewInputStreamTee(getter_AddRefs(stream), aIStream, mFileCacheOutputStream); if (NS_FAILED(rv)) return rv; } @@ -2393,10 +2344,11 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, rv = aIStream->Read(buffer, aLength, &amountRead); // if we are caching this to disk ourselves, lets write the bytes out. - nsCOMPtr outStream; - mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream)); - while (outStream && amountWrote < amountRead && NS_SUCCEEDED(rv)) - rv = outStream->Write(buffer, amountRead, &amountWrote); + if (mFileCacheOutputStream) { + while (amountWrote < amountRead && NS_SUCCEEDED(rv)) { + rv = mFileCacheOutputStream->Write(buffer, amountRead, &amountWrote); + } + } delete [] buffer; } return rv; @@ -2431,13 +2383,9 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, absoluteOffset)); } else { // if this is not byte range request and - // if we are writting the stream to disk ourselves, lets close it - nsCOMPtr outStream; - mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream)); - if (outStream) { - outStream->Close(); - mPluginStreamInfo->SetLocalCachedFileStream(nsnull); - } + // if we are writting the stream to disk ourselves, + // close & tear it down here + mFileCacheOutputStream = nsnull; } // if we still have pending stuff to do, lets not close the plugin socket. @@ -2481,24 +2429,25 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, return NS_OK; } - nsCOMPtr localFile; - mPluginStreamInfo->GetLocalCachedFile(getter_AddRefs(localFile)); - - if (!localFile) { - nsCOMPtr cacheChannel = do_QueryInterface(request); - if (cacheChannel) { - cacheChannel->GetCacheFile(getter_AddRefs(localFile)); - } else { - // see if it is a file channel. - nsCOMPtr fileChannel = do_QueryInterface(request); - if (fileChannel) { - fileChannel->GetFile(getter_AddRefs(localFile)); + // call OnFileAvailable if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly + if (mStreamType >= nsPluginStreamType_AsFile) { + nsCOMPtr localFile = do_QueryInterface(mLocalCachedFile); + if (!localFile) { + nsCOMPtr cacheChannel = do_QueryInterface(request); + if (cacheChannel) { + cacheChannel->GetCacheFile(getter_AddRefs(localFile)); + } else { + // see if it is a file channel. + nsCOMPtr fileChannel = do_QueryInterface(request); + if (fileChannel) { + fileChannel->GetFile(getter_AddRefs(localFile)); + } } } - } - - if (localFile) { - OnFileAvailable(localFile); + + if (localFile) { + OnFileAvailable(localFile); + } } if (mStartBinding) @@ -2600,26 +2549,44 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request, mStartBinding = PR_TRUE; - if (NS_SUCCEEDED(rv)) { - mPStreamListener->GetStreamType(&mStreamType); - // if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly - // most likely it'll try to check file extension, - // but our cache does nor support it yet. - // temp fix is to copy the file+ext into temp location - // all this code should be deleted when bug 90558 got fixed -#if !defined(CACHE_SUPPOPTS_FILE_EXTENSION) - if (mStreamType >= nsPluginStreamType_AsFile && httpChannel) { - // check out if we already set output stream for this channel - nsCOMPtr outStream; - mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream)); - if (!outStream) { - SetupPluginCacheFile(httpChannel); + if (NS_FAILED(rv)) + return rv; + + mPStreamListener->GetStreamType(&mStreamType); + + // now lets figure out if we have to save the file into plugin local cache + PRBool useLocalCache = PR_FALSE; + if (httpChannel) { + // Now we look for a content-encoding header. If we find one, + // we have to use the local cache, it'll have decoded copy of file + nsCAutoString contentEncoding; + rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"), + contentEncoding); + if (NS_SUCCEEDED(rv) && + !contentEncoding.Equals("identity",nsCaseInsensitiveCStringComparator())) { + useLocalCache = PR_TRUE; + } else if (mStreamType >= nsPluginStreamType_AsFile) { + // if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly + // check out if browser's cache is avalable + nsCOMPtr cacheChannel = do_QueryInterface(httpChannel); + if (cacheChannel && NS_FAILED(cacheChannel->SetCacheAsFile(PR_TRUE))) { + useLocalCache = PR_TRUE; // we'll use local cache } +#if !defined(CACHE_SUPPOPTS_FILE_EXTENSION) + // until bug 90558 got fixed + // and necko cache starts to support file extension + // we'll force to copy the file+ext into local plugin cache + // becase several plugins (e.g. acrobat, quick time) do not work w/o file extension + useLocalCache = PR_TRUE; +#endif + } + + if (useLocalCache) { + SetupPluginCacheFile(httpChannel); } -#endif } - return rv; + return NS_OK; } @@ -2672,22 +2639,6 @@ nsPluginStreamListenerPeer::VisitHeader(const nsACString &header, const nsACStri PromiseFlatCString(value).get()); } - -//////////////////////////////////////////////////////////////////////// -nsresult nsPluginStreamListenerPeer::SetLocalFile(nsIFile* aFile) -{ - NS_ENSURE_ARG_POINTER(aFile); - - if(mLocalFile) - { - NS_ASSERTION(!mLocalFile, "nsPluginStreamListenerPeer::SetLocalFile -- path already set, cleaning..."); - mLocalFile = nsnull; - } - - // clone file to prevent it from being changed out from under us - return aFile->Clone(getter_AddRefs(mLocalFile)); -} - ///////////////////////////////////////////////////////////////////////// nsPluginHostImpl::nsPluginHostImpl() @@ -2700,6 +2651,8 @@ nsPluginHostImpl::nsPluginHostImpl() mAllowAlienStarHandler = PR_FALSE; mUnusedLibraries.Clear(); + gActivePluginList = &mActivePluginList; + // check to see if pref is set at startup to let plugins take over in // full page mode for certain image mime types that we handle internally nsCOMPtr prefs(do_GetService(kPrefServiceCID)); @@ -5644,20 +5597,6 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL, if (NS_SUCCEEDED(rv)) { - // it is possible one plugin instance can request several different - // streams, if we are serving those streams as files from - // temp location (e.g. browser cache is not available) - // we do not have to delete the files until instance is active, - // usually temp files are getting deleted when listener peer is released by OnStopRequest(), - // lets add this listener peer to the to list of stream peers for this instance, - // it'll delay the release until nsActivePlugin::setStopped() call. - nsActivePlugin * p = mActivePluginList.find(aInstance); - if (p && p->mStreams) - { - p->mStreams->AppendElement((void *)listenerPeer); - NS_ADDREF(listenerPeer); - } - nsCOMPtr callbacks; if (doc) @@ -5917,10 +5856,10 @@ nsresult nsPluginHostImpl::NewFullPagePluginStream(nsIStreamListener *&aStreamLi // add peer to list of stream peers for this instance nsActivePlugin * p = mActivePluginList.find(aInstance); - if (p && p->mStreams) - { - p->mStreams->AppendElement((void *)aStreamListener); - NS_ADDREF(listener); + if (p) { + if (!p->mStreams && (NS_FAILED(rv = NS_NewISupportsArray(getter_AddRefs(p->mStreams))))) + return rv; + p->mStreams->AppendElement(aStreamListener); } return rv; @@ -6381,7 +6320,7 @@ nsPluginHostImpl::CreateTmpFileToPost(const char *postDataURL, char **pTmpFileNa PRBool dirExists; tempFile->Exists(&dirExists); if (!dirExists) - (void) tempFile->Create(nsIFile::DIRECTORY_TYPE, 0600); + (void) tempFile->Create(nsIFile::DIRECTORY_TYPE, 0777); nsCAutoString inFileName; inFile->GetNativeLeafName(inFileName); @@ -6554,15 +6493,11 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request, mPluginStreamInfo->SetSeekable(0); mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo); mPluginStreamInfo->SetStreamOffset(0); + mStreamType = nsPluginStreamType_AsFile; #if !defined(CACHE_SUPPOPTS_FILE_EXTENSION) - // check out if we already saving the stream into plugins cache - nsCOMPtr outStream; - mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream)); - if (outStream) { - outStream->Close(); - mPluginStreamInfo->SetLocalCachedFileStream(nsnull); - } + // close & tear down existing cached stream + mFileCacheOutputStream = nsnull; nsCOMPtr channel = do_QueryInterface(request); nsCOMPtr httpChannel = do_QueryInterface(channel); @@ -6682,3 +6617,29 @@ nsPluginByteRangeStreamListener::OnDataAvailable(nsIRequest *request, nsISupport return mStreamConverter->OnDataAvailable(request, ctxt, inStr, sourceOffset, count); } + +PRBool +nsPluginStreamInfo::UseExistingPluginCacheFile(nsPluginStreamInfo* psi, nsIFile* file) +{ + + NS_ENSURE_ARG_POINTER(psi); + + if ( psi->mLength == mLength && + psi->mModified == mModified && + !PL_strcmp(psi->mURL, mURL)) + { + if (psi->mLength != (PRUint32) mStreamOffset) { //lets check a file size + PRInt64 size; + if (NS_FAILED(file->GetFileSize(&size))) + return PR_FALSE; + + PRUint32 fs = nsInt64(size); + if (psi->mLength != fs) { + return PR_FALSE; + } + } + return PR_TRUE; + } + return PR_FALSE; +} + diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h index ff46153d7d0..4c853a16925 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h @@ -54,6 +54,7 @@ #include "nsWeakPtr.h" #include "nsIPrompt.h" #include "nsIGenericFactory.h" +#include "nsISupportsArray.h" class ns4xPlugin; class nsFileSpec; @@ -62,7 +63,6 @@ class nsIFile; class nsIChannel; class nsIRegistry; class nsPluginHostImpl; -class nsISupportsArray; /** * A linked-list of plugin information that is used for @@ -123,7 +123,8 @@ struct nsActivePlugin PRTime mllStopTime; PRBool mDefaultPlugin; PRBool mXPConnected; - nsVoidArray* mStreams; + //Array holding all opened stream listeners for this entry + nsCOMPtr mStreams; nsActivePlugin(nsPluginTag* aPluginTag, nsIPluginInstance* aInstance,