Bug 755961: Plugin stream decomtamination (nsIPluginStreamListener). r=bsmedberg

This commit is contained in:
Josh Aas
2012-05-17 19:54:26 -04:00
parent 951af4acf3
commit 19b2d04e7b
13 changed files with 146 additions and 273 deletions

View File

@@ -56,7 +56,6 @@
#include "nsThreadUtils.h"
#include "mozilla/Preferences.h"
#include "nsIPluginStreamListener.h"
#include "nsPluginsDir.h"
#include "nsPluginSafety.h"
#include "nsPluginLogging.h"
@@ -561,10 +560,13 @@ nsNPAPIPlugin::RetainStream(NPStream *pstream, nsISupports **aRetainedPeer)
if (!pstream || !pstream->ndata)
return NPERR_INVALID_PARAM;
nsNPAPIPluginStreamListener* listener =
static_cast<nsNPAPIPluginStreamListener*>(pstream->ndata);
nsPluginStreamListenerPeer* peer = listener->GetStreamListenerPeer();
nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
nsNPAPIPluginStreamListener* listener = streamWrapper->GetStreamListener();
if (!listener) {
return NPERR_GENERIC_ERROR;
}
nsPluginStreamListenerPeer* peer = listener->GetStreamListenerPeer();
if (!peer)
return NPERR_GENERIC_ERROR;
@@ -597,7 +599,7 @@ MakeNewNPAPIStreamInternal(NPP npp, const char *relativeURL, const char *target,
return NPERR_GENERIC_ERROR;
}
nsCOMPtr<nsIPluginStreamListener> listener;
nsRefPtr<nsNPAPIPluginStreamListener> listener;
// Set aCallNotify here to false. If pluginHost->GetURL or PostURL fail,
// the listener's destructor will do the notification while we are about to
// return a failure code.
@@ -607,7 +609,7 @@ MakeNewNPAPIStreamInternal(NPP npp, const char *relativeURL, const char *target,
inst->NewStreamListener(relativeURL, notifyData,
getter_AddRefs(listener));
if (listener) {
static_cast<nsNPAPIPluginStreamListener*>(listener.get())->SetCallNotify(false);
listener->SetCallNotify(false);
}
}
@@ -631,7 +633,7 @@ MakeNewNPAPIStreamInternal(NPP npp, const char *relativeURL, const char *target,
if (listener) {
// SetCallNotify(bDoNotify) here, see comment above.
static_cast<nsNPAPIPluginStreamListener*>(listener.get())->SetCallNotify(bDoNotify);
listener->SetCallNotify(bDoNotify);
}
return NPERR_NO_ERROR;
@@ -645,25 +647,6 @@ namespace {
static char *gNPPException;
// A little helper class used to wrap up plugin manager streams (that is,
// streams from the plugin to the browser).
class nsNPAPIStreamWrapper : nsISupports
{
public:
NS_DECL_ISUPPORTS
protected:
nsIOutputStream *fStream;
NPStream fNPStream;
public:
nsNPAPIStreamWrapper(nsIOutputStream* stream);
virtual ~nsNPAPIStreamWrapper();
void GetStream(nsIOutputStream* &result);
NPStream* GetNPStream() { return &fNPStream; }
};
class nsPluginThreadRunnable : public nsRunnable,
public PRCList
{
@@ -770,33 +753,6 @@ InHeap(HANDLE hHeap, LPVOID lpMem)
} /* anonymous namespace */
NS_IMPL_ISUPPORTS1(nsNPAPIStreamWrapper, nsISupports)
nsNPAPIStreamWrapper::nsNPAPIStreamWrapper(nsIOutputStream* stream)
: fStream(stream)
{
NS_ASSERTION(stream, "bad stream");
fStream = stream;
NS_ADDREF(fStream);
memset(&fNPStream, 0, sizeof(fNPStream));
fNPStream.ndata = (void*) this;
}
nsNPAPIStreamWrapper::~nsNPAPIStreamWrapper()
{
fStream->Close();
NS_IF_RELEASE(fStream);
}
void
nsNPAPIStreamWrapper::GetStream(nsIOutputStream* &result)
{
result = fStream;
NS_IF_ADDREF(fStream);
}
NPPExceptionAutoHolder::NPPExceptionAutoHolder()
: mOldException(gNPPException)
{
@@ -1067,9 +1023,9 @@ _newstream(NPP npp, NPMIMEType type, const char* target, NPStream* *result)
nsCOMPtr<nsIOutputStream> stream;
if (NS_SUCCEEDED(inst->NewStreamFromPlugin((const char*) type, target,
getter_AddRefs(stream)))) {
nsNPAPIStreamWrapper* wrapper = new nsNPAPIStreamWrapper(stream);
nsNPAPIStreamWrapper* wrapper = new nsNPAPIStreamWrapper(stream, nsnull);
if (wrapper) {
(*result) = wrapper->GetNPStream();
(*result) = &wrapper->mNPStream;
err = NPERR_NO_ERROR;
} else {
err = NPERR_OUT_OF_MEMORY_ERROR;
@@ -1098,20 +1054,22 @@ _write(NPP npp, NPStream *pstream, int32_t len, void *buffer)
PluginDestructionGuard guard(npp);
nsNPAPIStreamWrapper* wrapper = (nsNPAPIStreamWrapper*) pstream->ndata;
NS_ASSERTION(wrapper, "null stream");
if (!wrapper)
nsNPAPIStreamWrapper* wrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
if (!wrapper) {
return -1;
}
nsIOutputStream* stream;
wrapper->GetStream(stream);
nsIOutputStream* stream = wrapper->GetOutputStream();
if (!stream) {
return -1;
}
PRUint32 count = 0;
nsresult rv = stream->Write((char *)buffer, len, &count);
NS_RELEASE(stream);
if (rv != NS_OK)
if (NS_FAILED(rv)) {
return -1;
}
return (int32_t)count;
}
@@ -1132,34 +1090,24 @@ _destroystream(NPP npp, NPStream *pstream, NPError reason)
PluginDestructionGuard guard(npp);
nsCOMPtr<nsIPluginStreamListener> listener =
do_QueryInterface((nsISupports *)pstream->ndata);
nsNPAPIStreamWrapper *streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
if (!streamWrapper) {
return NPERR_INVALID_PARAM;
}
// DestroyStream can kill two kinds of streams: NPP derived and NPN derived.
// check to see if they're trying to kill a NPP stream
nsRefPtr<nsNPAPIPluginStreamListener> listener = streamWrapper->GetStreamListener();
if (listener) {
// Tell the stream listner that the stream is now gone.
listener->OnStopBinding(nsnull, NS_BINDING_ABORTED);
// FIXME: http://bugzilla.mozilla.org/show_bug.cgi?id=240131
//
// Is it ok to leave pstream->ndata set here, and who releases it
// (or is it even properly ref counted)? And who closes the stream
// etc?
} else {
nsNPAPIStreamWrapper* wrapper = (nsNPAPIStreamWrapper *)pstream->ndata;
NS_ASSERTION(wrapper, "null wrapper");
if (!wrapper)
return NPERR_INVALID_PARAM;
// This will release the wrapped nsIOutputStream.
// pstream should always be a subobject of wrapper. See bug 548441.
NS_ASSERTION((char*)wrapper <= (char*)pstream &&
NS_ASSERTION((char*)streamWrapper <= (char*)pstream &&
((char*)pstream) + sizeof(*pstream)
<= ((char*)wrapper) + sizeof(*wrapper),
<= ((char*)streamWrapper) + sizeof(*streamWrapper),
"pstream is not a subobject of wrapper");
delete wrapper;
delete streamWrapper;
}
return NPERR_NO_ERROR;
@@ -2571,7 +2519,11 @@ _requestread(NPStream *pstream, NPByteRange *rangeList)
if (!pstream || !rangeList || !pstream->ndata)
return NPERR_INVALID_PARAM;
nsNPAPIPluginStreamListener* streamlistener = (nsNPAPIPluginStreamListener*)pstream->ndata;
nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
nsNPAPIPluginStreamListener* streamlistener = streamWrapper->GetStreamListener();
if (!streamlistener) {
return NPERR_GENERIC_ERROR;
}
PRInt32 streamtype = NP_NORMAL;
@@ -2583,8 +2535,7 @@ _requestread(NPStream *pstream, NPByteRange *rangeList)
if (!streamlistener->mStreamInfo)
return NPERR_GENERIC_ERROR;
nsresult rv = streamlistener->mStreamInfo
->RequestRead((NPByteRange *)rangeList);
nsresult rv = streamlistener->mStreamInfo->RequestRead((NPByteRange *)rangeList);
if (NS_FAILED(rv))
return NPERR_GENERIC_ERROR;