Bug 532208: Defer deletion of browser streams to later tasks. r=bsmedberg

This commit is contained in:
Chris Jones 2010-02-26 13:07:56 -06:00
parent 958042217d
commit 568776b2d0
7 changed files with 84 additions and 43 deletions

View File

@ -152,16 +152,6 @@ BrowserStreamChild::AnswerNPP_StreamAsFile(const nsCString& fname)
return true; return true;
} }
bool
BrowserStreamChild::Answer__delete__(const NPError& reason,
const bool& artificial)
{
AssertPluginThread();
if (!artificial)
NPP_DestroyStream(reason);
return true;
}
NPError NPError
BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList) BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
{ {
@ -180,18 +170,31 @@ BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
return result; return result;
} }
void bool
BrowserStreamChild::NPP_DestroyStream(NPError reason) BrowserStreamChild::AnswerNPP_DestroyStream(const NPReason& reason,
NPError* err)
{ {
PLUGIN_LOG_DEBUG(("%s (reason=%i)", FULLFUNCTION, reason)); PLUGIN_LOG_DEBUG(("%s (reason=%i)", FULLFUNCTION, reason));
AssertPluginThread(); AssertPluginThread();
if (mClosed) if (mClosed) {
return; NS_WARNING("NPP_DestroyStream on a closed stream");
return true;
}
mInstance->mPluginIface->destroystream(&mInstance->mData, &mStream, reason); *err = mInstance->mPluginIface->destroystream(&mInstance->mData,
&mStream, reason);
mClosed = true; mClosed = true;
return true;
}
bool
BrowserStreamChild::Recv__delete__()
{
if (!mClosed)
NS_WARNING("__delete__ on an open stream");
return true;
} }
} /* namespace plugins */ } /* namespace plugins */

View File

@ -81,8 +81,12 @@ public:
int32_t* consumed); int32_t* consumed);
virtual bool AnswerNPP_StreamAsFile(const nsCString& fname); virtual bool AnswerNPP_StreamAsFile(const nsCString& fname);
virtual bool Answer__delete__(const NPError& reason,
const bool& artificial); NS_OVERRIDE
virtual bool AnswerNPP_DestroyStream(const NPReason& reason, NPError* err);
NS_OVERRIDE
virtual bool Recv__delete__();
void EnsureCorrectInstance(PluginInstanceChild* i) void EnsureCorrectInstance(PluginInstanceChild* i)

View File

@ -2,6 +2,15 @@
#include "BrowserStreamParent.h" #include "BrowserStreamParent.h"
#include "PluginInstanceParent.h" #include "PluginInstanceParent.h"
#include "PluginModuleParent.h"
template<>
struct RunnableMethodTraits<mozilla::plugins::BrowserStreamParent>
{
typedef mozilla::plugins::BrowserStreamParent Cls;
static void RetainCallee(Cls* obj) { }
static void ReleaseCallee(Cls* obj) { }
};
namespace mozilla { namespace mozilla {
namespace plugins { namespace plugins {
@ -10,12 +19,33 @@ BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp,
NPStream* stream) NPStream* stream)
: mNPP(npp) : mNPP(npp)
, mStream(stream) , mStream(stream)
, mDeleteTask(nsnull)
{ {
mStream->pdata = static_cast<AStream*>(this); mStream->pdata = static_cast<AStream*>(this);
} }
BrowserStreamParent::~BrowserStreamParent() BrowserStreamParent::~BrowserStreamParent()
{ {
if (mDeleteTask) {
mDeleteTask->Cancel();
// MessageLoop::current() owns this
mDeleteTask = nsnull;
}
}
NPError
BrowserStreamParent::NPP_DestroyStream(NPReason reason)
{
PLUGIN_LOG_DEBUG(("%s (reason=%i)", FULLFUNCTION, reason));
if (!mDeleteTask) {
mDeleteTask = NewRunnableMethod(this, &BrowserStreamParent::Delete);
MessageLoop::current()->PostTask(FROM_HERE, mDeleteTask);
}
NPError err = NPERR_NO_ERROR;
CallNPP_DestroyStream(reason, &err);
return err;
} }
bool bool
@ -42,15 +72,6 @@ BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
return true; return true;
} }
bool
BrowserStreamParent::Answer__delete__(const NPError& reason,
const bool& artificial)
{
if (!artificial)
NPN_DestroyStream(reason);
return true;
}
int32_t int32_t
BrowserStreamParent::WriteReady() BrowserStreamParent::WriteReady()
{ {
@ -87,12 +108,21 @@ BrowserStreamParent::StreamAsFile(const char* fname)
CallNPP_StreamAsFile(nsCString(fname)); CallNPP_StreamAsFile(nsCString(fname));
} }
NPError bool
BrowserStreamParent::NPN_DestroyStream(NPReason reason) BrowserStreamParent::AnswerNPN_DestroyStream(const NPReason& reason,
NPError* result)
{ {
PLUGIN_LOG_DEBUG_FUNCTION; PLUGIN_LOG_DEBUG_FUNCTION;
return mNPP->mNPNIface->destroystream(mNPP->mNPP, mStream, reason); *result = mNPP->mNPNIface->destroystream(mNPP->mNPP, mStream, reason);
return true;
}
void
BrowserStreamParent::Delete()
{
PBrowserStreamParent::Send__delete__(this);
// |this| just got deleted
} }
} // namespace plugins } // namespace plugins

