From c4eaaf4ebef59334fd93314eb679f6635ea04dd5 Mon Sep 17 00:00:00 2001 From: "warren%netscape.com" Date: Thu, 1 Oct 1998 08:08:09 +0000 Subject: [PATCH] Fixed up input stream buffering. Fixed some refcounting problems. --- modules/plugin/samples/simple/npsimple.cpp | 31 ++++++++ modules/plugin/src/npglue.cpp | 27 ++++--- modules/plugin/src/npglue.h | 23 ++++-- modules/plugin/src/nsplugin.cpp | 92 ++++++++++++++++------ modules/plugin/test/npsimple.cpp | 31 ++++++++ 5 files changed, 162 insertions(+), 42 deletions(-) diff --git a/modules/plugin/samples/simple/npsimple.cpp b/modules/plugin/samples/simple/npsimple.cpp index b550dc9ce349..42f5fce5dfc5 100644 --- a/modules/plugin/samples/simple/npsimple.cpp +++ b/modules/plugin/samples/simple/npsimple.cpp @@ -511,14 +511,21 @@ NS_IMPL_RELEASE(SimplePlugin); * resources allocated by NPP_Initialize. +++++++++++++++++++++++++++++++++++++++++++++++++*/ +SimplePlugin* gPlugin = NULL; + extern "C" NS_EXPORT nsresult NSGetFactory(const nsCID &aClass, nsIFactory **aFactory) { if (aClass.Equals(kIPluginIID)) { + if (gPlugin) { + *aFactory = gPlugin; + return NS_OK; + } SimplePlugin* fact = new SimplePlugin(); if (fact == NULL) return NS_ERROR_OUT_OF_MEMORY; fact->AddRef(); + gPlugin = fact; *aFactory = fact; return NS_OK; } @@ -708,6 +715,25 @@ SimplePluginInstance::Start(void) sprintf(factString, "my favorite function returned %d\n", v); DisplayJavaMessage(factString, -1); } + +#ifdef NEW_PLUGIN_STREAM_API + // Try getting some streams: + gPlugin->GetPluginManager()->GetURL(this, "http://warp", NULL, + new SimplePluginStreamListener(this)); + + gPlugin->GetPluginManager()->GetURL(this, "http://home.netscape.com", NULL, + new SimplePluginStreamListener(this), + nsPluginStreamType_AsFile); + + gPlugin->GetPluginManager()->GetURL(this, "http://warp/java", NULL, + new SimplePluginStreamListener(this), + nsPluginStreamType_AsFileOnly); + + gPlugin->GetPluginManager()->GetURL(this, "http://warp/java/oji", NULL, + new SimplePluginStreamListener(this), + nsPluginStreamType_Seek); +#endif + return NS_OK; } @@ -1080,6 +1106,11 @@ native_Simple_printToStdout(JRIEnv* env, struct Simple* self, void SimplePluginInstance::DisplayJavaMessage(char* msg, int len) { +#ifdef XP_PC + OutputDebugString(msg); + OutputDebugString("\n"); +#endif + Simple* javaPeer; // instance of the java class (there's no package qualifier) java_lang_String* str; diff --git a/modules/plugin/src/npglue.cpp b/modules/plugin/src/npglue.cpp index 13739079da07..c259447da36f 100644 --- a/modules/plugin/src/npglue.cpp +++ b/modules/plugin/src/npglue.cpp @@ -181,6 +181,7 @@ np_processURLNode(np_urlsnode* node, np_instance* instance, int status) nsIPluginStreamListener* listener = inStr->GetListener(); nsresult err = listener->OnStopBinding(node->urls->address, (nsPluginReason)np_statusToReason(status)); + inStr->Release(); // XXX ignore error? #else // !NEW_PLUGIN_STREAM_API @@ -580,10 +581,12 @@ NPL_Write(NET_StreamClass *stream, const unsigned char *str, int32 len) if (newstream->handle->userPlugin) { #ifdef NEW_PLUGIN_STREAM_API - nsPluginInputStream* instr = (nsPluginInputStream*)newstream->pstream->pdata; - nsIPluginStreamListener* listener = instr->GetListener(); - instr->SetReadBuffer(len, (const char*)str); - nsresult err = listener->OnDataAvailable((const char*)urls->address, instr, urls->position, len); + nsPluginInputStream* inStr = (nsPluginInputStream*)newstream->pstream->pdata; + nsIPluginStreamListener* listener = inStr->GetListener(); + nsresult err = inStr->ReceiveData((const char*)str, urls->position, len); + if (err == NS_OK) { + err = listener->OnDataAvailable((const char*)urls->address, inStr, urls->position, len); + } PR_ASSERT(err == NS_OK); // XXX this error should go somewhere #else // !NEW_PLUGIN_STREAM_API @@ -803,8 +806,10 @@ np_destroystream(np_stream *stream, NPError reason) TRACEMSG(("npglue.c: CallNPP_DestroyStreamProc")); if (stream->handle->userPlugin) { #ifdef NEW_PLUGIN_STREAM_API +#if 0 // released in np_processURLNode during NPL_URLExit nsPluginInputStream* inStr = (nsPluginInputStream*)stream->pstream->pdata; inStr->Release(); +#endif #else // !NEW_PLUGIN_STREAM_API nsPluginStreamPeer* peerStream = (nsPluginStreamPeer*)stream->pstream->pdata; nsIPluginStream* userStream = peerStream->GetUserStream(); @@ -958,13 +963,13 @@ NPL_Abort(NET_StreamClass *stream, int status) newstream->nstream = NULL; /* Remove reference to netlib stream */ - /* - * MK_UNABLE_TO_CONVERT is the special status code we - * return from NPL_Write to cancel the original netlib - * stream when we get a byte-range request, so we don't - * want to destroy the plug-in stream in this case (we - * shouldn't get this status code any other time here). - */ + /* + * MK_UNABLE_TO_CONVERT is the special status code we + * return from NPL_Write to cancel the original netlib + * stream when we get a byte-range request, so we don't + * want to destroy the plug-in stream in this case (we + * shouldn't get this status code any other time here). + */ if (!newstream->dontclose || (status < 0 && status != MK_UNABLE_TO_CONVERT)) np_destroystream(newstream, np_statusToReason(status)); } diff --git a/modules/plugin/src/npglue.h b/modules/plugin/src/npglue.h index 8fbb96add615..ee5f4c454b85 100644 --- a/modules/plugin/src/npglue.h +++ b/modules/plugin/src/npglue.h @@ -780,20 +780,27 @@ public: mStream = stream; } - void SetReadBuffer(PRUint32 len, const char* buffer) { - mBuffer = PL_strdup(buffer); - mBufferLength = len; - mAmountRead = 0; - } + nsresult ReceiveData(const char* buffer, PRUint32 offset, PRUint32 len); + void Cleanup(void); protected: nsIPluginStreamListener* mListener; nsPluginStreamType mStreamType; URL_Struct* mUrls; np_stream* mStream; - char* mBuffer; - PRUint32 mBufferLength; - PRUint32 mAmountRead; + + struct BufferElement { + BufferElement* next; + char* segment; + PRUint32 offset; + PRUint32 length; + }; + + BufferElement* mBuffer; +// PRUint32 mReadCursor; + +// PRUint32 mBufferLength; +// PRUint32 mAmountRead; }; diff --git a/modules/plugin/src/nsplugin.cpp b/modules/plugin/src/nsplugin.cpp index 3aade698453e..76edb8a454d7 100644 --- a/modules/plugin/src/nsplugin.cpp +++ b/modules/plugin/src/nsplugin.cpp @@ -159,8 +159,7 @@ nsPluginManager::Create(nsISupports* outer, const nsIID& aIID, void* *aInstanceP if (mgr == NULL) return NS_ERROR_OUT_OF_MEMORY; mgr->AddRef(); - *aInstancePtr = mgr->GetInner(); - *aInstancePtr = (outer != NULL)? (void *)mgr->GetInner(): (void *)mgr; + *aInstancePtr = outer ? (void *)mgr->GetInner() : (void *)mgr; return NS_OK; } @@ -613,6 +612,15 @@ nsPluginManager::GetURL(nsISupports* pluginInst, const char* referrer, PRBool forceJSEnabled) { + void* notifyData = NULL; + if (listener) { + nsPluginInputStream* inStr = new nsPluginInputStream(listener, streamType); + if (inStr == NULL) + return NS_ERROR_OUT_OF_MEMORY; + inStr->AddRef(); + notifyData = inStr; + } + NPError rslt = NPERR_INVALID_PARAM; nsIPluginInstance* inst = NULL; if (pluginInst->QueryInterface(kIPluginInstanceIID, (void**)&inst) == NS_OK) { @@ -620,12 +628,6 @@ nsPluginManager::GetURL(nsISupports* pluginInst, nsPluginInstancePeer* peer; nsresult err = inst->GetPeer((nsIPluginInstancePeer**)&peer); if (err == NS_OK) { - void* notifyData = NULL; - if (listener) { - nsPluginInputStream* inStr = new nsPluginInputStream(listener, streamType); - notifyData = inStr; - } - if (PR_CurrentThread() == mozilla_thread) { NPP npp = peer->GetNPP(); rslt = np_geturlinternal(npp, @@ -720,6 +722,15 @@ nsPluginManager::PostURL(nsISupports* pluginInst, PRUint32 postHeadersLen, const char* postHeaders) { + void* notifyData = NULL; + if (listener) { + nsPluginInputStream* inStr = new nsPluginInputStream(listener, streamType); + if (inStr == NULL) + return NS_ERROR_OUT_OF_MEMORY; + inStr->AddRef(); + notifyData = inStr; + } + NPError rslt = NPERR_INVALID_PARAM; nsIPluginInstance* inst = NULL; if (pluginInst->QueryInterface(kIPluginInstanceIID, (void**)&inst) == NS_OK) { @@ -727,12 +738,6 @@ nsPluginManager::PostURL(nsISupports* pluginInst, nsPluginInstancePeer* peer; nsresult err = inst->GetPeer((nsIPluginInstancePeer**)&peer); if (err == NS_OK) { - void* notifyData = NULL; - if (listener) { - nsPluginInputStream* inStr = new nsPluginInputStream(listener, streamType); - notifyData = inStr; - } - if (PR_CurrentThread() == mozilla_thread) { NPP npp = peer->GetNPP(); PR_ASSERT(postHeaders == NULL); // XXX need to deal with postHeaders @@ -1628,7 +1633,8 @@ nsPluginInputStream::nsPluginInputStream(nsIPluginStreamListener* listener, nsPluginStreamType streamType) : mListener(listener), mStreamType(streamType), mUrls(NULL), mStream(NULL), - mBuffer(NULL), mBufferLength(0), mAmountRead(0) + mBuffer(NULL) +// mBuffer(NULL), mBufferLength(0), mAmountRead(0) { NS_INIT_REFCNT(); listener->AddRef(); @@ -1636,8 +1642,8 @@ nsPluginInputStream::nsPluginInputStream(nsIPluginStreamListener* listener, nsPluginInputStream::~nsPluginInputStream(void) { + Cleanup(); mListener->Release(); - PL_strfree(mBuffer); } NS_IMPL_ADDREF(nsPluginInputStream); @@ -1659,9 +1665,26 @@ nsPluginInputStream::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_NOINTERFACE; } +void +nsPluginInputStream::Cleanup(void) +{ + if (mBuffer) { + // free the buffered data + BufferElement* element = mBuffer; + while (element != NULL) { + BufferElement* next = element->next; + PL_strfree(element->segment); + delete element; + element = next; + } + mBuffer = NULL; + } +} + NS_METHOD nsPluginInputStream::Close(void) { + Cleanup(); NPError err = npn_destroystream(mStream->instance->npp, mStream->pstream, nsPluginReason_UserBreak); return fromNPError[err]; @@ -1678,17 +1701,40 @@ nsPluginInputStream::GetLength(PRInt32 *aLength) #endif } +nsresult +nsPluginInputStream::ReceiveData(const char* buffer, PRUint32 offset, PRUint32 len) +{ + BufferElement* element = new BufferElement; + if (element == NULL) + return NS_ERROR_OUT_OF_MEMORY; + element->segment = PL_strdup(buffer); + element->offset = offset; + element->length = len; + element->next = mBuffer; + mBuffer = element; + return NS_OK; +} + NS_METHOD nsPluginInputStream::Read(char* aBuf, PRInt32 aOffset, PRInt32 aCount, PRInt32 *aReadCount) { - if (aOffset > (PRInt32)mBufferLength) - return NS_ERROR_FAILURE; // XXX right error? - PRUint32 cnt = PR_MIN(aCount, (PRInt32)mBufferLength - aOffset); - memcpy(aBuf, &mBuffer[aOffset], cnt); - *aReadCount = cnt; - mAmountRead -= cnt; - return NS_OK; + BufferElement* element; + for (element = mBuffer; element != NULL; element = element->next) { + if ((PRInt32)element->offset <= aOffset + && aOffset < (PRInt32)(element->offset + element->length)) { + // found our segment + PRUint32 segmentIndex = aOffset - element->offset; + PRUint32 segmentAmount = element->length - segmentIndex; + if (aCount > (PRInt32)segmentAmount) { + return NS_BASE_STREAM_EOF; // XXX right error? + } + memcpy(aBuf, &element->segment[segmentIndex], aCount); +// mReadCursor = segmentIndex + aCount; + return NS_OK; + } + } + return NS_ERROR_FAILURE; } NS_METHOD diff --git a/modules/plugin/test/npsimple.cpp b/modules/plugin/test/npsimple.cpp index b550dc9ce349..42f5fce5dfc5 100644 --- a/modules/plugin/test/npsimple.cpp +++ b/modules/plugin/test/npsimple.cpp @@ -511,14 +511,21 @@ NS_IMPL_RELEASE(SimplePlugin); * resources allocated by NPP_Initialize. +++++++++++++++++++++++++++++++++++++++++++++++++*/ +SimplePlugin* gPlugin = NULL; + extern "C" NS_EXPORT nsresult NSGetFactory(const nsCID &aClass, nsIFactory **aFactory) { if (aClass.Equals(kIPluginIID)) { + if (gPlugin) { + *aFactory = gPlugin; + return NS_OK; + } SimplePlugin* fact = new SimplePlugin(); if (fact == NULL) return NS_ERROR_OUT_OF_MEMORY; fact->AddRef(); + gPlugin = fact; *aFactory = fact; return NS_OK; } @@ -708,6 +715,25 @@ SimplePluginInstance::Start(void) sprintf(factString, "my favorite function returned %d\n", v); DisplayJavaMessage(factString, -1); } + +#ifdef NEW_PLUGIN_STREAM_API + // Try getting some streams: + gPlugin->GetPluginManager()->GetURL(this, "http://warp", NULL, + new SimplePluginStreamListener(this)); + + gPlugin->GetPluginManager()->GetURL(this, "http://home.netscape.com", NULL, + new SimplePluginStreamListener(this), + nsPluginStreamType_AsFile); + + gPlugin->GetPluginManager()->GetURL(this, "http://warp/java", NULL, + new SimplePluginStreamListener(this), + nsPluginStreamType_AsFileOnly); + + gPlugin->GetPluginManager()->GetURL(this, "http://warp/java/oji", NULL, + new SimplePluginStreamListener(this), + nsPluginStreamType_Seek); +#endif + return NS_OK; } @@ -1080,6 +1106,11 @@ native_Simple_printToStdout(JRIEnv* env, struct Simple* self, void SimplePluginInstance::DisplayJavaMessage(char* msg, int len) { +#ifdef XP_PC + OutputDebugString(msg); + OutputDebugString("\n"); +#endif + Simple* javaPeer; // instance of the java class (there's no package qualifier) java_lang_String* str;