This commit is contained in:
dougt%netscape.com 2001-05-22 22:32:45 +00:00
Родитель d9e67ab2aa
Коммит 59eb2b1392
12 изменённых файлов: 1150 добавлений и 418 удалений

Просмотреть файл

@ -82,7 +82,7 @@ public:
* @return The return value is currently ignored.
*/
NS_IMETHOD
OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length) = 0;
OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 sourceOffset, PRUint32 length) = 0;
NS_IMETHOD
OnFileAvailable(nsIPluginStreamInfo* pluginInfo, const char* fileName) = 0;

Просмотреть файл

@ -26,6 +26,7 @@
#include "nsplugin.h"
#include "ns4xPlugin.h"
#include "ns4xPluginInstance.h"
#include "ns4xPluginStreamListener.h"
#include "nsIServiceManager.h"
#include "nsIMemory.h"
#include "nsIPluginStreamListener.h"
@ -676,6 +677,11 @@ ns4xStreamWrapper::GetStream(nsIOutputStream* &result)
NPError NP_EXPORT
_newstream(NPP npp, NPMIMEType type, const char* window, NPStream* *result)
{
#ifdef NS_DEBUG
printf("\nNewStream called \n\n");
#endif
if(!npp)
return NPERR_INVALID_INSTANCE_ERROR;
@ -719,6 +725,10 @@ _newstream(NPP npp, NPMIMEType type, const char* window, NPStream* *result)
int32 NP_EXPORT
_write(NPP npp, NPStream *pstream, int32 len, void *buffer)
{
#ifdef NS_DEBUG
printf("\nWrite called by plugin: \n%s\n", buffer);
#endif
// negative return indicates failure to the plugin
if(!npp)
return -1;
@ -745,6 +755,11 @@ _write(NPP npp, NPStream *pstream, int32 len, void *buffer)
NPError NP_EXPORT
_destroystream(NPP npp, NPStream *pstream, NPError reason)
{
#ifdef NS_DEBUG
printf("\nDestroy Stream called \n\n");
#endif
if(!npp)
return NPERR_INVALID_INSTANCE_ERROR;
@ -770,7 +785,7 @@ _destroystream(NPP npp, NPStream *pstream, NPError reason)
// This will release the wrapped nsIOutputStream.
delete wrapper;
pstream->ndata = nsnull;
return NPERR_NO_ERROR;
}
@ -1035,7 +1050,38 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
NPError NP_EXPORT
_requestread(NPStream *pstream, NPByteRange *rangeList)
{
#ifdef NS_DEBUG
printf("\nRequestRead called by plugin: ");
for(NPByteRange * range = rangeList; range != nsnull; range = range->next)
{
printf("%i-%i", range->offset, range->offset + range->length - 1);
if(range->next)
printf(",");
}
printf("\n\n");
#endif
if(!pstream || !rangeList || !pstream->ndata)
return NPERR_INVALID_PARAM;
nsresult res = NS_OK;
ns4xPluginStreamListener * streamlistener = (ns4xPluginStreamListener *)pstream->ndata;
if(NS_FAILED(res))
return NPERR_GENERIC_ERROR;
nsPluginStreamType streamtype = nsPluginStreamType_Normal;
streamlistener->GetStreamType(&streamtype);
if(streamtype != nsPluginStreamType_Seek)
return NPERR_STREAM_NOT_SEEKABLE;
if(streamlistener->mStreamInfo)
streamlistener->mStreamInfo->RequestRead((nsByteRange *)rangeList);
return NS_OK;
}

Просмотреть файл

@ -21,7 +21,7 @@
*/
#include "ns4xPluginInstance.h"
#include "nsIPluginStreamListener.h"
#include "ns4xPluginStreamListener.h"
#include "nsPluginHostImpl.h"
#include "prlog.h"
@ -40,46 +40,6 @@
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); // needed for NS_TRY_SAFE_CALL_*
static NS_DEFINE_IID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
#define MAX_PLUGIN_NECKO_BUFFER 16384
class ns4xPluginStreamListener : public nsIPluginStreamListener {
public:
NS_DECL_ISUPPORTS
///////////////////////////////////////////////////////////////////////////
// from nsIPluginStreamListener:
NS_IMETHOD OnStartBinding(nsIPluginStreamInfo* pluginInfo);
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);
///////////////////////////////////////////////////////////////////////////
// ns4xPluginStreamListener specific methods:
ns4xPluginStreamListener(nsIPluginInstance* inst, void* notifyData);
virtual ~ns4xPluginStreamListener(void);
PRBool IsStarted(void);
protected:
void* mNotifyData;
char* mStreamBuffer;
ns4xPluginInstance* mInst;
NPStream mNPStream;
PRUint32 mPosition;
nsPluginStreamType mStreamType;
};
///////////////////////////////////////////////////////////////////////////////
// ns4xPluginStreamListener Methods
///////////////////////////////////////////////////////////////////////////////
@ -88,13 +48,13 @@ static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
ns4xPluginStreamListener::ns4xPluginStreamListener(nsIPluginInstance* inst,
void* notifyData)
: mNotifyData(notifyData)
: mNotifyData(notifyData),
mStreamInfo(nsnull)
{
NS_INIT_REFCNT();
mInst = (ns4xPluginInstance*) inst;
mPosition = 0;
mStreamBuffer=nsnull;
mStreamBuffer=nsnull;
mPosition = 0;
// Initialize the 4.x interface structure
memset(&mNPStream, 0, sizeof(mNPStream));
@ -137,6 +97,8 @@ ns4xPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
pluginInfo->IsSeekable(&seekable);
pluginInfo->GetContentType(&contentType);
mStreamInfo = pluginInfo;
PRLibrary* lib = mInst->fLibrary;
// if we don't know the end of the stream, use 0 instead of -1. bug 59571
@ -185,6 +147,7 @@ ns4xPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
NS_IMETHODIMP
ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
nsIInputStream* input,
PRUint32 sourceOffset,
PRUint32 length)
{
if (!mInst || !mInst->IsStarted())
@ -205,6 +168,11 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
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
// we are getting a range request, reset mPosition since postion passed to plugin will
// be relative to the absolute position of the file.
if (sourceOffset != 0)
mPosition = 0;
pluginInfo->GetURL(&mNPStream.url);
pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified));
@ -267,10 +235,24 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
{
PRLibrary* lib = mInst->fLibrary;
#ifdef DEBUG_dougt
printf("> %d - %d \n", sourceOffset + writeCount + mPosition, numtowrite);
#if 0
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
#endif
NS_TRY_SAFE_CALL_RETURN(writeCount, CallNPP_WriteProc(callbacks->write,
npp,
&mNPStream,
mPosition,
sourceOffset + writeCount + mPosition,
numtowrite,
(void *)mStreamBuffer), lib);
if (writeCount < 0) {
@ -278,8 +260,10 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
goto error;
}
if (sourceOffset == 0)
mPosition += numtowrite;
amountRead -= numtowrite;
mPosition += numtowrite;
}
}
@ -294,7 +278,7 @@ error:
if (leftToRead > 0) // if we have more to read in this pass, do it recursivly
{
OnDataAvailable(pluginInfo, input, leftToRead);
OnDataAvailable(pluginInfo, input, sourceOffset, leftToRead);
}
return rv;

