зеркало из https://github.com/mozilla/pjs.git
Bug 551049 part 3: delay the delivery of NPP_URLNotify until the related stream is completely delivered and destroyed, and propagate errors from NPP_Write and NPN_DestroyStream back to NPP_URLNotify r=bent
This commit is contained in:
Родитель
372ebbcfb0
Коммит
60af52af60
|
@ -46,19 +46,22 @@ BrowserStreamChild::BrowserStreamChild(PluginInstanceChild* instance,
|
|||
const nsCString& url,
|
||||
const uint32_t& length,
|
||||
const uint32_t& lastmodified,
|
||||
const PStreamNotifyChild* notifyData,
|
||||
StreamNotifyChild* notifyData,
|
||||
const nsCString& headers,
|
||||
const nsCString& mimeType,
|
||||
const bool& seekable,
|
||||
NPError* rv,
|
||||
uint16_t* stype)
|
||||
: mInstance(instance)
|
||||
, mClosed(false)
|
||||
, mStreamStatus(kStreamOpen)
|
||||
, mDestroyPending(NOT_DESTROYED)
|
||||
, mNotifyPending(false)
|
||||
, mInstanceDying(false)
|
||||
, mState(CONSTRUCTING)
|
||||
, mURL(url)
|
||||
, mHeaders(headers)
|
||||
, mDestroyPending(kDestroyNotPending)
|
||||
, mDeliverDataTracker(this)
|
||||
, mStreamNotify(notifyData)
|
||||
, mDeliveryTracker(this)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(("%s (%s, %i, %i, %p, %s, %s)", FULLFUNCTION,
|
||||
url.get(), length, lastmodified, (void*) notifyData,
|
||||
|
@ -71,19 +74,13 @@ BrowserStreamChild::BrowserStreamChild(PluginInstanceChild* instance,
|
|||
mStream.url = NullableStringGet(mURL);
|
||||
mStream.end = length;
|
||||
mStream.lastmodified = lastmodified;
|
||||
if (notifyData)
|
||||
mStream.notifyData =
|
||||
static_cast<const StreamNotifyChild*>(notifyData)->mClosure;
|
||||
mStream.headers = NullableStringGet(mHeaders);
|
||||
if (notifyData)
|
||||
mStream.notifyData = notifyData->mClosure;
|
||||
}
|
||||
|
||||
NPError
|
||||
BrowserStreamChild::StreamConstructed(
|
||||
const nsCString& url,
|
||||
const uint32_t& length,
|
||||
const uint32_t& lastmodified,
|
||||
PStreamNotifyChild* notifyData,
|
||||
const nsCString& headers,
|
||||
const nsCString& mimeType,
|
||||
const bool& seekable,
|
||||
uint16_t* stype)
|
||||
|
@ -95,16 +92,24 @@ BrowserStreamChild::StreamConstructed(
|
|||
&mInstance->mData, const_cast<char*>(NullableStringGet(mimeType)),
|
||||
&mStream, seekable, stype);
|
||||
if (rv != NPERR_NO_ERROR) {
|
||||
mClosed = true;
|
||||
mState = DELETING;
|
||||
mStreamNotify = NULL;
|
||||
}
|
||||
else {
|
||||
mState = ALIVE;
|
||||
|
||||
if (mStreamNotify)
|
||||
mStreamNotify->SetAssociatedStream(this);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
BrowserStreamChild::~BrowserStreamChild()
|
||||
{
|
||||
NS_ASSERTION(!mStreamNotify, "Should have nulled it by now!");
|
||||
}
|
||||
|
||||
bool
|
||||
BrowserStreamChild::RecvWrite(const int32_t& offset,
|
||||
const Buffer& data,
|
||||
|
@ -117,7 +122,7 @@ BrowserStreamChild::RecvWrite(const int32_t& offset,
|
|||
if (ALIVE != mState)
|
||||
NS_RUNTIMEABORT("Unexpected state: received data after NPP_DestroyStream?");
|
||||
|
||||
if (mClosed)
|
||||
if (kStreamOpen != mStreamStatus)
|
||||
return true;
|
||||
|
||||
mStream.end = newlength;
|
||||
|
@ -129,9 +134,7 @@ BrowserStreamChild::RecvWrite(const int32_t& offset,
|
|||
newdata->data = data;
|
||||
newdata->curpos = 0;
|
||||
|
||||
if (mDeliverDataTracker.empty())
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
mDeliverDataTracker.NewRunnableMethod(&BrowserStreamChild::DeliverData));
|
||||
EnsureDeliveryPending();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -146,7 +149,7 @@ BrowserStreamChild::AnswerNPP_StreamAsFile(const nsCString& fname)
|
|||
if (ALIVE != mState)
|
||||
NS_RUNTIMEABORT("Unexpected state: received file after NPP_DestroyStream?");
|
||||
|
||||
if (mClosed)
|
||||
if (kStreamOpen != mStreamStatus)
|
||||
return true;
|
||||
|
||||
mInstance->mPluginIface->asfile(&mInstance->mData, &mStream,
|
||||
|
@ -163,12 +166,11 @@ BrowserStreamChild::RecvNPP_DestroyStream(const NPReason& reason)
|
|||
NS_RUNTIMEABORT("Unexpected state: recevied NPP_DestroyStream twice?");
|
||||
|
||||
mState = DYING;
|
||||
mDestroyPending = reason;
|
||||
|
||||
if (mDeliverDataTracker.empty())
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
mDeliverDataTracker.NewRunnableMethod(&BrowserStreamChild::DeliverData));
|
||||
mDestroyPending = DESTROY_PENDING;
|
||||
if (NPRES_DONE != reason)
|
||||
mStreamStatus = reason;
|
||||
|
||||
EnsureDeliveryPending();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -190,7 +192,7 @@ BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
|
|||
|
||||
AssertPluginThread();
|
||||
|
||||
if (ALIVE != mState || mClosed)
|
||||
if (ALIVE != mState || kStreamOpen != mStreamStatus)
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
IPCByteRanges ranges;
|
||||
|
@ -207,84 +209,95 @@ BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
|
|||
void
|
||||
BrowserStreamChild::NPN_DestroyStream(NPReason reason)
|
||||
{
|
||||
mClosed = true;
|
||||
mStreamStatus = reason;
|
||||
if (ALIVE == mState)
|
||||
SendNPN_DestroyStream(NPRES_NETWORK_ERR);
|
||||
SendNPN_DestroyStream(reason);
|
||||
|
||||
ClearSuspendedTimer();
|
||||
mPendingData.Clear();
|
||||
MaybeDeliverNPP_DestroyStream();
|
||||
EnsureDeliveryPending();
|
||||
}
|
||||
|
||||
void
|
||||
BrowserStreamChild::DeliverData()
|
||||
BrowserStreamChild::EnsureDeliveryPending()
|
||||
{
|
||||
if (mState != ALIVE && mState != DYING)
|
||||
NS_RUNTIMEABORT("Unexpected state");
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
mDeliveryTracker.NewRunnableMethod(&BrowserStreamChild::Deliver));
|
||||
}
|
||||
|
||||
if (mClosed) {
|
||||
ClearSuspendedTimer();
|
||||
MaybeDeliverNPP_DestroyStream();
|
||||
return;
|
||||
}
|
||||
|
||||
while (mPendingData.Length()) {
|
||||
while (mPendingData[0].curpos < mPendingData[0].data.Length()) {
|
||||
int32_t r = mInstance->mPluginIface->writeready(&mInstance->mData, &mStream);
|
||||
if (r == 0) {
|
||||
SetSuspendedTimer();
|
||||
return;
|
||||
}
|
||||
if (!mPendingData.Length())
|
||||
break;
|
||||
r = mInstance->mPluginIface->write(
|
||||
&mInstance->mData, &mStream,
|
||||
mPendingData[0].offset + mPendingData[0].curpos, // offset
|
||||
mPendingData[0].data.Length() - mPendingData[0].curpos, // length
|
||||
const_cast<char*>(mPendingData[0].data.BeginReading() + mPendingData[0].curpos));
|
||||
if (r == 0) {
|
||||
SetSuspendedTimer();
|
||||
return;
|
||||
}
|
||||
if (r < 0) { // error condition
|
||||
NPN_DestroyStream(NPRES_NETWORK_ERR);
|
||||
return;
|
||||
}
|
||||
if (!mPendingData.Length())
|
||||
break;
|
||||
|
||||
mPendingData[0].curpos += r;
|
||||
void
|
||||
BrowserStreamChild::Deliver()
|
||||
{
|
||||
while (kStreamOpen == mStreamStatus && mPendingData.Length()) {
|
||||
if (DeliverPendingData() && kStreamOpen == mStreamStatus) {
|
||||
SetSuspendedTimer();
|
||||
return;
|
||||
}
|
||||
if (!mPendingData.Length())
|
||||
break;
|
||||
mPendingData.RemoveElementAt(0);
|
||||
}
|
||||
|
||||
ClearSuspendedTimer();
|
||||
MaybeDeliverNPP_DestroyStream();
|
||||
}
|
||||
|
||||
void
|
||||
BrowserStreamChild::MaybeDeliverNPP_DestroyStream()
|
||||
{
|
||||
if (kDestroyNotPending != mDestroyPending) {
|
||||
NS_ASSERTION(mPendingData.Length() == 0, "Pending data?");
|
||||
NS_ASSERTION(kStreamOpen != mStreamStatus || 0 == mPendingData.Length(),
|
||||
"Exit out of the data-delivery loop with pending data");
|
||||
mPendingData.Clear();
|
||||
|
||||
if (DESTROY_PENDING == mDestroyPending) {
|
||||
mDestroyPending = DESTROYED;
|
||||
if (mState != DYING)
|
||||
NS_RUNTIMEABORT("mDestroyPending but state not DYING");
|
||||
|
||||
mClosed = true;
|
||||
NPReason reason = mDestroyPending;
|
||||
mDestroyPending = kDestroyNotPending;
|
||||
NS_ASSERTION(NPRES_DONE != mStreamStatus, "Success status set too early!");
|
||||
if (kStreamOpen == mStreamStatus)
|
||||
mStreamStatus = NPRES_DONE;
|
||||
|
||||
(void) mInstance->mPluginIface
|
||||
->destroystream(&mInstance->mData, &mStream, reason);
|
||||
|
||||
->destroystream(&mInstance->mData, &mStream, mStreamStatus);
|
||||
}
|
||||
if (DESTROYED == mDestroyPending && mNotifyPending) {
|
||||
NS_ASSERTION(mStreamNotify, "mDestroyPending but no mStreamNotify?");
|
||||
|
||||
mNotifyPending = false;
|
||||
mStreamNotify->NPP_URLNotify(mStreamStatus);
|
||||
delete mStreamNotify;
|
||||
mStreamNotify = NULL;
|
||||
}
|
||||
if (DYING == mState && DESTROYED == mDestroyPending
|
||||
&& !mStreamNotify && !mInstanceDying) {
|
||||
SendStreamDestroyed();
|
||||
mState = DELETING;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BrowserStreamChild::DeliverPendingData()
|
||||
{
|
||||
if (mState != ALIVE && mState != DYING)
|
||||
NS_RUNTIMEABORT("Unexpected state");
|
||||
|
||||
NS_ASSERTION(mPendingData.Length(), "Called from Deliver with empty pending");
|
||||
|
||||
while (mPendingData[0].curpos < mPendingData[0].data.Length()) {
|
||||
int32_t r = mInstance->mPluginIface->writeready(&mInstance->mData, &mStream);
|
||||
if (kStreamOpen != mStreamStatus)
|
||||
return false;
|
||||
if (0 == r) // plugin wants to suspend delivery
|
||||
return true;
|
||||
|
||||
r = mInstance->mPluginIface->write(
|
||||
&mInstance->mData, &mStream,
|
||||
mPendingData[0].offset + mPendingData[0].curpos, // offset
|
||||
mPendingData[0].data.Length() - mPendingData[0].curpos, // length
|
||||
const_cast<char*>(mPendingData[0].data.BeginReading() + mPendingData[0].curpos));
|
||||
if (kStreamOpen != mStreamStatus)
|
||||
return false;
|
||||
if (0 == r)
|
||||
return true;
|
||||
if (r < 0) { // error condition
|
||||
NPN_DestroyStream(NPRES_NETWORK_ERR);
|
||||
return false;
|
||||
}
|
||||
mPendingData[0].curpos += r;
|
||||
}
|
||||
mPendingData.RemoveElementAt(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
BrowserStreamChild::SetSuspendedTimer()
|
||||
|
@ -292,8 +305,8 @@ BrowserStreamChild::SetSuspendedTimer()
|
|||
if (mSuspendedTimer.IsRunning())
|
||||
return;
|
||||
mSuspendedTimer.Start(
|
||||
base::TimeDelta::FromMilliseconds(100),
|
||||
this, &BrowserStreamChild::DeliverData);
|
||||
base::TimeDelta::FromMilliseconds(100), // 100ms copied from Mozilla plugin host
|
||||
this, &BrowserStreamChild::Deliver);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace mozilla {
|
|||
namespace plugins {
|
||||
|
||||
class PluginInstanceChild;
|
||||
class PStreamNotifyChild;
|
||||
class StreamNotifyChild;
|
||||
|
||||
class BrowserStreamChild : public PBrowserStreamChild, public AStream
|
||||
{
|
||||
|
@ -54,22 +54,17 @@ public:
|
|||
const nsCString& url,
|
||||
const uint32_t& length,
|
||||
const uint32_t& lastmodified,
|
||||
const PStreamNotifyChild* notifyData,
|
||||
StreamNotifyChild* notifyData,
|
||||
const nsCString& headers,
|
||||
const nsCString& mimeType,
|
||||
const bool& seekable,
|
||||
NPError* rv,
|
||||
uint16_t* stype);
|
||||
virtual ~BrowserStreamChild() { }
|
||||
virtual ~BrowserStreamChild();
|
||||
|
||||
NS_OVERRIDE virtual bool IsBrowserStream() { return true; }
|
||||
|
||||
NPError StreamConstructed(
|
||||
const nsCString& url,
|
||||
const uint32_t& length,
|
||||
const uint32_t& lastmodified,
|
||||
PStreamNotifyChild* notifyData,
|
||||
const nsCString& headers,
|
||||
const nsCString& mimeType,
|
||||
const bool& seekable,
|
||||
uint16_t* stype);
|
||||
|
@ -95,21 +90,87 @@ public:
|
|||
NPError NPN_RequestRead(NPByteRange* aRangeList);
|
||||
void NPN_DestroyStream(NPReason reason);
|
||||
|
||||
void NotifyPending() {
|
||||
NS_ASSERTION(!mNotifyPending, "Pending twice?");
|
||||
mNotifyPending = true;
|
||||
EnsureDeliveryPending();
|
||||
}
|
||||
|
||||
/**
|
||||
* During instance destruction, artificially cancel all outstanding streams.
|
||||
*
|
||||
* @return false if we are already in the DELETING state.
|
||||
*/
|
||||
bool InstanceDying() {
|
||||
if (DELETING == mState)
|
||||
return false;
|
||||
|
||||
mInstanceDying = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FinishDelivery() {
|
||||
NS_ASSERTION(mInstanceDying, "Should only be called after InstanceDying");
|
||||
NS_ASSERTION(DELETING != mState, "InstanceDying didn't work?");
|
||||
mStreamStatus = NPRES_NETWORK_ERR;
|
||||
Deliver();
|
||||
NS_ASSERTION(!mStreamNotify, "Didn't deliver NPN_URLNotify?");
|
||||
}
|
||||
|
||||
private:
|
||||
friend class StreamNotifyChild;
|
||||
using PBrowserStreamChild::SendNPN_DestroyStream;
|
||||
|
||||
/**
|
||||
* Deliver the data currently in mPending, scheduling
|
||||
* Post an event to ensure delivery of pending data/destroy/urlnotify events
|
||||
* outside of the current RPC stack.
|
||||
*/
|
||||
void EnsureDeliveryPending();
|
||||
|
||||
/**
|
||||
* Deliver data, destruction, notify scheduling
|
||||
* or cancelling the suspended timer as needed.
|
||||
*/
|
||||
void DeliverData();
|
||||
void MaybeDeliverNPP_DestroyStream();
|
||||
void Deliver();
|
||||
|
||||
/**
|
||||
* Deliver one chunk of pending data.
|
||||
* @return true if the plugin indicated a pause was necessary
|
||||
*/
|
||||
bool DeliverPendingData();
|
||||
|
||||
void SetSuspendedTimer();
|
||||
void ClearSuspendedTimer();
|
||||
|
||||
PluginInstanceChild* mInstance;
|
||||
NPStream mStream;
|
||||
bool mClosed;
|
||||
|
||||
static const NPReason kStreamOpen = -1;
|
||||
|
||||
/**
|
||||
* The plugin's notion of whether a stream has been "closed" (no more
|
||||
* data delivery) differs from the plugin host due to asynchronous delivery
|
||||
* of data and NPN_DestroyStream. While the plugin-visible stream is open,
|
||||
* mStreamStatus should be kStreamOpen (-1). mStreamStatus will be a
|
||||
* failure code if either the parent or child indicates stream failure.
|
||||
*/
|
||||
NPReason mStreamStatus;
|
||||
|
||||
/**
|
||||
* Delivery of NPP_DestroyStream and NPP_URLNotify must be postponed until
|
||||
* all data has been delivered.
|
||||
*/
|
||||
enum {
|
||||
NOT_DESTROYED, // NPP_DestroyStream not yet received
|
||||
DESTROY_PENDING, // NPP_DestroyStream received, not yet delivered
|
||||
DESTROYED // NPP_DestroyStream delivered, NPP_URLNotify may still be pending
|
||||
} mDestroyPending;
|
||||
bool mNotifyPending;
|
||||
|
||||
// When NPP_Destroy is called for our instance (manager), this flag is set
|
||||
// cancels the stream and avoids sending StreamDestroyed.
|
||||
bool mInstanceDying;
|
||||
|
||||
enum {
|
||||
CONSTRUCTING,
|
||||
ALIVE,
|
||||
|
@ -118,16 +179,7 @@ private:
|
|||
} mState;
|
||||
nsCString mURL;
|
||||
nsCString mHeaders;
|
||||
|
||||
static const NPReason kDestroyNotPending = -1;
|
||||
|
||||
/**
|
||||
* When NPP_DestroyStream is delivered with pending data, we postpone
|
||||
* delivering or acknowledging it until the pending data has been written.
|
||||
*
|
||||
* The default/initial value is kDestroyNotPending
|
||||
*/
|
||||
NPReason mDestroyPending;
|
||||
StreamNotifyChild* mStreamNotify;
|
||||
|
||||
struct PendingData
|
||||
{
|
||||
|
@ -143,7 +195,7 @@ private:
|
|||
* stack frame. It instead posts a runnable using this tracker to cancel
|
||||
* in case we are destroyed.
|
||||
*/
|
||||
ScopedRunnableMethodFactory<BrowserStreamChild> mDeliverDataTracker;
|
||||
ScopedRunnableMethodFactory<BrowserStreamChild> mDeliveryTracker;
|
||||
base::RepeatingTimer<BrowserStreamChild> mSuspendedTimer;
|
||||
};
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ parent:
|
|||
/**
|
||||
* Covers both NPN_GetURLNotify and NPN_PostURLNotify.
|
||||
* @TODO This would be more readable as an overloaded method,
|
||||
* but IPDL doesn't allow that for constructors (or any method?).
|
||||
* but IPDL doesn't allow that for constructors.
|
||||
*/
|
||||
rpc PStreamNotify(nsCString url, nsCString target, bool post,
|
||||
nsCString buffer, bool file)
|
||||
|
|
|
@ -20,7 +20,7 @@ child:
|
|||
/**
|
||||
* Represents NPP_URLNotify
|
||||
*/
|
||||
rpc __delete__(NPReason reason);
|
||||
async __delete__(NPReason reason);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -75,11 +75,11 @@ using mozilla::gfx::SharedDIB;
|
|||
#endif // defined(OS_WIN)
|
||||
|
||||
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
||||
const nsCString& aMimeType) :
|
||||
mPluginIface(aPluginIface)
|
||||
const nsCString& aMimeType)
|
||||
: mPluginIface(aPluginIface)
|
||||
, mQuirks(0)
|
||||
, mCachedWindowActor(nsnull)
|
||||
, mCachedElementActor(nsnull)
|
||||
, mQuirks(0)
|
||||
#if defined(OS_WIN)
|
||||
, mPluginWindowHWND(0)
|
||||
, mPluginWndProc(0)
|
||||
|
@ -1288,9 +1288,7 @@ PluginInstanceChild::AnswerPBrowserStreamConstructor(
|
|||
{
|
||||
AssertPluginThread();
|
||||
*rv = static_cast<BrowserStreamChild*>(aActor)
|
||||
->StreamConstructed(url, length, lastmodified,
|
||||
notifyData, headers, mimeType, seekable,
|
||||
stype);
|
||||
->StreamConstructed(mimeType, seekable, stype);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1306,7 +1304,8 @@ PluginInstanceChild::AllocPBrowserStream(const nsCString& url,
|
|||
uint16_t *stype)
|
||||
{
|
||||
AssertPluginThread();
|
||||
return new BrowserStreamChild(this, url, length, lastmodified, notifyData,
|
||||
return new BrowserStreamChild(this, url, length, lastmodified,
|
||||
static_cast<StreamNotifyChild*>(notifyData),
|
||||
headers, mimeType, seekable, rv, stype);
|
||||
}
|
||||
|
||||
|
@ -1348,29 +1347,58 @@ PluginInstanceChild::AllocPStreamNotify(const nsCString& url,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
StreamNotifyChild::Answer__delete__(const NPReason& reason)
|
||||
void
|
||||
StreamNotifyChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
AssertPluginThread();
|
||||
return static_cast<PluginInstanceChild*>(Manager())
|
||||
->NotifyStream(this, reason);
|
||||
if (AncestorDeletion == why && mBrowserStream) {
|
||||
NS_ERROR("Pending NPP_URLNotify not called when closing an instance.");
|
||||
|
||||
// reclaim responsibility for deleting ourself
|
||||
mBrowserStream = NULL;
|
||||
mBrowserStream->mStreamNotify = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StreamNotifyChild::SetAssociatedStream(BrowserStreamChild* bs)
|
||||
{
|
||||
NS_ASSERTION(bs, "Shouldn't be null");
|
||||
NS_ASSERTION(!mBrowserStream, "Two streams for one streamnotify?");
|
||||
|
||||
mBrowserStream = bs;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::NotifyStream(StreamNotifyChild* notifyData,
|
||||
NPReason reason)
|
||||
StreamNotifyChild::Recv__delete__(const NPReason& reason)
|
||||
{
|
||||
if (notifyData->mClosure)
|
||||
mPluginIface->urlnotify(&mData, notifyData->mURL.get(), reason,
|
||||
notifyData->mClosure);
|
||||
AssertPluginThread();
|
||||
|
||||
if (mBrowserStream)
|
||||
mBrowserStream->NotifyPending();
|
||||
else
|
||||
NPP_URLNotify(reason);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
StreamNotifyChild::NPP_URLNotify(NPReason reason)
|
||||
{
|
||||
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(Manager());
|
||||
|
||||
if (mClosure)
|
||||
instance->mPluginIface->urlnotify(instance->GetNPP(), mURL.get(),
|
||||
reason, mClosure);
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild* notifyData)
|
||||
{
|
||||
AssertPluginThread();
|
||||
delete notifyData;
|
||||
|
||||
if (!static_cast<StreamNotifyChild*>(notifyData)->mBrowserStream)
|
||||
delete notifyData;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1506,6 +1534,19 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
|||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
|
||||
nsTArray<PBrowserStreamChild*> streams;
|
||||
ManagedPBrowserStreamChild(streams);
|
||||
|
||||
// First make sure none of these streams become deleted
|
||||
for (PRUint32 i = 0; i < streams.Length(); ) {
|
||||
if (static_cast<BrowserStreamChild*>(streams[i])->InstanceDying())
|
||||
++i;
|
||||
else
|
||||
streams.RemoveElementAt(i);
|
||||
}
|
||||
for (PRUint32 i = 0; i < streams.Length(); ++i)
|
||||
static_cast<BrowserStreamChild*>(streams[i])->FinishDelivery();
|
||||
|
||||
for (PRUint32 i = 0; i < mPendingAsyncCalls.Length(); ++i)
|
||||
mPendingAsyncCalls[i]->Cancel();
|
||||
mPendingAsyncCalls.TruncateLength(0);
|
||||
|
|
|
@ -59,11 +59,13 @@ namespace plugins {
|
|||
|
||||
class PBrowserStreamChild;
|
||||
class BrowserStreamChild;
|
||||
class StreamNotifyChild;
|
||||
|
||||
class PluginInstanceChild : public PPluginInstanceChild
|
||||
{
|
||||
friend class BrowserStreamChild;
|
||||
friend class PluginStreamChild;
|
||||
friend class StreamNotifyChild;
|
||||
|
||||
#ifdef OS_WIN
|
||||
friend LRESULT CALLBACK PluginWindowProc(HWND hWnd,
|
||||
|
@ -183,8 +185,6 @@ public:
|
|||
|
||||
void InvalidateRect(NPRect* aInvalidRect);
|
||||
|
||||
bool NotifyStream(StreamNotifyChild* notifyData, NPReason reason);
|
||||
|
||||
uint32_t ScheduleTimer(uint32_t interval, bool repeat, TimerFunc func);
|
||||
void UnscheduleTimer(uint32_t id);
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class BrowserStreamChild;
|
||||
|
||||
class StreamNotifyChild : public PStreamNotifyChild
|
||||
{
|
||||
friend class PluginInstanceChild;
|
||||
|
@ -53,17 +55,37 @@ public:
|
|||
StreamNotifyChild(const nsCString& aURL)
|
||||
: mURL(aURL)
|
||||
, mClosure(NULL)
|
||||
, mBrowserStream(NULL)
|
||||
{ }
|
||||
|
||||
NS_OVERRIDE virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
void SetValid(void* aClosure) {
|
||||
mClosure = aClosure;
|
||||
}
|
||||
|
||||
bool Answer__delete__(const NPReason& reason);
|
||||
void NPP_URLNotify(NPReason reason);
|
||||
|
||||
private:
|
||||
NS_OVERRIDE virtual bool Recv__delete__(const NPReason& reason);
|
||||
|
||||
/**
|
||||
* If a stream is created for this this URLNotify, we associate the objects
|
||||
* so that the NPP_URLNotify call is not fired before the stream data is
|
||||
* completely delivered. The BrowserStreamChild takes responsibility for
|
||||
* calling NPP_URLNotify and deleting this object.
|
||||
*/
|
||||
void SetAssociatedStream(BrowserStreamChild* bs);
|
||||
|
||||
nsCString mURL;
|
||||
void* mClosure;
|
||||
|
||||
/**
|
||||
* If mBrowserStream is true, it is responsible for deleting this C++ object
|
||||
* and DeallocPStreamNotify is not, so that the delayed delivery of
|
||||
* NPP_URLNotify is possible.
|
||||
*/
|
||||
BrowserStreamChild* mBrowserStream;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
Загрузка…
Ссылка в новой задаче