Bug 542700 - Async calls aren't cancelled when the instance is destroyed, and the list of pending calls isn't protected against simultaneous access, r=cjones

--HG--
extra : rebase_source : b0949fd4921d1dbb558e84e191387964af5767fc
This commit is contained in:
Benjamin Smedberg 2010-03-25 14:25:38 -04:00
parent fc1d594cb2
commit 2e0b8d0752
4 changed files with 28 additions and 7 deletions

View File

@ -64,9 +64,11 @@ void
ChildAsyncCall::Run()
{
if (mFunc) {
MutexAutoLock lock(mInstance->mAsyncCallMutex);
mInstance->mPendingAsyncCalls.RemoveElement(this);
mFunc(mData);
}
if (mFunc)
mFunc(mData);
}
} // namespace plugins

View File

@ -42,6 +42,7 @@
#include "BrowserStreamChild.h"
#include "PluginStreamChild.h"
#include "StreamNotifyChild.h"
#include "PluginThreadChild.h"
#include "mozilla/ipc/SyncChannel.h"
@ -97,6 +98,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
, mCachedWinlessPluginHWND(0)
, mWinlessPopupSurrogateHWND(0)
#endif // OS_WIN
, mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex")
{
memset(&mWindow, 0, sizeof(mWindow));
mData.ndata = (void*) this;
@ -1724,6 +1726,18 @@ PluginInstanceChild::UnscheduleTimer(uint32_t id)
mTimers.RemoveElement(id, ChildTimer::IDComparator());
}
void
PluginInstanceChild::AsyncCall(PluginThreadCallback aFunc, void* aUserData)
{
ChildAsyncCall* task = new ChildAsyncCall(this, aFunc, aUserData);
{
MutexAutoLock lock(mAsyncCallMutex);
mPendingAsyncCalls.AppendElement(task);
}
PluginThreadChild::current()->message_loop()->PostTask(FROM_HERE, task);
}
static PLDHashOperator
InvalidateObject(DeletingObjectEntry* e, void* userArg)
{
@ -1776,9 +1790,12 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
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);
{
MutexAutoLock lock(mAsyncCallMutex);
for (PRUint32 i = 0; i < mPendingAsyncCalls.Length(); ++i)
mPendingAsyncCalls[i]->Cancel();
mPendingAsyncCalls.TruncateLength(0);
}
mTimers.Clear();

View File

@ -194,6 +194,8 @@ public:
uint32_t ScheduleTimer(uint32_t interval, bool repeat, TimerFunc func);
void UnscheduleTimer(uint32_t id);
void AsyncCall(PluginThreadCallback aFunc, void* aUserData);
private:
friend class PluginModuleChild;
@ -282,6 +284,8 @@ private:
#endif
friend class ChildAsyncCall;
Mutex mAsyncCallMutex;
nsTArray<ChildAsyncCall*> mPendingAsyncCalls;
nsTArray<nsAutoPtr<ChildTimer> > mTimers;

View File

@ -1324,9 +1324,7 @@ _pluginthreadasynccall(NPP aNPP,
if (!aFunc)
return;
PluginThreadChild::current()->message_loop()
->PostTask(FROM_HERE, new ChildAsyncCall(InstCast(aNPP), aFunc,
aUserData));
InstCast(aNPP)->AsyncCall(aFunc, aUserData);
}
NPError NP_CALLBACK