Просмотреть файл

@ -116,7 +116,7 @@ public:
// returns the state of mStarted
PRBool IsStarted(void);
protected:
nsresult InitializePlugin(nsIPluginInstancePeer* peer);

Просмотреть файл

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef ns4xPluginStreamListener_h__
#define ns4xPluginStreamListener_h__
#include "nsIPluginStreamListener.h"
#include "nsIPluginStreamInfo.h"
#define MAX_PLUGIN_NECKO_BUFFER 16384
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 OnFileAvailable( nsIPluginStreamInfo* pluginInfo, const char* fileName);
NS_IMETHOD OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status);
NS_IMETHOD GetStreamType(nsPluginStreamType *result);
// ns4xPluginStreamListener specific methods:
ns4xPluginStreamListener(nsIPluginInstance* inst, void* notifyData);
virtual ~ns4xPluginStreamListener();
PRBool IsStarted();
protected:
void* mNotifyData;
char* mStreamBuffer;
ns4xPluginInstance* mInst;
NPStream mNPStream;
PRUint32 mPosition;
nsPluginStreamType mStreamType;
public:
nsIPluginStreamInfo * mStreamInfo;
};
#endif

Просмотреть файл

@ -37,6 +37,7 @@
#include "nsIObserverService.h"
#include "nsIHttpProtocolHandler.h"
#include "nsIHttpChannel.h"
#include "nsIByteRangeRequest.h"
#include "nsIStreamListener.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
@ -44,6 +45,7 @@
#include "nsXPIDLString.h"
#include "nsIPref.h"
#include "nsIProtocolProxyService.h"
#include "nsIStreamConverterService.h"
#include "nsIFile.h"
#include "nsIInputStream.h"
#include "nsIIOService.h"
@ -55,6 +57,8 @@
#include "nsIDocument.h"
#include "nsIScriptablePlugin.h"
#include "nsICachingChannel.h"
#include "nsHashtable.h"
// Friggin' X11 has to "#define None". Lame!
#ifdef None
@ -63,12 +67,11 @@
#include "nsIRegistry.h"
#include "nsEnumeratorUtils.h"
#include "nsISupportsPrimitives.h"
// for the dialog
#include "nsIStringBundle.h"
#include "nsIPrompt.h"
#include "nsIWindowWatcher.h"
#include "nsHashtable.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptGlobalObjectOwner.h"
@ -144,6 +147,7 @@ static NS_DEFINE_IID(kIRequestObserverIID, NS_IREQUESTOBSERVER_IID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kHttpHandlerCID, NS_HTTPPROTOCOLHANDLER_CID);
static NS_DEFINE_CID(kIHttpHeaderVisitorIID, NS_IHTTPHEADERVISITOR_IID);
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
static NS_DEFINE_IID(kIFileUtilitiesIID, NS_IFILEUTILITIES_IID);
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
@ -167,6 +171,8 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
#define NS_PREF_MAX_NUM_CACHED_PLUGINS "browser.plugins.max_num_cached_plugins"
#define DEFAULT_NUMBER_OF_STOPPED_PLUGINS 10
#define MAGIC_REQUEST_CONTEXT 0x01020304
void DisplayNoDefaultPluginDialog(const char *mimeType);
/**
@ -828,10 +834,11 @@ void nsPluginTag::TryUnloadPlugin(PRBool aForceShutdown)
mLibrary = nsnull;
}
class nsPluginStreamListenerPeer;
class nsPluginStreamInfo : public nsIPluginStreamInfo
{
public:
nsPluginStreamInfo();
virtual ~nsPluginStreamInfo();
@ -874,22 +881,116 @@ public:
void
SetURL(const char* url);
void
SetPluginInstance(nsIPluginInstance * aPluginInstance);
void
SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer);
void
MakeByteRangeString(nsByteRange* aRangeList, char** string, PRInt32 *numRequests);
void
SetLocalCachedFile(const char* path);
void
GetLocalCachedFile(char** path);
private:
char* mContentType;
char* mURL;
PRBool mSeekable;
char* mFilePath;
PRBool mSeekable;
PRUint32 mLength;
PRUint32 mModified;
nsIPluginInstance * mPluginInstance;
nsPluginStreamListenerPeer * mPluginStreamListenerPeer;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class nsPluginStreamListenerPeer : public nsIStreamListener,
public nsIProgressEventSink,
public nsIHttpHeaderVisitor
{
public:
nsPluginStreamListenerPeer();
virtual ~nsPluginStreamListenerPeer();
NS_DECL_ISUPPORTS
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIHTTPHEADERVISITOR
// Called by GetURL and PostURL (via NewStream)
nsresult Initialize(nsIURI *aURL,
nsIPluginInstance *aInstance,
nsIPluginStreamListener *aListener,
PRInt32 requestCount = 1);
nsresult InitializeEmbeded(nsIURI *aURL,
nsIPluginInstance* aInstance,
nsIPluginInstanceOwner *aOwner = nsnull,
nsIPluginHost *aHost = nsnull);
nsresult InitializeFullPage(nsIPluginInstance *aInstance);
nsresult OnFileAvailable(const char* aFilename);
nsILoadGroup* GetLoadGroup();
nsresult SetLocalFile(const char* aFilename);
private:
nsresult SetUpCache(nsIURI* aURL);
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
nsIURI *mURL;
nsIPluginInstanceOwner *mOwner;
nsIPluginInstance *mInstance;
nsIPluginStreamListener *mPStreamListener;
nsPluginStreamInfo *mPluginStreamInfo;
PRBool mSetUpListener;
/*
* Set to PR_TRUE after nsIPluginInstancePeer::OnStartBinding() has
* been called. Checked in ::OnStopRequest so we can call the
* plugin's OnStartBinding if, for some reason, it has not already
* been called.
*/
PRPackedBool mStartBinding;
PRPackedBool mHaveFiredOnStartRequest;
// these get passed to the plugin stream listener
char *mMIMEType;
PRUint32 mLength;
nsPluginStreamType mStreamType;
nsIPluginHost *mHost;
// local file which was used to post data and which should be deleted after that
char *mLocalFile;
nsHashtable *mDataForwardToRequest;
public:
PRBool mAbort;
PRInt32 mPendingRequests;
};
nsPluginStreamInfo::nsPluginStreamInfo()
{
NS_INIT_REFCNT();
mPluginInstance = nsnull;
mPluginStreamListenerPeer = nsnull;
mContentType = nsnull;
mURL = nsnull;
mSeekable = PR_FALSE;
mFilePath = nsnull;
mSeekable = PR_FALSE;
mLength = 0;
mModified = 0;
}
@ -900,6 +1001,11 @@ nsPluginStreamInfo::~nsPluginStreamInfo()
PL_strfree(mContentType);
if(mURL != nsnull)
PL_strfree(mURL);
if(mFilePath != nsnull)
PL_strfree(mFilePath);
NS_IF_RELEASE(mPluginInstance);
NS_IF_RELEASE(mPluginStreamListenerPeer);
}
NS_IMPL_ADDREF(nsPluginStreamInfo)
@ -965,10 +1071,111 @@ nsPluginStreamInfo::GetURL(const char** result)
return NS_OK;
}
void
nsPluginStreamInfo::MakeByteRangeString(nsByteRange* aRangeList, char** rangeRequest, PRInt32 *numRequests)
{
*rangeRequest = nsnull;
*numRequests = 0;
//the string should look like this: bytes=500-700,601-999
if(!aRangeList)
return;
PRInt32 requestCnt = 0;
// XXX needs to be smarter than that
char * string = new char[1024];
string[0] = '\0';
PL_strcat(string, "bytes=");
for(nsByteRange * range = aRangeList; range != nsnull; range = range->next)
{
// XXX zero length?
if(!range->length)
continue;
// XXX needs to be fixed for negative offsets
nsCString firstbyte; firstbyte.AppendInt(range->offset);
nsCString lastbyte; firstbyte.AppendInt(range->offset + range->length - 1);
PL_strcat(string, firstbyte.get());
PL_strcat(string, "-");
PL_strcat(string, lastbyte.get());
if(range->next)
PL_strcat(string, ",");
requestCnt++;
}
// get rid of possible tailing comma
PRInt32 len = PL_strlen(string);
if(string[len - 1] == ',')
string[len - 1] = '\0';
*rangeRequest = string;
*numRequests = requestCnt;
return;
}
NS_IMETHODIMP
nsPluginStreamInfo::RequestRead(nsByteRange* rangeList)
{
return NS_ERROR_NOT_IMPLEMENTED;
mPluginStreamListenerPeer->mAbort = PR_TRUE;
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> url;
rv = NS_NewURI(getter_AddRefs(url), mURL);
nsCOMPtr<nsIChannel> channel;
rv = NS_OpenURI(getter_AddRefs(channel), url, nsnull, nsnull, nsnull);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
if(!httpChannel)
return NS_ERROR_FAILURE;
char *rangeString;
PRInt32 numRequests;
MakeByteRangeString(rangeList, &rangeString, &numRequests);
if(!rangeString)
return NS_ERROR_FAILURE;
httpChannel->SetRequestHeader("Range", rangeString);
delete [] rangeString;
// instruct old stream listener to cancel the request on the next
// attempt to write.
nsCOMPtr<nsIStreamListener> converter = mPluginStreamListenerPeer;
if (numRequests > 1) {
nsCOMPtr<nsIStreamConverterService> serv = do_GetService(kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = serv->AsyncConvertData(NS_LITERAL_STRING("multipart/byteranges").get(),
NS_LITERAL_STRING("*/*").get(),
mPluginStreamListenerPeer,
nsnull,
getter_AddRefs(converter));
if (NS_FAILED(rv))
return rv;
}
mPluginStreamListenerPeer->mPendingRequests += numRequests;
nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
rv = container->SetData(MAGIC_REQUEST_CONTEXT);
if (NS_FAILED(rv)) return rv;
return channel->AsyncOpen(converter, container);
}
// local methods
@ -1009,68 +1216,33 @@ nsPluginStreamInfo::SetURL(const char* url)
mURL = PL_strdup(url);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class nsPluginStreamListenerPeer : public nsIStreamListener,
public nsIProgressEventSink,
public nsIHttpHeaderVisitor
void
nsPluginStreamInfo::SetLocalCachedFile(const char* path)
{
if(mFilePath != nsnull)
PL_strfree(mFilePath);
mFilePath = PL_strdup(path);
}
void
nsPluginStreamInfo::GetLocalCachedFile(char** path)
{
*path = PL_strdup(mFilePath);
}
void
nsPluginStreamInfo::SetPluginInstance(nsIPluginInstance * aPluginInstance)
{
public:
nsPluginStreamListenerPeer();
virtual ~nsPluginStreamListenerPeer();
NS_IF_ADDREF(mPluginInstance = aPluginInstance);
}
NS_DECL_ISUPPORTS
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIHTTPHEADERVISITOR
// Called by GetURL and PostURL (via NewStream)
nsresult Initialize(nsIURI *aURL,
nsIPluginInstance *aInstance,
nsIPluginStreamListener *aListener);
nsresult InitializeEmbeded(nsIURI *aURL,
nsIPluginInstance* aInstance,
nsIPluginInstanceOwner *aOwner = nsnull,
nsIPluginHost *aHost = nsnull);
nsresult InitializeFullPage(nsIPluginInstance *aInstance);
nsresult OnFileAvailable(const char* aFilename);
nsILoadGroup* GetLoadGroup();
nsresult SetLocalFile(const char* aFilename);
private:
nsresult SetUpCache(nsIURI* aURL);
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
nsIURI *mURL;
nsIPluginInstanceOwner *mOwner;
nsIPluginInstance *mInstance;
nsIPluginStreamListener *mPStreamListener;
nsPluginStreamInfo *mPluginStreamInfo;
PRBool mSetUpListener;
/*
* Set to PR_TRUE after nsIPluginInstancePeer::OnStartBinding() has
* been called. Checked in ::OnStopRequest so we can call the
* plugin's OnStartBinding if, for some reason, it has not already
* been called.
*/
PRBool mStartBinding;
// these get passed to the plugin stream listener
char *mMIMEType;
PRUint32 mLength;
nsPluginStreamType mStreamType;
nsIPluginHost *mHost;
// local file which was used to post data and which should be deleted after that
char *mLocalFile;
};
void
nsPluginStreamInfo::SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer)
{
NS_IF_ADDREF(mPluginStreamListenerPeer = aPluginStreamListenerPeer);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -1157,6 +1329,11 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
mStreamType = nsPluginStreamType_Normal;
mStartBinding = PR_FALSE;
mLocalFile = nsnull;
mAbort = PR_FALSE;
mPendingRequests = 0;
mHaveFiredOnStartRequest = PR_FALSE;
mDataForwardToRequest = nsnull;
}
nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
@ -1187,55 +1364,21 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
localFile->Delete(PR_FALSE);
delete [] mLocalFile;
}
delete mDataForwardToRequest;
}
NS_IMPL_ADDREF(nsPluginStreamListenerPeer);
NS_IMPL_RELEASE(nsPluginStreamListenerPeer);
NS_IMPL_ISUPPORTS3(nsPluginStreamListenerPeer,
nsIStreamListener,
nsIRequestObserver,
nsIHttpHeaderVisitor)
nsresult nsPluginStreamListenerPeer::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
if (nsnull == aInstancePtrResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(kIStreamListenerIID))
{
*aInstancePtrResult = (void *)((nsIStreamListener *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIRequestObserverIID))
{
*aInstancePtrResult = (void *)((nsIRequestObserver *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIHttpHeaderVisitorIID))
{
*aInstancePtrResult = (void *)((nsIHttpHeaderVisitor *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kISupportsIID))
{
*aInstancePtrResult = (void *)((nsISupports *)((nsIStreamListener *)this));
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
/* Called as a result of GetURL and PostURL */
nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
nsIPluginInstance *aInstance,
nsIPluginStreamListener* aListener)
nsIPluginStreamListener* aListener,
PRInt32 requestCount)
{
#ifdef NS_DEBUG
char* spec;
@ -1255,6 +1398,15 @@ nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
mPluginStreamInfo = new nsPluginStreamInfo();
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mPendingRequests = requestCount;
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
return NS_OK;
}
@ -1297,6 +1449,13 @@ nsresult nsPluginStreamListenerPeer::InitializeEmbeded(nsIURI *aURL,
mPluginStreamInfo = new nsPluginStreamInfo();
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
return NS_OK;
}
@ -1315,6 +1474,13 @@ nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIPluginInstance *aInst
mPluginStreamInfo = new nsPluginStreamInfo();
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
return NS_OK;
}
@ -1324,6 +1490,12 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo
{
nsresult rv = NS_OK;
if (mHaveFiredOnStartRequest) {
return NS_OK;
}
mHaveFiredOnStartRequest = PR_TRUE;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (!channel)
@ -1435,12 +1607,52 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStatus(nsIRequest *request,
return NS_OK;
}
class nsPRUintKey : public nsHashKey {
protected:
PRUint32 mKey;
public:
nsPRUintKey(PRUint32 key) : mKey(key) {}
PRUint32 HashCode(void) const {
return mKey;
}
PRBool Equals(const nsHashKey *aKey) const {
return mKey == ((const nsPRUintKey *) aKey)->mKey;
}
nsHashKey *Clone() const {
return new nsPRUintKey(mKey);
}
PRUint32 GetValue() { return mKey; }
};
NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
nsISupports* aContext,
nsIInputStream *aIStream,
PRUint32 sourceOffset,
PRUint32 aLength)
{
if(mAbort)
{
PRUint32 magicNumber = 0; // set it to something that is not the magic number.
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext);
if (container)
container->GetData(&magicNumber);
if (magicNumber != MAGIC_REQUEST_CONTEXT)
{
// this is not one of our range requests
mAbort = PR_FALSE;
return NS_BINDING_ABORTED;
}
}
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> aURL;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
@ -1463,9 +1675,30 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
// call OnDataAvailable
if(mStreamType != nsPluginStreamType_AsFileOnly)
{
// It's up to the plugin to read from the stream
// If it doesn't, OnStopRequest will never be called
rv = mPStreamListener->OnDataAvailable((nsIPluginStreamInfo*)mPluginStreamInfo, aIStream, aLength);
// get the absolute offset of the request, if one exists.
nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request);
PRInt32 absoluteOffset = 0;
PRInt32 amtForwardToPlugin = 0;
if (brr) {
brr->GetStartRange(&absoluteOffset);
// we need to track how much data we have forward on to the plugin.
nsPRUintKey key(absoluteOffset);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
if (mDataForwardToRequest->Exists(&key))
amtForwardToPlugin = (PRInt32) mDataForwardToRequest->Remove(&key);
mDataForwardToRequest->Put(&key, (void*) (amtForwardToPlugin+aLength));
}
rv = mPStreamListener->OnDataAvailable((nsIPluginStreamInfo*)mPluginStreamInfo,
aIStream,
absoluteOffset+amtForwardToPlugin,
aLength);
// if a plugin returns an error, the peer must kill the stream
// else the stream and PluginStreamListener leak
if (NS_FAILED(rv))
@ -1486,7 +1719,74 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
nsISupports* aContext,
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.
if (cacheChannel) {
rv = cacheChannel->GetCacheFile(getter_AddRefs(localFile));
if (NS_SUCCEEDED(rv)) {
localFile->GetPath(getter_Copies(pathAndFilename));
mPluginStreamInfo->SetLocalCachedFile(pathAndFilename);
}
}
// remove the request from our data forwarding count hash.
nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request);
if (brr) {
PRInt32 absoluteOffset = 0;
brr->GetStartRange(&absoluteOffset);
nsPRUintKey key(absoluteOffset);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
(void) mDataForwardToRequest->Remove(&key);
}
// if we still have pending stuff to do, lets not close the plugin socket.
if (--mPendingRequests > 0)
return NS_OK;
// we keep our connections around...
PRUint32 magicNumber = 0; // set it to something that is not the magic number.
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext);
if (container)
container->GetData(&magicNumber);
if (magicNumber == MAGIC_REQUEST_CONTEXT)
{
// this is one of our range requests
return NS_OK;
}
if(!mPStreamListener)
return NS_ERROR_FAILURE;
if (!pathAndFilename)
mPluginStreamInfo->GetLocalCachedFile(getter_Copies(pathAndFilename));
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)
OnFileAvailable(pathAndFilename);
nsCOMPtr<nsIURI> aURL;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (!channel)
@ -1495,59 +1795,34 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
rv = channel->GetURI(getter_AddRefs(aURL));
if (NS_FAILED(rv))
return rv;
nsXPIDLCString urlString;
rv = aURL->GetSpec(getter_Copies(urlString));
if (NS_SUCCEEDED(rv))
mPluginStreamInfo->SetURL(urlString);
// Set the content type to ensure we don't pass null to the plugin
nsXPIDLCString aContentType;
rv = channel->GetContentType(getter_Copies(aContentType));
if (NS_FAILED(rv))
return rv;
if(nsnull != mPStreamListener)
if (aContentType)
mPluginStreamInfo->SetContentType(aContentType);
if (mStartBinding)
{
char* urlString;
nsCOMPtr<nsIFile> localFile;
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(channel);
if (cacheChannel)
rv = cacheChannel->GetCacheFile(getter_AddRefs(localFile));
if (NS_SUCCEEDED(rv) && localFile)
{
char* pathAndFilename;
rv = localFile->GetPath(&pathAndFilename);
if (NS_SUCCEEDED(rv))
{
OnFileAvailable(pathAndFilename);
nsMemory::Free(pathAndFilename);
}
}
rv = aURL->GetSpec(&urlString);
if (NS_SUCCEEDED(rv))
{
mPluginStreamInfo->SetURL(urlString);
nsCRT::free(urlString);
}
// Set the content type to ensure we don't pass null to the plugin
char* aContentType = nsnull;
rv = channel->GetContentType(&aContentType);
if (NS_FAILED(rv))
return rv;
if (nsnull != aContentType)
mPluginStreamInfo->SetContentType(aContentType);
if (mStartBinding)
{
// On start binding has been called
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
else
{
// OnStartBinding hasn't been called, so complete the action.
mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo);
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
if (aContentType)
nsCRT::free(aContentType);
// On start binding has been called
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
else
{
// OnStartBinding hasn't been called, so complete the action.
mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo);
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
return rv;
return NS_OK;
}
// private methods for nsPluginStreamListenerPeer
@ -1604,6 +1879,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
bSeekable = PR_TRUE;
}
}
mPluginStreamInfo->SetSeekable(bSeekable);
// get Last-Modified header for plugin info

