зеркало из https://github.com/mozilla/pjs.git
fix 145054, Plugins may starve when cached data they read from is removed too soon; r=av,sr=darin
This commit is contained in:
Родитель
be187d5e77
Коммит
1b4cdd623a
|
@ -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<nsIFile> mCachedFile;
|
||||
PRBool mSeekable;
|
||||
PRUint32 mLength;
|
||||
PRUint32 mModified;
|
||||
nsIPluginInstance * mPluginInstance;
|
||||
nsPluginStreamListenerPeer * mPluginStreamListenerPeer;
|
||||
nsCOMPtr<nsIOutputStream> 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<nsIFile> 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<nsIOutputStream> 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<nsIFile> 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<nsIURI> uri;
|
||||
rv = channel->GetURI(getter_AddRefs(uri));
|
||||
|
@ -2057,29 +2018,50 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
|
|||
nsCOMPtr<nsIURL> 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<nsIOutputStream> 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<nsIHttpChannel> 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<nsICachingChannel> 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<nsIFileChannel> 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<nsIOutputStream> 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<nsIOutputStream> 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<nsIOutputStream> 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<nsIFile> localFile;
|
||||
mPluginStreamInfo->GetLocalCachedFile(getter_AddRefs(localFile));
|
||||
|
||||
if (!localFile) {
|
||||
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
|
||||
if (cacheChannel) {
|
||||
cacheChannel->GetCacheFile(getter_AddRefs(localFile));
|
||||
} else {
|
||||
// see if it is a file channel.
|
||||
nsCOMPtr<nsIFileChannel> 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<nsIFile> localFile = do_QueryInterface(mLocalCachedFile);
|
||||
if (!localFile) {
|
||||
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
|
||||
if (cacheChannel) {
|
||||
cacheChannel->GetCacheFile(getter_AddRefs(localFile));
|
||||
} else {
|
||||
// see if it is a file channel.
|
||||
nsCOMPtr<nsIFileChannel> 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<nsIOutputStream> 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<nsICachingChannel> 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<nsIPref> 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<nsIInterfaceRequestor> 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<nsIOutputStream> outStream;
|
||||
mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream));
|
||||
if (outStream) {
|
||||
outStream->Close();
|
||||
mPluginStreamInfo->SetLocalCachedFileStream(nsnull);
|
||||
}
|
||||
// close & tear down existing cached stream
|
||||
mFileCacheOutputStream = nsnull;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
nsCOMPtr<nsIHttpChannel> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <nsISupportsArray> mStreams;
|
||||
|
||||
nsActivePlugin(nsPluginTag* aPluginTag,
|
||||
nsIPluginInstance* aInstance,
|
||||
|
|
Загрузка…
Ссылка в новой задаче