зеркало из https://github.com/mozilla/gecko-dev.git
fix bug 115891 Byte range request are not giving the correct data, r=peterl, sr=darin, a=asa
This commit is contained in:
Родитель
336bc57506
Коммит
be7f51fae3
|
@ -45,7 +45,6 @@ nsplugin.h
|
|||
nsplugindefs.h
|
||||
nsICookieStorage.h
|
||||
nsIPluginStreamListener.h
|
||||
nsIPluginStreamListener2.h
|
||||
nsIPluginStreamInfo.h
|
||||
nsIPluginInputStream.h
|
||||
nsIPluginInputStream2.h
|
||||
|
|
|
@ -46,7 +46,6 @@ EXPORTS = \
|
|||
nsIPluginTagInfo2.h \
|
||||
nsIWindowlessPlugInstPeer.h \
|
||||
nsIPluginInputStream.h \
|
||||
nsIPluginInputStream2.h \
|
||||
nsIPluginStreamListener.h \
|
||||
nsIPluginStreamListener2.h \
|
||||
nsIPluginStreamInfo.h \
|
||||
|
|
|
@ -34,7 +34,6 @@ EXPORTS = \
|
|||
nsIPluginTagInfo2.h \
|
||||
nsIWindowlessPlugInstPeer.h \
|
||||
nsIPluginStreamListener.h \
|
||||
nsIPluginStreamListener2.h \
|
||||
nsIPluginStreamInfo.h \
|
||||
nsplugin.h \
|
||||
nsplugindefs.h \
|
||||
|
|
|
@ -72,6 +72,12 @@ public:
|
|||
|
||||
NS_IMETHOD
|
||||
RequestRead(nsByteRange* rangeList) = 0;
|
||||
|
||||
NS_IMETHOD
|
||||
GetStreamOffset(PRInt32 *aStreamOffset) = 0;
|
||||
|
||||
NS_IMETHOD
|
||||
SetStreamOffset(PRInt32 aStreamOffset) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
||||
NS_TRY_SAFE_CALL_RETURN(numtowrite, CallNPP_WriteReadyProc(callbacks->writeready,
|
||||
npp,
|
||||
&mNPStream), lib);
|
||||
char *ptrStreamBuffer = mStreamBuffer; // tmp ptr
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
|
||||
("NPP WriteReady called: this=%p, npp=%p, return(towrite)=%d, url=%s\n",
|
||||
this, npp, numtowrite, mNPStream.url));
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
PRInt32 writeCount = 0; // bytes consumed by plugin instance
|
||||
|
||||
rv = NS_OK;
|
||||
NS_TRY_SAFE_CALL_RETURN(writeCount,
|
||||
CallNPP_WriteProc(callbacks->write, npp, &mNPStream, mPosition, numtowrite, (void *)ptrStreamBuffer),
|
||||
mInst->fLibrary);
|
||||
|
||||
error:
|
||||
if (PR_TRUE == createdHere) // cleanup buffer if we made it locally
|
||||
{
|
||||
PR_Free(mStreamBuffer);
|
||||
mStreamBuffer=nsnull;
|
||||
}
|
||||
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 (leftToRead > 0) // if we have more to read in this pass, do it recursively
|
||||
{
|
||||
OnDataAvailable(pluginInfo, input, leftToRead);
|
||||
}
|
||||
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;) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
@ -1141,6 +1140,12 @@ public:
|
|||
NS_IMETHOD
|
||||
RequestRead(nsByteRange* rangeList);
|
||||
|
||||
NS_IMETHOD
|
||||
GetStreamOffset(PRInt32 *result);
|
||||
|
||||
NS_IMETHOD
|
||||
SetStreamOffset(PRInt32 result);
|
||||
|
||||
// local methods
|
||||
|
||||
void
|
||||
|
@ -1191,6 +1196,7 @@ private:
|
|||
nsPluginStreamListenerPeer * mPluginStreamListenerPeer;
|
||||
nsCOMPtr<nsIOutputStream> 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)
|
||||
{
|
||||
|
@ -1432,7 +1444,13 @@ 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<nsIURI> 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<nsIStreamListener> 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<nsISupportsPRUint32> 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<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)) {
|
||||
|
@ -2142,7 +2178,6 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIURI> aURL;
|
||||
nsCOMPtr<nsIChannel> 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<nsIInputStream> stream = aIStream;
|
||||
|
@ -2200,14 +2236,7 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPluginStreamListener2> 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,35 +2269,12 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
|
|||
nsresult aStatus)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request);
|
||||
nsCOMPtr<nsIFile> 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()));
|
||||
("nsPluginStreamListenerPeer::OnStopRequest this=%p aStatus=%d request=%p\n",
|
||||
this, aStatus, request));
|
||||
|
||||
// If we are writting the stream to disk ourselves, lets close it
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
mPluginStreamInfo->GetLocalCachedFileStream(getter_AddRefs(outStream));
|
||||
if (outStream) {
|
||||
outStream->Close();
|
||||
}
|
||||
|
||||
// remove the request from our data forwarding count hash.
|
||||
// for ByteRangeRequest we're just updating the mDataForwardToRequest hash and return.
|
||||
nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request);
|
||||
if (brr) {
|
||||
PRInt32 absoluteOffset = 0;
|
||||
|
@ -2276,13 +2282,24 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
|
|||
|
||||
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<nsIOutputStream> 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)
|
||||
return NS_OK;
|
||||
|
@ -2302,21 +2319,6 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
|
|||
if(!mPStreamListener)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!pathAndFilename) {
|
||||
// see if it is a file channel.
|
||||
nsCOMPtr<nsIFileChannel> 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<nsIURI> aURL;
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
if (!channel)
|
||||
|
@ -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<nsIFile> 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) {
|
||||
localFile->GetPath(getter_Copies(pathAndFilename));
|
||||
}
|
||||
}
|
||||
|
||||
if (pathAndFilename && *pathAndFilename) {
|
||||
OnFileAvailable(pathAndFilename);
|
||||
}
|
||||
|
||||
if (mStartBinding)
|
||||
{
|
||||
// On start binding has been called
|
||||
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
|
||||
|
|
Загрузка…
Ссылка в новой задаче