Просмотреть файл

@ -26,6 +26,7 @@
#include "nsplugin.h"
#include "ns4xPlugin.h"
#include "ns4xPluginInstance.h"
#include "ns4xPluginStreamListener.h"
#include "nsIServiceManager.h"
#include "nsIMemory.h"
#include "nsIPluginStreamListener.h"
@ -676,6 +677,11 @@ ns4xStreamWrapper::GetStream(nsIOutputStream* &result)
NPError NP_EXPORT
_newstream(NPP npp, NPMIMEType type, const char* window, NPStream* *result)
{
#ifdef NS_DEBUG
printf("\nNewStream called \n\n");
#endif
if(!npp)
return NPERR_INVALID_INSTANCE_ERROR;
@ -719,6 +725,10 @@ _newstream(NPP npp, NPMIMEType type, const char* window, NPStream* *result)
int32 NP_EXPORT
_write(NPP npp, NPStream *pstream, int32 len, void *buffer)
{
#ifdef NS_DEBUG
printf("\nWrite called by plugin: \n%s\n", buffer);
#endif
// negative return indicates failure to the plugin
if(!npp)
return -1;
@ -745,6 +755,11 @@ _write(NPP npp, NPStream *pstream, int32 len, void *buffer)
NPError NP_EXPORT
_destroystream(NPP npp, NPStream *pstream, NPError reason)
{
#ifdef NS_DEBUG
printf("\nDestroy Stream called \n\n");
#endif
if(!npp)
return NPERR_INVALID_INSTANCE_ERROR;
@ -770,7 +785,7 @@ _destroystream(NPP npp, NPStream *pstream, NPError reason)
// This will release the wrapped nsIOutputStream.
delete wrapper;
pstream->ndata = nsnull;
return NPERR_NO_ERROR;
}
@ -1035,7 +1050,38 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
NPError NP_EXPORT
_requestread(NPStream *pstream, NPByteRange *rangeList)
{
#ifdef NS_DEBUG
printf("\nRequestRead called by plugin: ");
for(NPByteRange * range = rangeList; range != nsnull; range = range->next)
{
printf("%i-%i", range->offset, range->offset + range->length - 1);
if(range->next)
printf(",");
}
printf("\n\n");
#endif
if(!pstream || !rangeList || !pstream->ndata)
return NPERR_INVALID_PARAM;
nsresult res = NS_OK;
ns4xPluginStreamListener * streamlistener = (ns4xPluginStreamListener *)pstream->ndata;
if(NS_FAILED(res))
return NPERR_GENERIC_ERROR;
nsPluginStreamType streamtype = nsPluginStreamType_Normal;
streamlistener->GetStreamType(&streamtype);
if(streamtype != nsPluginStreamType_Seek)
return NPERR_STREAM_NOT_SEEKABLE;
if(streamlistener->mStreamInfo)
streamlistener->mStreamInfo->RequestRead((nsByteRange *)rangeList);
return NS_OK;
}

Просмотреть файл

@ -21,7 +21,7 @@
*/
#include "ns4xPluginInstance.h"
#include "nsIPluginStreamListener.h"
#include "ns4xPluginStreamListener.h"
#include "nsPluginHostImpl.h"
#include "prlog.h"
@ -40,46 +40,6 @@
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); // needed for NS_TRY_SAFE_CALL_*
static NS_DEFINE_IID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
#define MAX_PLUGIN_NECKO_BUFFER 16384
class ns4xPluginStreamListener : public nsIPluginStreamListener {
public:
NS_DECL_ISUPPORTS
///////////////////////////////////////////////////////////////////////////
// from nsIPluginStreamListener:
NS_IMETHOD OnStartBinding(nsIPluginStreamInfo* pluginInfo);
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);
///////////////////////////////////////////////////////////////////////////
// ns4xPluginStreamListener specific methods:
ns4xPluginStreamListener(nsIPluginInstance* inst, void* notifyData);
virtual ~ns4xPluginStreamListener(void);
PRBool IsStarted(void);
protected:
void* mNotifyData;
char* mStreamBuffer;
ns4xPluginInstance* mInst;
NPStream mNPStream;
PRUint32 mPosition;
nsPluginStreamType mStreamType;
};
///////////////////////////////////////////////////////////////////////////////
// ns4xPluginStreamListener Methods
///////////////////////////////////////////////////////////////////////////////
@ -88,13 +48,13 @@ static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
ns4xPluginStreamListener::ns4xPluginStreamListener(nsIPluginInstance* inst,
void* notifyData)
: mNotifyData(notifyData)
: mNotifyData(notifyData),
mStreamInfo(nsnull)
{
NS_INIT_REFCNT();
mInst = (ns4xPluginInstance*) inst;
mPosition = 0;
mStreamBuffer=nsnull;
mStreamBuffer=nsnull;
mPosition = 0;
// Initialize the 4.x interface structure
memset(&mNPStream, 0, sizeof(mNPStream));
@ -137,6 +97,8 @@ ns4xPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
pluginInfo->IsSeekable(&seekable);
pluginInfo->GetContentType(&contentType);
mStreamInfo = pluginInfo;
PRLibrary* lib = mInst->fLibrary;
// if we don't know the end of the stream, use 0 instead of -1. bug 59571
@ -185,6 +147,7 @@ ns4xPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
NS_IMETHODIMP
ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
nsIInputStream* input,
PRUint32 sourceOffset,
PRUint32 length)
{
if (!mInst || !mInst->IsStarted())
@ -205,6 +168,11 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
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
// we are getting a range request, reset mPosition since postion passed to plugin will
// be relative to the absolute position of the file.
if (sourceOffset != 0)
mPosition = 0;
pluginInfo->GetURL(&mNPStream.url);
pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified));
@ -267,10 +235,24 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
{
PRLibrary* lib = mInst->fLibrary;
#ifdef DEBUG_dougt
printf("> %d - %d \n", sourceOffset + writeCount + mPosition, numtowrite);
#if 0
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
#endif
NS_TRY_SAFE_CALL_RETURN(writeCount, CallNPP_WriteProc(callbacks->write,
npp,
&mNPStream,
mPosition,
sourceOffset + writeCount + mPosition,
numtowrite,
(void *)mStreamBuffer), lib);
if (writeCount < 0) {
@ -278,8 +260,10 @@ ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
goto error;
}
if (sourceOffset == 0)
mPosition += numtowrite;
amountRead -= numtowrite;
mPosition += numtowrite;
}
}
@ -294,7 +278,7 @@ error:
if (leftToRead > 0) // if we have more to read in this pass, do it recursivly
{
OnDataAvailable(pluginInfo, input, leftToRead);
OnDataAvailable(pluginInfo, input, sourceOffset, leftToRead);
}
return rv;

