diff --git a/mozilla/modules/plugin/base/public/MANIFEST b/mozilla/modules/plugin/base/public/MANIFEST index 25692025ec3..510f94a6ffb 100644 --- a/mozilla/modules/plugin/base/public/MANIFEST +++ b/mozilla/modules/plugin/base/public/MANIFEST @@ -45,7 +45,6 @@ nsplugin.h nsplugindefs.h nsICookieStorage.h nsIPluginStreamListener.h -nsIPluginStreamListener2.h nsIPluginStreamInfo.h nsIPluginInputStream.h nsIPluginInputStream2.h diff --git a/mozilla/modules/plugin/base/public/Makefile.in b/mozilla/modules/plugin/base/public/Makefile.in index e7c312f288f..f8f80134663 100644 --- a/mozilla/modules/plugin/base/public/Makefile.in +++ b/mozilla/modules/plugin/base/public/Makefile.in @@ -46,7 +46,6 @@ EXPORTS = \ nsIPluginTagInfo2.h \ nsIWindowlessPlugInstPeer.h \ nsIPluginInputStream.h \ - nsIPluginInputStream2.h \ nsIPluginStreamListener.h \ nsIPluginStreamListener2.h \ nsIPluginStreamInfo.h \ diff --git a/mozilla/modules/plugin/base/public/makefile.win b/mozilla/modules/plugin/base/public/makefile.win index 1728c887944..b50c0d9955a 100644 --- a/mozilla/modules/plugin/base/public/makefile.win +++ b/mozilla/modules/plugin/base/public/makefile.win @@ -34,7 +34,6 @@ EXPORTS = \ nsIPluginTagInfo2.h \ nsIWindowlessPlugInstPeer.h \ nsIPluginStreamListener.h \ - nsIPluginStreamListener2.h \ nsIPluginStreamInfo.h \ nsplugin.h \ nsplugindefs.h \ diff --git a/mozilla/modules/plugin/base/public/nsIPluginStreamInfo.h b/mozilla/modules/plugin/base/public/nsIPluginStreamInfo.h index 32d6220c969..979e89f8634 100644 --- a/mozilla/modules/plugin/base/public/nsIPluginStreamInfo.h +++ b/mozilla/modules/plugin/base/public/nsIPluginStreamInfo.h @@ -72,6 +72,12 @@ public: NS_IMETHOD RequestRead(nsByteRange* rangeList) = 0; + + NS_IMETHOD + GetStreamOffset(PRInt32 *aStreamOffset) = 0; + + NS_IMETHOD + SetStreamOffset(PRInt32 aStreamOffset) = 0; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp index 65d8f02f06b..fa22f95aff0 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp @@ -64,7 +64,6 @@ static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); // needed for NS_TRY_SAFE_CALL_* static NS_DEFINE_IID(kCPluginManagerCID, NS_PLUGINMANAGER_CID); static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID); -static NS_DEFINE_IID(kIPluginStreamListener2IID, NS_IPLUGINSTREAMLISTENER2_IID); static NS_DEFINE_IID(kIPluginInstanceIID, NS_IPLUGININSTANCE_IID); static NS_DEFINE_IID(kIPluginTagInfoIID, NS_IPLUGINTAGINFO_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -72,8 +71,7 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); /////////////////////////////////////////////////////////////////////////////// // ns4xPluginStreamListener Methods -NS_IMPL_ISUPPORTS2(ns4xPluginStreamListener, nsIPluginStreamListener, - nsIPluginStreamListener2); +NS_IMPL_ISUPPORTS1(ns4xPluginStreamListener, nsIPluginStreamListener); /////////////////////////////////////////////////////////////////////////////// @@ -89,7 +87,7 @@ ns4xPluginStreamListener::ns4xPluginStreamListener(nsIPluginInstance* inst, mInst = (ns4xPluginInstance*) inst; mStreamBuffer=nsnull; mPosition = 0; - mCurrentStreamOffset = -1; + mStreamBufferSize = 0; // Initialize the 4.x interface structure memset(&mNPStream, 0, sizeof(mNPStream)); @@ -123,6 +121,14 @@ ns4xPluginStreamListener::~ns4xPluginStreamListener(void) // cases, notify should have already been called for other reasons elsewhere. CallURLNotify(NPRES_NETWORK_ERR); + // lets get rid of the buffer + if (mStreamBuffer) + { + PR_Free(mStreamBuffer); + mStreamBuffer=nsnull; + } + + NS_IF_RELEASE(inst); } @@ -163,13 +169,6 @@ nsresult ns4xPluginStreamListener::CleanUpStream(NPReason reason) rv = NS_OK; } - // lets get rid of the buffer if we made one globally - if (mStreamBuffer) - { - PR_Free(mStreamBuffer); - mStreamBuffer=nsnull; - } - mStreamCleanedUp = PR_TRUE; mStreamStarted = PR_FALSE; @@ -286,297 +285,179 @@ ns4xPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo) return NS_ERROR_FAILURE; } - // create buffer for stream here because we know the size - mStreamBuffer = (char*) PR_Malloc((PRUint32)MAX_PLUGIN_NECKO_BUFFER); - if (!mStreamBuffer) - { - NS_ASSERTION(PR_FALSE,"failed to create 4.x plugin stream buffer or size MAX_PLUGIN_NECKO_BUFFER"); - return NS_ERROR_OUT_OF_MEMORY; - } - mStreamStarted = PR_TRUE; return NS_OK; } - /////////////////////////////////////////////////////////////////////////////// NS_IMETHODIMP ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length) { + nsresult rv = NS_ERROR_FAILURE; if (!mInst || !mInst->IsStarted()) - return NS_ERROR_FAILURE; + return rv; const NPPluginFuncs *callbacks = nsnull; - NPP npp; - mInst->GetCallbacks(&callbacks); + // check out if plugin implements NPP_Write call + if(!callbacks || !callbacks->write || !length) + return rv; // it'll cancel necko transaction + + if (!mStreamBuffer) + { + // to optimize the mem usage & performance we have to allocate mStreamBuffer here + // in first ODA when length of data available in input stream is known. + // mStreamBuffer will be freed in DTOR. + // we also have to remember the size of that buff + // to make safe consecutive Read() calls form input stream into our buff. + if (length >= MAX_PLUGIN_NECKO_BUFFER) { + // ">" is rare case for decoded stream, but lets eat it all + mStreamBufferSize = length; + } else { + PRUint32 contentLength; + pluginInfo->GetLength(&contentLength); + if (contentLength < MAX_PLUGIN_NECKO_BUFFER) { + // this is most common case for contentLength < 16k + mStreamBufferSize = length < contentLength ? contentLength:length; + } else { + mStreamBufferSize = MAX_PLUGIN_NECKO_BUFFER; + } + } + mStreamBuffer = (char*) PR_Malloc(mStreamBufferSize); + if (!mStreamBuffer) + return NS_ERROR_OUT_OF_MEMORY; + } + + // prepare NPP_ calls params + NPP npp; mInst->GetNPP(&npp); - - if(!callbacks) - return NS_ERROR_FAILURE; - - PRInt32 numtowrite = 0; - PRInt32 amountRead = 0; - PRInt32 writeCount = 0; - PRUint32 leftToRead = 0; // just in case OnDataaAvail tries to overflow our buffer - PRBool createdHere = PR_FALSE; // we did malloc in locally, so we must free locally - pluginInfo->GetURL(&mNPStream.url); pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified)); - if (callbacks->write == nsnull || length == 0) - return NS_OK; // XXX ? + PRInt32 streamOffset; + pluginInfo->GetStreamOffset(&streamOffset); + mPosition = streamOffset; + streamOffset += length; + // Set new stream offset for the next ODA call + // regardless of how following NPP_Write call will behave + // we pretend to consume all data from the input stream. + // It's possible that current steam position will be overwritten + // from NPP_RangeRequest call made from NPP_Write, so + // we cannot call SetStreamOffset after NPP_Write. + // Note: there is a special case when data flow + // should be temporarily stopped if NPP_WriteReady returns 0 (bug #89270) + pluginInfo->SetStreamOffset(streamOffset); - if (nsnull == mStreamBuffer) - { - // create the buffer here because we failed in OnStartBinding - // XXX why don't we always get an OnStartBinding? This will protect us. - mStreamBuffer = (char*) PR_Malloc(length); - if (!mStreamBuffer) - return NS_ERROR_OUT_OF_MEMORY; - createdHere = PR_TRUE; + PRUint32 bytesToRead = mStreamBufferSize; + if (length < mStreamBufferSize) { + // do not read more that supplier wants us to read + bytesToRead = length; } - if (length > MAX_PLUGIN_NECKO_BUFFER) // what if Necko gives us a lot of data? + do { - leftToRead = length - MAX_PLUGIN_NECKO_BUFFER; // break it up - length = MAX_PLUGIN_NECKO_BUFFER; - } - nsresult rv = input->Read(mStreamBuffer, length, (PRUint32*)&amountRead); - if (NS_FAILED(rv)) - goto error; + PRInt32 amountRead = 0; + rv = input->Read(mStreamBuffer, bytesToRead, (PRUint32*)&amountRead); + if (amountRead == 0 || NS_FAILED(rv)) { + NS_WARNING("input->Read() returns no data, it's almost impossible to get here"); + break; + } - // amountRead tells us how many bytes were put in the buffer - // WriteReady returns to us how many bytes the plugin is - // ready to handle - we have to keep calling WriteReady and - // Write until the buffer is empty - while (amountRead > 0) - { - if (callbacks->writeready != NULL) - { - PRLibrary* lib = nsnull; - lib = mInst->fLibrary; + // this loop in general case will end on length <= 0, without extra input->Read() call + length -= amountRead; + + char *ptrStreamBuffer = mStreamBuffer; // tmp ptr - NS_TRY_SAFE_CALL_RETURN(numtowrite, CallNPP_WriteReadyProc(callbacks->writeready, - npp, - &mNPStream), lib); - - NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, - ("NPP WriteReady called: this=%p, npp=%p, return(towrite)=%d, url=%s\n", - this, npp, numtowrite, mNPStream.url)); - - // if WriteReady returned 0, the plugin is not ready to handle - // the data, return FAILURE for now - if (numtowrite <= 0) { - NS_ASSERTION(numtowrite,"WriteReady returned Zero"); - rv = NS_ERROR_FAILURE; - goto error; + // it is possible plugin's NPP_Write() returns 0 byte consumed + // we use zeroBytesWriteCount to count situation like this + // and break the loop + PRInt32 zeroBytesWriteCount = 0; + + // amountRead tells us how many bytes were put in the buffer + // WriteReady returns to us how many bytes the plugin is + // ready to handle - we have to keep calling WriteReady and + // Write until amountRead > 0 + for(;;) + { // it breaks on (amountRead <= 0) or on error + PRInt32 numtowrite; + if (callbacks->writeready) + { + NS_TRY_SAFE_CALL_RETURN(numtowrite, + CallNPP_WriteReadyProc(callbacks->writeready, npp, &mNPStream), + mInst->fLibrary); + + NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, + ("NPP WriteReady called: this=%p, npp=%p, return(towrite)=%d, url=%s\n", + this, npp, numtowrite, mNPStream.url)); + + // if WriteReady returned 0, the plugin is not ready to handle + // the data, return FAILURE for now + if (numtowrite <= 0) { + NS_ASSERTION(numtowrite,"WriteReady returned Zero"); + rv = NS_ERROR_FAILURE; + break; + } + if (numtowrite > amountRead) + numtowrite = amountRead; } - - if (numtowrite > amountRead) + else + { + // if WriteReady is not supported by the plugin, + // just write the whole buffer numtowrite = amountRead; - } - else - { - // if WriteReady is not supported by the plugin, - // just write the whole buffer - numtowrite = length; - } - - if (numtowrite > 0) - { - NS_TRY_SAFE_CALL_RETURN(writeCount, CallNPP_WriteProc(callbacks->write, - npp, - &mNPStream, - mPosition, - numtowrite, - (void *)mStreamBuffer), mInst->fLibrary); - - NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, - ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, buf=%s, return(written)=%d, url=%s\n", - this, npp, mPosition, numtowrite, (char *)mStreamBuffer, writeCount, mNPStream.url)); - - if (writeCount < 0) { - rv = NS_ERROR_FAILURE; - goto error; } - - amountRead -= writeCount; - mPosition += writeCount; - if (amountRead > 0) - memmove(mStreamBuffer,mStreamBuffer+writeCount,amountRead); - } - } - - rv = NS_OK; - -error: - if (PR_TRUE == createdHere) // cleanup buffer if we made it locally - { - PR_Free(mStreamBuffer); - mStreamBuffer=nsnull; - } - - if (leftToRead > 0) // if we have more to read in this pass, do it recursively - { - OnDataAvailable(pluginInfo, input, leftToRead); - } + + PRInt32 writeCount = 0; // bytes consumed by plugin instance + + NS_TRY_SAFE_CALL_RETURN(writeCount, + CallNPP_WriteProc(callbacks->write, npp, &mNPStream, mPosition, numtowrite, (void *)ptrStreamBuffer), + mInst->fLibrary); + + NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, + ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, buf=%s, return(written)=%d, url=%s\n", + this, npp, mPosition, numtowrite, (char *)ptrStreamBuffer, writeCount, mNPStream.url)); + + if (writeCount > 0) + { + mPosition += writeCount; + amountRead -= writeCount; + if (amountRead <= 0) + break; // in common case we'll break for(;;) loop here + + zeroBytesWriteCount = 0; + if (writeCount % sizeof(long)) { + // memmove will take care about alignment + memmove(ptrStreamBuffer,ptrStreamBuffer+writeCount,amountRead); + } else { + // if aligned we can use ptrStreamBuffer += to eliminate memmove() + ptrStreamBuffer += writeCount; + } + } + else if (writeCount == 0) + { + // if NPP_Write() returns writeCount == 0 lets say 3 times in a raw + // lets consider this as end of ODA call (plugin isn't hungry, or broken) without an error. + if (++zeroBytesWriteCount == 3) + { + length = 0; // break do{}while + rv = NS_OK; + break; + } + } + else + { + length = 0; // break do{}while + rv = NS_ERROR_FAILURE; + break; + } + } // end of for(;;) + } while ((PRInt32)(length) > 0); return rv; } - -/////////////////////////////////////////////////////////////////////////////// -NS_IMETHODIMP -ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo, - nsIInputStream* input, - PRUint32 sourceOffset, - PRUint32 length) -{ - if (!mInst || !mInst->IsStarted()) - return NS_ERROR_FAILURE; - - const NPPluginFuncs *callbacks = nsnull; - NPP npp; - - mInst->GetCallbacks(&callbacks); - mInst->GetNPP(&npp); - - if(!callbacks) - return NS_ERROR_FAILURE; - - PRInt32 numtowrite = 0; - PRInt32 amountRead = 0; - PRInt32 writeCount = 0; - PRUint32 leftToRead = 0; // just in case OnDataaAvail tries to overflow our buffer - PRBool createdHere = PR_FALSE; // we did malloc in locally, so we must free locally - - // if we are getting a range request, reset mPosition. - if (sourceOffset != mCurrentStreamOffset || - mCurrentStreamOffset == -1 ) - { - mPosition = 0; - mCurrentStreamOffset = sourceOffset; - } - - pluginInfo->GetURL(&mNPStream.url); - pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified)); - - if (callbacks->write == nsnull || length == 0) - return NS_OK; // XXX ? - - if (nsnull == mStreamBuffer) - { - // create the buffer here because we failed in OnStartBinding - // XXX why don't we always get an OnStartBinding? This will protect us. - mStreamBuffer = (char*) PR_Malloc(length); - if (!mStreamBuffer) - return NS_ERROR_OUT_OF_MEMORY; - createdHere = PR_TRUE; - } - - if (length > MAX_PLUGIN_NECKO_BUFFER) // what if Necko gives us a lot of data? - { - leftToRead = length - MAX_PLUGIN_NECKO_BUFFER; // break it up - length = MAX_PLUGIN_NECKO_BUFFER; - } - nsresult rv = input->Read(mStreamBuffer, length, (PRUint32*)&amountRead); - if (NS_FAILED(rv)) - goto error; - - // amountRead tells us how many bytes were put in the buffer - // WriteReady returns to us how many bytes the plugin is - // ready to handle - we have to keep calling WriteReady and - // Write until the buffer is empty - while (amountRead > 0) - { - if (callbacks->writeready != NULL) - { - PRLibrary* lib = nsnull; - lib = mInst->fLibrary; - - NS_TRY_SAFE_CALL_RETURN(numtowrite, CallNPP_WriteReadyProc(callbacks->writeready, - npp, - &mNPStream), lib); - - NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, - ("NPP WriteReady called: this=%p, npp=%p, return(towrite)=%d, url=%s\n", - this, npp, numtowrite, mNPStream.url)); - - // if WriteReady returned 0, the plugin is not ready to handle - // the data, return FAILURE for now - if (numtowrite <= 0) { - rv = NS_ERROR_FAILURE; - goto error; - } - - if (numtowrite > amountRead) - numtowrite = amountRead; - } - else - { - // if WriteReady is not supported by the plugin, - // just write the whole buffer - numtowrite = length; - } - - if (numtowrite > 0) - { -#if 0 // useful for debugging problems with byte range buffers - printf("> %d - %d \n", sourceOffset + writeCount + mPosition, numtowrite); - nsCString x; - x.Append("d:\\parts\\"); - x.AppendInt(sourceOffset); - - PRFileDesc* fd; - fd = PR_Open(x, PR_CREATE_FILE |PR_SYNC| PR_APPEND | PR_RDWR, 777); - PR_Write(fd, mStreamBuffer, numtowrite); - PR_Close(fd); -#endif - - NS_TRY_SAFE_CALL_RETURN(writeCount, CallNPP_WriteProc(callbacks->write, - npp, - &mNPStream, - sourceOffset + writeCount + mPosition, - numtowrite, - (void *)mStreamBuffer), mInst->fLibrary); - - NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, - ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, buf=%s, return(written)=%d, url=%s\n", - this, npp, mPosition, numtowrite, (char *)mStreamBuffer, writeCount, mNPStream.url)); - - if (writeCount < 0) { - rv = NS_ERROR_FAILURE; - goto error; - } - - if (sourceOffset == 0) - mPosition += numtowrite; - - amountRead -= numtowrite; - } - } - - rv = NS_OK; - -error: - if (PR_TRUE == createdHere) // cleanup buffer if we made it locally - { - PR_Free(mStreamBuffer); - mStreamBuffer=nsnull; - } - - if (leftToRead > 0) // if we have more to read in this pass, do it recursively - { - OnDataAvailable(pluginInfo, input, sourceOffset, leftToRead); - } - - return rv; -} - - /////////////////////////////////////////////////////////////////////////////// NS_IMETHODIMP ns4xPluginStreamListener::OnFileAvailable(nsIPluginStreamInfo* pluginInfo, @@ -798,7 +679,7 @@ NS_IMETHODIMP ns4xPluginInstance::Stop(void) if (fCallbacks->destroy == NULL) return NS_ERROR_FAILURE; // XXX right error? - NPSavedData *sdata; + NPSavedData *sdata = 0; // clean up open streams for(nsInstanceStream *is = mStreams; is != nsnull;) { diff --git a/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h b/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h index 238ac477fff..0837c916779 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h +++ b/mozilla/modules/plugin/base/src/ns4xPluginStreamListener.h @@ -38,27 +38,23 @@ #ifndef ns4xPluginStreamListener_h__ #define ns4xPluginStreamListener_h__ -#include "nsIPluginStreamListener2.h" +#include "nsIPluginStreamListener.h" #include "nsIPluginStreamInfo.h" #define MAX_PLUGIN_NECKO_BUFFER 16384 -class ns4xPluginStreamListener : public nsIPluginStreamListener2 +class ns4xPluginStreamListener : public nsIPluginStreamListener { public: NS_DECL_ISUPPORTS // from nsIPluginStreamListener: NS_IMETHOD OnStartBinding(nsIPluginStreamInfo* pluginInfo); - NS_IMETHOD OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length, PRUint32 offset); + NS_IMETHOD OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length); NS_IMETHOD OnFileAvailable( nsIPluginStreamInfo* pluginInfo, const char* fileName); NS_IMETHOD OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status); NS_IMETHOD GetStreamType(nsPluginStreamType *result); - NS_IMETHOD OnDataAvailable(nsIPluginStreamInfo* pluginInfo, - nsIInputStream* input, - PRUint32 length); - // ns4xPluginStreamListener specific methods: ns4xPluginStreamListener(nsIPluginInstance* inst, void* notifyData); virtual ~ns4xPluginStreamListener(); @@ -73,7 +69,7 @@ protected: ns4xPluginInstance* mInst; NPStream mNPStream; PRUint32 mPosition; - PRUint32 mCurrentStreamOffset; + PRUint32 mStreamBufferSize; nsPluginStreamType mStreamType; PRBool mStreamStarted; PRBool mStreamCleanedUp; diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index 25288c1d513..d05f2f4984f 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -65,7 +65,6 @@ #include "nsIStreamListener.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" -#include "nsIPluginStreamListener2.h" #include "nsIURL.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" @@ -1140,6 +1139,12 @@ public: NS_IMETHOD RequestRead(nsByteRange* rangeList); + + NS_IMETHOD + GetStreamOffset(PRInt32 *result); + + NS_IMETHOD + SetStreamOffset(PRInt32 result); // local methods @@ -1191,6 +1196,7 @@ private: nsPluginStreamListenerPeer * mPluginStreamListenerPeer; nsCOMPtr mFileCacheOutputStream; PRBool mLocallyCached; + PRInt32 mStreamOffset; }; @@ -1286,6 +1292,7 @@ nsPluginStreamInfo::nsPluginStreamInfo() mLength = 0; mModified = 0; mLocallyCached = PR_FALSE; + mStreamOffset = 0; } @@ -1297,6 +1304,11 @@ 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 && mFilePath) { @@ -1431,8 +1443,14 @@ nsPluginStreamInfo::MakeByteRangeString(nsByteRange* aRangeList, nsACString &ran //////////////////////////////////////////////////////////////////////// NS_IMETHODIMP nsPluginStreamInfo::RequestRead(nsByteRange* rangeList) -{ - mPluginStreamListenerPeer->mAbort = PR_TRUE; +{ + nsCAutoString rangeString; + PRInt32 numRequests; + + MakeByteRangeString(rangeList, rangeString, &numRequests); + + if(numRequests == 0) + return NS_ERROR_FAILURE; nsresult rv = NS_OK; nsCOMPtr url; @@ -1448,18 +1466,12 @@ nsPluginStreamInfo::RequestRead(nsByteRange* rangeList) if(!httpChannel) return NS_ERROR_FAILURE; - nsCAutoString rangeString; - PRInt32 numRequests; - - MakeByteRangeString(rangeList, rangeString, &numRequests); - - if(rangeString.IsEmpty()) - return NS_ERROR_FAILURE; httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString); + - // instruct old stream listener to cancel the request on the next - // attempt to write. + mPluginStreamListenerPeer->mAbort = PR_TRUE; // instruct old stream listener to cancel + // the request on the next ODA. nsCOMPtr converter = mPluginStreamListenerPeer; @@ -1477,6 +1489,11 @@ nsPluginStreamInfo::RequestRead(nsByteRange* rangeList) return rv; } + // 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); + mPluginStreamListenerPeer->mPendingRequests += numRequests; nsCOMPtr container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv); @@ -1487,6 +1504,20 @@ nsPluginStreamInfo::RequestRead(nsByteRange* rangeList) return channel->AsyncOpen(converter, container); } +NS_IMETHODIMP +nsPluginStreamInfo::GetStreamOffset(PRInt32 *result) +{ + *result = mStreamOffset; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +NS_IMETHODIMP +nsPluginStreamInfo::SetStreamOffset(PRInt32 offset) +{ + mStreamOffset = offset; + return NS_OK; +} //////////////////////////////////////////////////////////////////////// void @@ -1981,6 +2012,11 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo 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)) { @@ -2142,7 +2178,6 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, } } - nsresult rv = NS_OK; nsCOMPtr aURL; nsCOMPtr channel = do_QueryInterface(request); @@ -2184,6 +2219,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, amtForwardToPlugin = NS_PTR_TO_INT32(mDataForwardToRequest->Remove(&key)); mDataForwardToRequest->Put(&key, (void*) (amtForwardToPlugin+aLength)); + mPluginStreamInfo->SetStreamOffset(absoluteOffset + amtForwardToPlugin); } nsCOMPtr stream = aIStream; @@ -2200,14 +2236,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, return rv; } - nsCOMPtr PStreamListener2 = do_QueryInterface(mPStreamListener); - if (PStreamListener2 && brr) - rv = PStreamListener2->OnDataAvailable((nsIPluginStreamInfo*)mPluginStreamInfo, - stream, - absoluteOffset+amtForwardToPlugin, - aLength); - else - rv = mPStreamListener->OnDataAvailable((nsIPluginStreamInfo*)mPluginStreamInfo, + rv = mPStreamListener->OnDataAvailable((nsIPluginStreamInfo*)mPluginStreamInfo, stream, aLength); @@ -2240,48 +2269,36 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, nsresult aStatus) { nsresult rv = NS_OK; - nsCOMPtr cacheChannel = do_QueryInterface(request); - nsCOMPtr localFile; - nsXPIDLCString pathAndFilename; - - // doing multiple requests, the main url load (the cacheable entry) could come - // out of order. Here we will check to see if the request is main url load. - - mPluginStreamInfo->GetLocalCachedFile(getter_Copies(pathAndFilename)); - - if (!pathAndFilename && cacheChannel) { - rv = cacheChannel->GetCacheFile(getter_AddRefs(localFile)); - if (NS_SUCCEEDED(rv)) { - localFile->GetPath(getter_Copies(pathAndFilename)); - mPluginStreamInfo->SetLocalCachedFile(pathAndFilename); - } - } PLUGIN_LOG(PLUGIN_LOG_NOISY, - ("nsPluginStreamListenerPeer::OnStopRequest this=%p aStatus=%d request=%p, cachefile=%s\n", - this, aStatus, request, pathAndFilename.get())); - - // If we are writting the stream to disk ourselves, lets close it - nsCOMPtr outStream; - mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream)); - if (outStream) { - outStream->Close(); - } - - // remove the request from our data forwarding count hash. + ("nsPluginStreamListenerPeer::OnStopRequest this=%p aStatus=%d request=%p\n", + this, aStatus, request)); + + // for ByteRangeRequest we're just updating the mDataForwardToRequest hash and return. nsCOMPtr brr = do_QueryInterface(request); if (brr) { PRInt32 absoluteOffset = 0; brr->GetStartRange(&absoluteOffset); nsPRUintKey key(absoluteOffset); - - if (!mDataForwardToRequest) - return NS_ERROR_FAILURE; + // remove the request from our data forwarding count hash. (void) mDataForwardToRequest->Remove(&key); - } + + PLUGIN_LOG(PLUGIN_LOG_NOISY, + (" ::OnStopRequest for ByteRangeRequest Started=%d\n", + 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 still have pending stuff to do, lets not close the plugin socket. if (--mPendingRequests > 0) @@ -2301,21 +2318,6 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, if(!mPStreamListener) return NS_ERROR_FAILURE; - - if (!pathAndFilename) { - // see if it is a file channel. - nsCOMPtr fileChannel = do_QueryInterface(request); - if (fileChannel) { - fileChannel->GetFile(getter_AddRefs(localFile)); - if (localFile) { - localFile->GetPath(getter_Copies(pathAndFilename)); - mPluginStreamInfo->SetLocalCachedFile(pathAndFilename); - } - } - } - - if (pathAndFilename && *pathAndFilename) - OnFileAvailable(pathAndFilename); nsCOMPtr aURL; nsCOMPtr channel = do_QueryInterface(request); @@ -2344,8 +2346,38 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, if (mRequestFailed) aStatus = NS_ERROR_FAILURE; - // on error status cleanup the stream - if (mStartBinding || NS_FAILED(aStatus)) + if (NS_FAILED(aStatus)) { + // on error status cleanup the stream + // and return w/o OnFileAvailable() + mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus); + return NS_OK; + } + + nsXPIDLCString pathAndFilename; + mPluginStreamInfo->GetLocalCachedFile(getter_Copies(pathAndFilename)); + + if (!pathAndFilename) { + nsCOMPtr 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) { + localFile->GetPath(getter_Copies(pathAndFilename)); + } + } + + if (pathAndFilename && *pathAndFilename) { + OnFileAvailable(pathAndFilename); + } + + if (mStartBinding) { // On start binding has been called mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);