View File

@ -44,6 +44,7 @@
namespace mozilla { namespace mozilla {
namespace plugins { namespace plugins {
class PluginModuleParent;
class PluginInstanceParent; class PluginInstanceParent;
class BrowserStreamParent : public PBrowserStreamParent, public AStream class BrowserStreamParent : public PBrowserStreamParent, public AStream
@ -56,23 +57,25 @@ public:
NPStream* stream); NPStream* stream);
virtual ~BrowserStreamParent(); virtual ~BrowserStreamParent();
NPError NPP_DestroyStream(NPReason reason);
NS_OVERRIDE virtual bool IsBrowserStream() { return true; } NS_OVERRIDE virtual bool IsBrowserStream() { return true; }
virtual bool AnswerNPN_RequestRead(const IPCByteRanges& ranges, virtual bool AnswerNPN_RequestRead(const IPCByteRanges& ranges,
NPError* result); NPError* result);
virtual bool virtual bool AnswerNPN_DestroyStream(const NPReason& reason, NPError* result);
Answer__delete__(const NPError& reason, const bool& artificial);
int32_t WriteReady(); int32_t WriteReady();
int32_t Write(int32_t offset, int32_t len, void* buffer); int32_t Write(int32_t offset, int32_t len, void* buffer);
void StreamAsFile(const char* fname); void StreamAsFile(const char* fname);
private: private:
NPError NPN_DestroyStream(NPError reason); void Delete();
PluginInstanceParent* mNPP; PluginInstanceParent* mNPP;
NPStream* mStream; NPStream* mStream;
CancelableTask* mDeleteTask;
}; };
} // namespace plugins } // namespace plugins

View File

@ -66,17 +66,17 @@ child:
rpc NPP_StreamAsFile(nsCString fname); rpc NPP_StreamAsFile(nsCString fname);
rpc NPP_DestroyStream(NPReason reason)
returns (NPError error);
async __delete__();
parent: parent:
rpc NPN_RequestRead(IPCByteRanges ranges) rpc NPN_RequestRead(IPCByteRanges ranges)
returns (NPError result); returns (NPError result);
both: rpc NPN_DestroyStream(NPReason reason)
/** returns (NPError error);
* ~PBrowserStream is for both NPN_DestroyStream and NPP_DestroyStream.
* @param artificial True when the stream is closed as a by-product of
* some other call (such as a failure in NPP_Write).
*/
rpc __delete__(NPReason reason, bool artificial);
}; };
} // namespace plugins } // namespace plugins

View File

@ -640,7 +640,7 @@ PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
if (NPERR_NO_ERROR != err) if (NPERR_NO_ERROR != err)
PBrowserStreamParent::Call__delete__(bs, NPERR_GENERIC_ERROR, true); bs->NPP_DestroyStream(NPERR_GENERIC_ERROR);
return err; return err;
} }
@ -658,8 +658,7 @@ PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason)
if (sp->mNPP != this) if (sp->mNPP != this)
NS_RUNTIMEABORT("Mismatched plugin data"); NS_RUNTIMEABORT("Mismatched plugin data");
PBrowserStreamParent::Call__delete__(sp, reason, false); return sp->NPP_DestroyStream(reason);
return NPERR_NO_ERROR;
} }
else { else {
PluginStreamParent* sp = PluginStreamParent* sp =

View File

@ -898,7 +898,9 @@ _destroystream(NPP aNPP,
if (s->IsBrowserStream()) { if (s->IsBrowserStream()) {
BrowserStreamChild* bs = static_cast<BrowserStreamChild*>(s); BrowserStreamChild* bs = static_cast<BrowserStreamChild*>(s);
bs->EnsureCorrectInstance(p); bs->EnsureCorrectInstance(p);
PBrowserStreamChild::Call__delete__(bs, aReason, false); NPError err = NPERR_NO_ERROR;
bs->CallNPN_DestroyStream(aReason, &err);
return err;
} }
else { else {
PluginStreamChild* ps = static_cast<PluginStreamChild*>(s); PluginStreamChild* ps = static_cast<PluginStreamChild*>(s);