Просмотреть файл

@ -116,7 +116,7 @@ public:
// returns the state of mStarted
PRBool IsStarted(void);
protected:
nsresult InitializePlugin(nsIPluginInstancePeer* peer);

Просмотреть файл

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef ns4xPluginStreamListener_h__
#define ns4xPluginStreamListener_h__
#include "nsIPluginStreamListener.h"
#include "nsIPluginStreamInfo.h"
#define MAX_PLUGIN_NECKO_BUFFER 16384
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 OnFileAvailable( nsIPluginStreamInfo* pluginInfo, const char* fileName);
NS_IMETHOD OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status);
NS_IMETHOD GetStreamType(nsPluginStreamType *result);
// ns4xPluginStreamListener specific methods:
ns4xPluginStreamListener(nsIPluginInstance* inst, void* notifyData);
virtual ~ns4xPluginStreamListener();
PRBool IsStarted();
protected:
void* mNotifyData;
char* mStreamBuffer;
ns4xPluginInstance* mInst;
NPStream mNPStream;
PRUint32 mPosition;
nsPluginStreamType mStreamType;
public:
nsIPluginStreamInfo * mStreamInfo;
};
#endif

Просмотреть файл

@ -37,6 +37,7 @@
#include "nsIObserverService.h"
#include "nsIHttpProtocolHandler.h"
#include "nsIHttpChannel.h"
#include "nsIByteRangeRequest.h"
#include "nsIStreamListener.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
@ -44,6 +45,7 @@
#include "nsXPIDLString.h"
#include "nsIPref.h"
#include "nsIProtocolProxyService.h"
#include "nsIStreamConverterService.h"
#include "nsIFile.h"
#include "nsIInputStream.h"
#include "nsIIOService.h"
@ -55,6 +57,8 @@
#include "nsIDocument.h"
#include "nsIScriptablePlugin.h"
#include "nsICachingChannel.h"
#include "nsHashtable.h"
// Friggin' X11 has to "#define None". Lame!
#ifdef None
@ -63,12 +67,11 @@
#include "nsIRegistry.h"
#include "nsEnumeratorUtils.h"
#include "nsISupportsPrimitives.h"
// for the dialog
#include "nsIStringBundle.h"
#include "nsIPrompt.h"
#include "nsIWindowWatcher.h"
#include "nsHashtable.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptGlobalObjectOwner.h"
@ -144,6 +147,7 @@ static NS_DEFINE_IID(kIRequestObserverIID, NS_IREQUESTOBSERVER_IID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kHttpHandlerCID, NS_HTTPPROTOCOLHANDLER_CID);
static NS_DEFINE_CID(kIHttpHeaderVisitorIID, NS_IHTTPHEADERVISITOR_IID);
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
static NS_DEFINE_IID(kIFileUtilitiesIID, NS_IFILEUTILITIES_IID);
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
@ -167,6 +171,8 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
#define NS_PREF_MAX_NUM_CACHED_PLUGINS "browser.plugins.max_num_cached_plugins"
#define DEFAULT_NUMBER_OF_STOPPED_PLUGINS 10
#define MAGIC_REQUEST_CONTEXT 0x01020304
void DisplayNoDefaultPluginDialog(const char *mimeType);
/**
@ -828,10 +834,11 @@ void nsPluginTag::TryUnloadPlugin(PRBool aForceShutdown)
mLibrary = nsnull;
}
class nsPluginStreamListenerPeer;
class nsPluginStreamInfo : public nsIPluginStreamInfo
{
public:
nsPluginStreamInfo();
virtual ~nsPluginStreamInfo();
@ -874,22 +881,116 @@ public:
void
SetURL(const char* url);
void
SetPluginInstance(nsIPluginInstance * aPluginInstance);
void
SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer);
void
MakeByteRangeString(nsByteRange* aRangeList, char** string, PRInt32 *numRequests);
void
SetLocalCachedFile(const char* path);
void
GetLocalCachedFile(char** path);
private:
char* mContentType;
char* mURL;
PRBool mSeekable;
char* mFilePath;
PRBool mSeekable;
PRUint32 mLength;
PRUint32 mModified;
nsIPluginInstance * mPluginInstance;
nsPluginStreamListenerPeer * mPluginStreamListenerPeer;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class nsPluginStreamListenerPeer : public nsIStreamListener,
public nsIProgressEventSink,
public nsIHttpHeaderVisitor
{
public:
nsPluginStreamListenerPeer();
virtual ~nsPluginStreamListenerPeer();
NS_DECL_ISUPPORTS
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIHTTPHEADERVISITOR
// Called by GetURL and PostURL (via NewStream)
nsresult Initialize(nsIURI *aURL,
nsIPluginInstance *aInstance,
nsIPluginStreamListener *aListener,
PRInt32 requestCount = 1);
nsresult InitializeEmbeded(nsIURI *aURL,
nsIPluginInstance* aInstance,
nsIPluginInstanceOwner *aOwner = nsnull,
nsIPluginHost *aHost = nsnull);
nsresult InitializeFullPage(nsIPluginInstance *aInstance);
nsresult OnFileAvailable(const char* aFilename);
nsILoadGroup* GetLoadGroup();
nsresult SetLocalFile(const char* aFilename);
private:
nsresult SetUpCache(nsIURI* aURL);
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
nsIURI *mURL;
nsIPluginInstanceOwner *mOwner;
nsIPluginInstance *mInstance;
nsIPluginStreamListener *mPStreamListener;
nsPluginStreamInfo *mPluginStreamInfo;
PRBool mSetUpListener;
/*
* Set to PR_TRUE after nsIPluginInstancePeer::OnStartBinding() has
* been called. Checked in ::OnStopRequest so we can call the
* plugin's OnStartBinding if, for some reason, it has not already
* been called.
*/
PRPackedBool mStartBinding;
PRPackedBool mHaveFiredOnStartRequest;
// these get passed to the plugin stream listener
char *mMIMEType;
PRUint32 mLength;
nsPluginStreamType mStreamType;
nsIPluginHost *mHost;
// local file which was used to post data and which should be deleted after that
char *mLocalFile;
nsHashtable *mDataForwardToRequest;
public:
PRBool mAbort;
PRInt32 mPendingRequests;
};
nsPluginStreamInfo::nsPluginStreamInfo()
{
NS_INIT_REFCNT();
mPluginInstance = nsnull;
mPluginStreamListenerPeer = nsnull;
mContentType = nsnull;
mURL = nsnull;
mSeekable = PR_FALSE;
mFilePath = nsnull;
mSeekable = PR_FALSE;
mLength = 0;
mModified = 0;
}
@ -900,6 +1001,11 @@ nsPluginStreamInfo::~nsPluginStreamInfo()
PL_strfree(mContentType);
if(mURL != nsnull)
PL_strfree(mURL);
if(mFilePath != nsnull)
PL_strfree(mFilePath);
NS_IF_RELEASE(mPluginInstance);
NS_IF_RELEASE(mPluginStreamListenerPeer);
}
NS_IMPL_ADDREF(nsPluginStreamInfo)
@ -965,10 +1071,111 @@ nsPluginStreamInfo::GetURL(const char** result)
return NS_OK;
}
void
nsPluginStreamInfo::MakeByteRangeString(nsByteRange* aRangeList, char** rangeRequest, PRInt32 *numRequests)
{
*rangeRequest = nsnull;
*numRequests = 0;
//the string should look like this: bytes=500-700,601-999
if(!aRangeList)
return;
PRInt32 requestCnt = 0;
// XXX needs to be smarter than that
char * string = new char[1024];
string[0] = '\0';
PL_strcat(string, "bytes=");
for(nsByteRange * range = aRangeList; range != nsnull; range = range->next)
{
// XXX zero length?
if(!range->length)
continue;
// XXX needs to be fixed for negative offsets
nsCString firstbyte; firstbyte.AppendInt(range->offset);
nsCString lastbyte; firstbyte.AppendInt(range->offset + range->length - 1);
PL_strcat(string, firstbyte.get());
PL_strcat(string, "-");
PL_strcat(string, lastbyte.get());
if(range->next)
PL_strcat(string, ",");
requestCnt++;
}
// get rid of possible tailing comma
PRInt32 len = PL_strlen(string);
if(string[len - 1] == ',')
string[len - 1] = '\0';
*rangeRequest = string;
*numRequests = requestCnt;
return;
}
NS_IMETHODIMP
nsPluginStreamInfo::RequestRead(nsByteRange* rangeList)
{
return NS_ERROR_NOT_IMPLEMENTED;
mPluginStreamListenerPeer->mAbort = PR_TRUE;
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> url;
rv = NS_NewURI(getter_AddRefs(url), mURL);
nsCOMPtr<nsIChannel> channel;
rv = NS_OpenURI(getter_AddRefs(channel), url, nsnull, nsnull, nsnull);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
if(!httpChannel)
return NS_ERROR_FAILURE;
char *rangeString;
PRInt32 numRequests;
MakeByteRangeString(rangeList, &rangeString, &numRequests);
if(!rangeString)
return NS_ERROR_FAILURE;
httpChannel->SetRequestHeader("Range", rangeString);
delete [] rangeString;
// instruct old stream listener to cancel the request on the next
// attempt to write.
nsCOMPtr<nsIStreamListener> converter = mPluginStreamListenerPeer;
if (numRequests > 1) {
nsCOMPtr<nsIStreamConverterService> serv = do_GetService(kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = serv->AsyncConvertData(NS_LITERAL_STRING("multipart/byteranges").get(),
NS_LITERAL_STRING("*/*").get(),
mPluginStreamListenerPeer,
nsnull,
getter_AddRefs(converter));
if (NS_FAILED(rv))
return rv;
}
mPluginStreamListenerPeer->mPendingRequests += numRequests;
nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
rv = container->SetData(MAGIC_REQUEST_CONTEXT);
if (NS_FAILED(rv)) return rv;
return channel->AsyncOpen(converter, container);
}
// local methods
@ -1009,68 +1216,33 @@ nsPluginStreamInfo::SetURL(const char* url)
mURL = PL_strdup(url);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class nsPluginStreamListenerPeer : public nsIStreamListener,
public nsIProgressEventSink,
public nsIHttpHeaderVisitor
void
nsPluginStreamInfo::SetLocalCachedFile(const char* path)
{
if(mFilePath != nsnull)
PL_strfree(mFilePath);
mFilePath = PL_strdup(path);
}
void
nsPluginStreamInfo::GetLocalCachedFile(char** path)
{
*path = PL_strdup(mFilePath);
}
void
nsPluginStreamInfo::SetPluginInstance(nsIPluginInstance * aPluginInstance)
{
public:
nsPluginStreamListenerPeer();
virtual ~nsPluginStreamListenerPeer();
NS_IF_ADDREF(mPluginInstance = aPluginInstance);
}
NS_DECL_ISUPPORTS
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIHTTPHEADERVISITOR
// Called by GetURL and PostURL (via NewStream)
nsresult Initialize(nsIURI *aURL,
nsIPluginInstance *aInstance,
nsIPluginStreamListener *aListener);
nsresult InitializeEmbeded(nsIURI *aURL,
nsIPluginInstance* aInstance,
nsIPluginInstanceOwner *aOwner = nsnull,
nsIPluginHost *aHost = nsnull);
nsresult InitializeFullPage(nsIPluginInstance *aInstance);
nsresult OnFileAvailable(const char* aFilename);
nsILoadGroup* GetLoadGroup();
nsresult SetLocalFile(const char* aFilename);
private:
nsresult SetUpCache(nsIURI* aURL);
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
nsIURI *mURL;
nsIPluginInstanceOwner *mOwner;
nsIPluginInstance *mInstance;
nsIPluginStreamListener *mPStreamListener;
nsPluginStreamInfo *mPluginStreamInfo;
PRBool mSetUpListener;
/*
* Set to PR_TRUE after nsIPluginInstancePeer::OnStartBinding() has
* been called. Checked in ::OnStopRequest so we can call the
* plugin's OnStartBinding if, for some reason, it has not already
* been called.
*/
PRBool mStartBinding;
// these get passed to the plugin stream listener
char *mMIMEType;
PRUint32 mLength;
nsPluginStreamType mStreamType;
nsIPluginHost *mHost;
// local file which was used to post data and which should be deleted after that
char *mLocalFile;
};
void
nsPluginStreamInfo::SetPluginStreamListenerPeer(nsPluginStreamListenerPeer * aPluginStreamListenerPeer)
{
NS_IF_ADDREF(mPluginStreamListenerPeer = aPluginStreamListenerPeer);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -1157,6 +1329,11 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
mStreamType = nsPluginStreamType_Normal;
mStartBinding = PR_FALSE;
mLocalFile = nsnull;
mAbort = PR_FALSE;
mPendingRequests = 0;
mHaveFiredOnStartRequest = PR_FALSE;
mDataForwardToRequest = nsnull;
}
nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
@ -1187,55 +1364,21 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
localFile->Delete(PR_FALSE);
delete [] mLocalFile;
}
delete mDataForwardToRequest;
}
NS_IMPL_ADDREF(nsPluginStreamListenerPeer);
NS_IMPL_RELEASE(nsPluginStreamListenerPeer);
NS_IMPL_ISUPPORTS3(nsPluginStreamListenerPeer,
nsIStreamListener,
nsIRequestObserver,
nsIHttpHeaderVisitor)
nsresult nsPluginStreamListenerPeer::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
if (nsnull == aInstancePtrResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(kIStreamListenerIID))
{
*aInstancePtrResult = (void *)((nsIStreamListener *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIRequestObserverIID))
{
*aInstancePtrResult = (void *)((nsIRequestObserver *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIHttpHeaderVisitorIID))
{
*aInstancePtrResult = (void *)((nsIHttpHeaderVisitor *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kISupportsIID))
{
*aInstancePtrResult = (void *)((nsISupports *)((nsIStreamListener *)this));
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
/* Called as a result of GetURL and PostURL */
nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
nsIPluginInstance *aInstance,
nsIPluginStreamListener* aListener)
nsIPluginStreamListener* aListener,
PRInt32 requestCount)
{
#ifdef NS_DEBUG
char* spec;
@ -1255,6 +1398,15 @@ nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
mPluginStreamInfo = new nsPluginStreamInfo();
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mPendingRequests = requestCount;
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
return NS_OK;
}
@ -1297,6 +1449,13 @@ nsresult nsPluginStreamListenerPeer::InitializeEmbeded(nsIURI *aURL,
mPluginStreamInfo = new nsPluginStreamInfo();
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
return NS_OK;
}
@ -1315,6 +1474,13 @@ nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIPluginInstance *aInst
mPluginStreamInfo = new nsPluginStreamInfo();
mPluginStreamInfo->SetPluginInstance(aInstance);
mPluginStreamInfo->SetPluginStreamListenerPeer(this);
mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
return NS_OK;
}
@ -1324,6 +1490,12 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo
{
nsresult rv = NS_OK;
if (mHaveFiredOnStartRequest) {
return NS_OK;
}
mHaveFiredOnStartRequest = PR_TRUE;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (!channel)
@ -1435,12 +1607,52 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStatus(nsIRequest *request,
return NS_OK;
}
class nsPRUintKey : public nsHashKey {
protected:
PRUint32 mKey;
public:
nsPRUintKey(PRUint32 key) : mKey(key) {}
PRUint32 HashCode(void) const {
return mKey;
}
PRBool Equals(const nsHashKey *aKey) const {
return mKey == ((const nsPRUintKey *) aKey)->mKey;
}
nsHashKey *Clone() const {
return new nsPRUintKey(mKey);
}
PRUint32 GetValue() { return mKey; }
};
NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
nsISupports* aContext,
nsIInputStream *aIStream,
PRUint32 sourceOffset,
PRUint32 aLength)
{
if(mAbort)
{
PRUint32 magicNumber = 0; // set it to something that is not the magic number.
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext);
if (container)
container->GetData(&magicNumber);
if (magicNumber != MAGIC_REQUEST_CONTEXT)
{
// this is not one of our range requests
mAbort = PR_FALSE;
return NS_BINDING_ABORTED;
}
}
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> aURL;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
@ -1463,9 +1675,30 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
// call OnDataAvailable
if(mStreamType != nsPluginStreamType_AsFileOnly)
{
// It's up to the plugin to read from the stream
// If it doesn't, OnStopRequest will never be called
rv = mPStreamListener->OnDataAvailable((nsIPluginStreamInfo*)mPluginStreamInfo, aIStream, aLength);
// get the absolute offset of the request, if one exists.
nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request);
PRInt32 absoluteOffset = 0;
PRInt32 amtForwardToPlugin = 0;
if (brr) {
brr->GetStartRange(&absoluteOffset);
// we need to track how much data we have forward on to the plugin.
nsPRUintKey key(absoluteOffset);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
if (mDataForwardToRequest->Exists(&key))
amtForwardToPlugin = (PRInt32) mDataForwardToRequest->Remove(&key);
mDataForwardToRequest->Put(&key, (void*) (amtForwardToPlugin+aLength));
}
rv = mPStreamListener->OnDataAvailable((nsIPluginStreamInfo*)mPluginStreamInfo,
aIStream,
absoluteOffset+amtForwardToPlugin,
aLength);
// if a plugin returns an error, the peer must kill the stream
// else the stream and PluginStreamListener leak
if (NS_FAILED(rv))
@ -1486,7 +1719,74 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
nsISupports* aContext,
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.
if (cacheChannel) {
rv = cacheChannel->GetCacheFile(getter_AddRefs(localFile));
if (NS_SUCCEEDED(rv)) {
localFile->GetPath(getter_Copies(pathAndFilename));
mPluginStreamInfo->SetLocalCachedFile(pathAndFilename);
}
}
// remove the request from our data forwarding count hash.
nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request);
if (brr) {
PRInt32 absoluteOffset = 0;
brr->GetStartRange(&absoluteOffset);
nsPRUintKey key(absoluteOffset);
if (!mDataForwardToRequest)
return NS_ERROR_FAILURE;
(void) mDataForwardToRequest->Remove(&key);
}
// if we still have pending stuff to do, lets not close the plugin socket.
if (--mPendingRequests > 0)
return NS_OK;
// we keep our connections around...
PRUint32 magicNumber = 0; // set it to something that is not the magic number.
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext);
if (container)
container->GetData(&magicNumber);
if (magicNumber == MAGIC_REQUEST_CONTEXT)
{
// this is one of our range requests
return NS_OK;
}
if(!mPStreamListener)
return NS_ERROR_FAILURE;
if (!pathAndFilename)
mPluginStreamInfo->GetLocalCachedFile(getter_Copies(pathAndFilename));
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)
OnFileAvailable(pathAndFilename);
nsCOMPtr<nsIURI> aURL;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (!channel)
@ -1495,59 +1795,34 @@ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
rv = channel->GetURI(getter_AddRefs(aURL));
if (NS_FAILED(rv))
return rv;
nsXPIDLCString urlString;
rv = aURL->GetSpec(getter_Copies(urlString));
if (NS_SUCCEEDED(rv))
mPluginStreamInfo->SetURL(urlString);
// Set the content type to ensure we don't pass null to the plugin
nsXPIDLCString aContentType;
rv = channel->GetContentType(getter_Copies(aContentType));
if (NS_FAILED(rv))
return rv;
if(nsnull != mPStreamListener)
if (aContentType)
mPluginStreamInfo->SetContentType(aContentType);
if (mStartBinding)
{
char* urlString;
nsCOMPtr<nsIFile> localFile;
nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(channel);
if (cacheChannel)
rv = cacheChannel->GetCacheFile(getter_AddRefs(localFile));
if (NS_SUCCEEDED(rv) && localFile)
{
char* pathAndFilename;
rv = localFile->GetPath(&pathAndFilename);
if (NS_SUCCEEDED(rv))
{
OnFileAvailable(pathAndFilename);
nsMemory::Free(pathAndFilename);
}
}
rv = aURL->GetSpec(&urlString);
if (NS_SUCCEEDED(rv))
{
mPluginStreamInfo->SetURL(urlString);
nsCRT::free(urlString);
}
// Set the content type to ensure we don't pass null to the plugin
char* aContentType = nsnull;
rv = channel->GetContentType(&aContentType);
if (NS_FAILED(rv))
return rv;
if (nsnull != aContentType)
mPluginStreamInfo->SetContentType(aContentType);
if (mStartBinding)
{
// On start binding has been called
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
else
{
// OnStartBinding hasn't been called, so complete the action.
mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo);
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
if (aContentType)
nsCRT::free(aContentType);
// On start binding has been called
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
else
{
// OnStartBinding hasn't been called, so complete the action.
mPStreamListener->OnStartBinding((nsIPluginStreamInfo*)mPluginStreamInfo);
mPStreamListener->OnStopBinding((nsIPluginStreamInfo*)mPluginStreamInfo, aStatus);
}
return rv;
return NS_OK;
}
// private methods for nsPluginStreamListenerPeer
@ -1604,6 +1879,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
bSeekable = PR_TRUE;
}
}
mPluginStreamInfo->SetSeekable(bSeekable);
// get Last-Modified header for plugin info

Просмотреть файл

@ -82,7 +82,7 @@ public:
* @return The return value is currently ignored.
*/
NS_IMETHOD
OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length) = 0;
OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 sourceOffset, PRUint32 length) = 0;
NS_IMETHOD
OnFileAvailable(nsIPluginStreamInfo* pluginInfo, const char* fileName) = 0;