From d8f6fca3abdc51fc3b99df1b005c33f48f5fe6af Mon Sep 17 00:00:00 2001 From: Ben Turner Date: Thu, 8 Oct 2009 12:11:13 -0700 Subject: [PATCH] Add threadsafety assertions to plugin code --- dom/plugins/BrowserStreamChild.cpp | 12 ++++ dom/plugins/PluginInstanceChild.cpp | 28 ++++++++ dom/plugins/PluginMessageUtils.h | 7 ++ dom/plugins/PluginModuleChild.cpp | 71 +++++++++++++++++++- dom/plugins/PluginScriptableObjectChild.cpp | 49 ++++++++++++++ dom/plugins/PluginScriptableObjectParent.cpp | 6 ++ dom/plugins/PluginStreamChild.cpp | 4 ++ ipc/glue/AsyncChannel.cpp | 7 ++ ipc/glue/AsyncChannel.h | 15 +++++ ipc/glue/RPCChannel.cpp | 7 ++ ipc/glue/SyncChannel.cpp | 5 ++ 11 files changed, 210 insertions(+), 1 deletion(-) diff --git a/dom/plugins/BrowserStreamChild.cpp b/dom/plugins/BrowserStreamChild.cpp index f1a06dcc676..f051567150b 100644 --- a/dom/plugins/BrowserStreamChild.cpp +++ b/dom/plugins/BrowserStreamChild.cpp @@ -57,6 +57,8 @@ BrowserStreamChild::BrowserStreamChild(PluginInstanceChild* instance, , mURL(url) , mHeaders(headers) { + AssertPluginThread(); + memset(&mStream, 0, sizeof(mStream)); mStream.ndata = static_cast(this); if (!mURL.IsEmpty()) @@ -80,6 +82,8 @@ bool BrowserStreamChild::AnswerNPP_WriteReady(const int32_t& newlength, int32_t *size) { + AssertPluginThread(); + if (mClosed) { *size = 0; return true; @@ -96,6 +100,9 @@ BrowserStreamChild::AnswerNPP_Write(const int32_t& offset, const Buffer& data, int32_t* consumed) { + _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + if (mClosed) { *consumed = -1; return true; @@ -111,6 +118,7 @@ bool BrowserStreamChild::AnswerNPP_StreamAsFile(const nsCString& fname) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); printf("mClosed: %i\n", mClosed); if (mClosed) @@ -124,6 +132,8 @@ BrowserStreamChild::AnswerNPP_StreamAsFile(const nsCString& fname) NPError BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList) { + AssertPluginThread(); + IPCByteRanges ranges; for (; aRangeList; aRangeList = aRangeList->next) { IPCByteRange br = {aRangeList->offset, aRangeList->length}; @@ -139,6 +149,8 @@ BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList) void BrowserStreamChild::NPP_DestroyStream(NPError reason) { + AssertPluginThread(); + if (mClosed) return; diff --git a/dom/plugins/PluginInstanceChild.cpp b/dom/plugins/PluginInstanceChild.cpp index 66bfa697d5d..4656689cae2 100644 --- a/dom/plugins/PluginInstanceChild.cpp +++ b/dom/plugins/PluginInstanceChild.cpp @@ -70,6 +70,7 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar, { printf ("[PluginInstanceChild] NPN_GetValue(%s)\n", NPNVariableToString(aVar)); + AssertPluginThread(); switch(aVar) { @@ -179,6 +180,7 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue) { printf ("[PluginInstanceChild] NPN_SetValue(%s, %ld)\n", NPPVariableToString(aVar), reinterpret_cast(aValue)); + AssertPluginThread(); switch (aVar) { case NPPVpluginWindowBool: { @@ -212,6 +214,8 @@ bool PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWindow( bool* windowed, NPError* rv) { + AssertPluginThread(); + NPBool isWindowed; *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginWindowBool, reinterpret_cast(&isWindowed)); @@ -223,6 +227,8 @@ bool PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginTransparent( bool* transparent, NPError* rv) { + AssertPluginThread(); + NPBool isTransparent; *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginTransparentBool, reinterpret_cast(&isTransparent)); @@ -234,6 +240,8 @@ bool PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNeedsXEmbed( bool* needs, NPError* rv) { + AssertPluginThread(); + #ifdef OS_LINUX NPBool needsXEmbed; @@ -255,6 +263,7 @@ PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject( PPluginScriptableObjectChild** value, NPError* result) { + AssertPluginThread(); NPObject* object; *result = mPluginIface->getvalue(GetNPP(), NPPVpluginScriptableNPObject, @@ -283,6 +292,7 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPEvent& event, int16_t* handled) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); #if defined(OS_LINUX) && defined(DEBUG_cjones) if (GraphicsExpose == event.type) @@ -334,6 +344,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow, aWindow.window, aWindow.x, aWindow.y, aWindow.width, aWindow.height); + AssertPluginThread(); #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) // The minimum info is sent over IPC to allow this @@ -563,6 +574,8 @@ PluginInstanceChild::PluginWindowProc(HWND hWnd, PPluginScriptableObjectChild* PluginInstanceChild::AllocPPluginScriptableObject() { + AssertPluginThread(); + nsAutoPtr* object = mScriptableObjects.AppendElement(); NS_ENSURE_TRUE(object, nsnull); @@ -577,6 +590,8 @@ bool PluginInstanceChild::DeallocPPluginScriptableObject( PPluginScriptableObjectChild* aObject) { + AssertPluginThread(); + PluginScriptableObjectChild* object = reinterpret_cast(aObject); @@ -601,6 +616,8 @@ bool PluginInstanceChild::AnswerPPluginScriptableObjectConstructor( PPluginScriptableObjectChild* aActor) { + AssertPluginThread(); + // This is only called in response to the parent process requesting the // creation of an actor. This actor will represent an NPObject that is // created by the browser and returned to the plugin. @@ -632,6 +649,7 @@ PluginInstanceChild::AllocPBrowserStream(const nsCString& url, NPError* rv, uint16_t *stype) { + AssertPluginThread(); return new BrowserStreamChild(this, url, length, lastmodified, notifyData, headers, mimeType, seekable, rv, stype); } @@ -641,6 +659,7 @@ PluginInstanceChild::AnswerPBrowserStreamDestructor(PBrowserStreamChild* stream, const NPError& reason, const bool& artificial) { + AssertPluginThread(); if (!artificial) static_cast(stream)->NPP_DestroyStream(reason); return true; @@ -651,6 +670,7 @@ PluginInstanceChild::DeallocPBrowserStream(PBrowserStreamChild* stream, const NPError& reason, const bool& artificial) { + AssertPluginThread(); delete stream; return true; } @@ -669,6 +689,7 @@ PluginInstanceChild::AnswerPPluginStreamDestructor(PPluginStreamChild* stream, const NPReason& reason, const bool& artificial) { + AssertPluginThread(); if (!artificial) { static_cast(stream)->NPP_DestroyStream(reason); } @@ -680,6 +701,7 @@ PluginInstanceChild::DeallocPPluginStream(PPluginStreamChild* stream, const NPError& reason, const bool& artificial) { + AssertPluginThread(); delete stream; return true; } @@ -692,6 +714,7 @@ PluginInstanceChild::AllocPStreamNotify(const nsCString& url, const bool& file, NPError* result) { + AssertPluginThread(); NS_RUNTIMEABORT("not reached"); return NULL; } @@ -700,6 +723,8 @@ bool PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild* notifyData, const NPReason& reason) { + AssertPluginThread(); + StreamNotifyChild* sn = static_cast(notifyData); mPluginIface->urlnotify(&mData, sn->mURL.get(), reason, sn->mClosure); delete sn; @@ -710,6 +735,7 @@ PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild* notifyData, PluginScriptableObjectChild* PluginInstanceChild::GetActorForNPObject(NPObject* aObject) { + AssertPluginThread(); NS_ASSERTION(aObject, "Null pointer!"); if (aObject->_class == PluginScriptableObjectChild::GetClass()) { @@ -745,6 +771,8 @@ NPError PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow, NPStream** aStream) { + AssertPluginThread(); + PluginStreamChild* ps = new PluginStreamChild(this); NPError result; diff --git a/dom/plugins/PluginMessageUtils.h b/dom/plugins/PluginMessageUtils.h index d0e32868922..151dd265cbe 100644 --- a/dom/plugins/PluginMessageUtils.h +++ b/dom/plugins/PluginMessageUtils.h @@ -45,6 +45,7 @@ #include "npruntime.h" #include "nsAutoPtr.h" #include "nsStringGlue.h" +#include "nsThreadUtils.h" namespace mozilla { @@ -161,6 +162,12 @@ NPNVariableToString(NPNVariable aVar) #undef VARSTR +inline void AssertPluginThread() +{ + NS_ASSERTION(NS_IsMainThread(), "should be on the plugin's main thread!"); +} + + } /* namespace plugins */ } /* namespace mozilla */ diff --git a/dom/plugins/PluginModuleChild.cpp b/dom/plugins/PluginModuleChild.cpp index cfb7d2015cc..b8b11c661f2 100644 --- a/dom/plugins/PluginModuleChild.cpp +++ b/dom/plugins/PluginModuleChild.cpp @@ -195,6 +195,7 @@ bool PluginModuleChild::RegisterNPObject(NPObject* aObject, PluginScriptableObjectChild* aActor) { + AssertPluginThread(); NS_ASSERTION(mObjectMap.IsInitialized(), "Not initialized!"); NS_ASSERTION(aObject && aActor, "Null pointer!"); NS_ASSERTION(!mObjectMap.Get(aObject, nsnull), @@ -205,6 +206,7 @@ PluginModuleChild::RegisterNPObject(NPObject* aObject, void PluginModuleChild::UnregisterNPObject(NPObject* aObject) { + AssertPluginThread(); NS_ASSERTION(mObjectMap.IsInitialized(), "Not initialized!"); NS_ASSERTION(aObject, "Null pointer!"); NS_ASSERTION(mObjectMap.Get(aObject, nsnull), @@ -215,6 +217,7 @@ PluginModuleChild::UnregisterNPObject(NPObject* aObject) PluginScriptableObjectChild* PluginModuleChild::GetActorForNPObject(NPObject* aObject) { + AssertPluginThread(); NS_ASSERTION(mObjectMap.IsInitialized(), "Not initialized!"); NS_ASSERTION(aObject, "Null pointer!"); PluginScriptableObjectChild* actor; @@ -478,6 +481,8 @@ _requestread(NPStream* aStream, NPByteRange* aRangeList) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + BrowserStreamChild* bs = static_cast(static_cast(aStream->ndata)); bs->EnsureCorrectStream(aStream); @@ -491,6 +496,7 @@ _geturlnotify(NPP aNPP, void* aNotifyData) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); nsCString url = NullableString(aRelativeURL); NPError err; @@ -507,6 +513,7 @@ _getvalue(NPP aNPP, void* aValue) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); return InstCast(aNPP)->NPN_GetValue(aVariable, aValue); } @@ -517,6 +524,7 @@ _setvalue(NPP aNPP, void* aValue) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); return InstCast(aNPP)->NPN_SetValue(aVariable, aValue); } @@ -526,6 +534,8 @@ _geturl(NPP aNPP, const char* aTarget) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + NPError err; InstCast(aNPP)->CallNPN_GetURL(NullableString(aRelativeURL), NullableString(aTarget), &err); @@ -542,6 +552,7 @@ _posturlnotify(NPP aNPP, void* aNotifyData) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); nsCString url = NullableString(aRelativeURL); NPError err; @@ -563,6 +574,8 @@ _posturl(NPP aNPP, NPBool aIsFile) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + NPError err; // FIXME what should happen when |aBuffer| is null? InstCast(aNPP)->CallNPN_PostURL(NullableString(aRelativeURL), @@ -579,6 +592,7 @@ _newstream(NPP aNPP, NPStream** aStream) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); return InstCast(aNPP)->NPN_NewStream(aMIMEType, aWindow, aStream); } @@ -589,6 +603,8 @@ _write(NPP aNPP, void* aBuffer) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + PluginStreamChild* ps = static_cast(static_cast(aStream->ndata)); ps->EnsureCorrectInstance(InstCast(aNPP)); @@ -602,6 +618,8 @@ _destroystream(NPP aNPP, NPError aReason) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + PluginInstanceChild* p = InstCast(aNPP); AStream* s = static_cast(aStream->ndata); if (s->IsBrowserStream()) { @@ -622,12 +640,14 @@ _status(NPP aNPP, const char* aMessage) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); } void NP_CALLBACK _memfree(void* aPtr) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_Free(aPtr); } @@ -635,6 +655,7 @@ uint32_t NP_CALLBACK _memflush(uint32_t aSize) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); return 0; } @@ -642,6 +663,7 @@ void NP_CALLBACK _reloadplugins(NPBool aReloadPages) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); } void NP_CALLBACK @@ -649,6 +671,7 @@ _invalidaterect(NPP aNPP, NPRect* aInvalidRect) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); InstCast(aNPP)->SendNPN_InvalidateRect(*aInvalidRect); } @@ -657,6 +680,7 @@ _invalidateregion(NPP aNPP, NPRegion aInvalidRegion) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); // Not implemented in Mozilla. } @@ -664,12 +688,14 @@ void NP_CALLBACK _forceredraw(NPP aNPP) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); } const char* NP_CALLBACK _useragent(NPP aNPP) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); PluginModuleChild::current()->CallNPN_UserAgent(&gUserAgent); return NullableStringGet(gUserAgent); @@ -679,6 +705,7 @@ void* NP_CALLBACK _memalloc(uint32_t aSize) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); return NS_Alloc(aSize); } @@ -687,6 +714,7 @@ void* NP_CALLBACK /* OJI type: JRIEnv* */ _getjavaenv(void) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); return 0; } @@ -694,6 +722,7 @@ void* NP_CALLBACK /* OJI type: jref */ _getjavapeer(NPP aNPP) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); return 0; } @@ -701,6 +730,7 @@ NPIdentifier NP_CALLBACK _getstringidentifier(const NPUTF8* aName) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NPRemoteIdentifier ident; if (!PluginModuleChild::current()-> @@ -718,6 +748,7 @@ _getstringidentifiers(const NPUTF8** aNames, NPIdentifier* aIdentifiers) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!(aNames && aNameCount > 0 && aIdentifiers)) { NS_RUNTIMEABORT("Bad input! Headed for a crash!"); @@ -755,6 +786,7 @@ bool NP_CALLBACK _identifierisstring(NPIdentifier aIdentifier) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); bool isString; if (!PluginModuleChild::current()-> @@ -771,6 +803,7 @@ NPIdentifier NP_CALLBACK _getintidentifier(int32_t aIntId) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NPRemoteIdentifier ident; if (!PluginModuleChild::current()-> @@ -786,6 +819,7 @@ NPUTF8* NP_CALLBACK _utf8fromidentifier(NPIdentifier aIdentifier) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NPError err; nsCAutoString val; @@ -803,6 +837,7 @@ int32_t NP_CALLBACK _intfromidentifier(NPIdentifier aIdentifier) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NPError err; int32_t val; @@ -822,6 +857,7 @@ _createobject(NPP aNPP, NPClass* aClass) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NPObject* newObject; if (aClass && aClass->allocate) { @@ -841,6 +877,8 @@ _createobject(NPP aNPP, NPObject* NP_CALLBACK _retainobject(NPObject* aNPObj) { + AssertPluginThread(); + #ifdef DEBUG printf("[PluginModuleChild] %s: object %p, refcnt %d\n", __FUNCTION__, aNPObj, aNPObj->referenceCount + 1); @@ -852,6 +890,8 @@ _retainobject(NPObject* aNPObj) void NP_CALLBACK _releaseobject(NPObject* aNPObj) { + AssertPluginThread(); + #ifdef DEBUG printf("[PluginModuleChild] %s: object %p, refcnt %d\n", __FUNCTION__, aNPObj, aNPObj->referenceCount - 1); @@ -875,6 +915,7 @@ _invoke(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invoke) return false; @@ -890,6 +931,7 @@ _invokedefault(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invokeDefault) return false; @@ -904,6 +946,8 @@ _evaluate(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + NS_NOTYETIMPLEMENTED("Implement me!"); return false; } @@ -915,6 +959,7 @@ _getproperty(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->getProperty) return false; @@ -929,6 +974,7 @@ _setproperty(NPP aNPP, const NPVariant* aValue) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->setProperty) return false; @@ -942,6 +988,7 @@ _removeproperty(NPP aNPP, NPIdentifier aPropertyName) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->removeProperty) return false; @@ -955,6 +1002,7 @@ _hasproperty(NPP aNPP, NPIdentifier aPropertyName) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasProperty) return false; @@ -968,6 +1016,7 @@ _hasmethod(NPP aNPP, NPIdentifier aMethodName) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasMethod) return false; @@ -982,6 +1031,7 @@ _enumerate(NPP aNPP, uint32_t* aCount) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class) return false; @@ -1004,6 +1054,7 @@ _construct(NPP aNPP, NPVariant* aResult) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); if (!aNPP || !aNPObj || !aNPObj->_class || !NP_CLASS_STRUCT_VERSION_HAS_CTOR(aNPObj->_class) || @@ -1018,6 +1069,8 @@ void NP_CALLBACK _releasevariantvalue(NPVariant* aVariant) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + if (NPVARIANT_IS_STRING(*aVariant)) { NPString str = NPVARIANT_TO_STRING(*aVariant); free(const_cast(str.UTF8Characters)); @@ -1036,6 +1089,7 @@ _setexception(NPObject* aNPObj, const NPUTF8* aMessage) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); } @@ -1044,6 +1098,7 @@ _pushpopupsenabledstate(NPP aNPP, NPBool aEnabled) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return false; } @@ -1052,6 +1107,7 @@ bool NP_CALLBACK _poppopupsenabledstate(NPP aNPP) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return false; } @@ -1062,6 +1118,7 @@ _pluginthreadasynccall(NPP aNPP, void* aUserData) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); } @@ -1070,6 +1127,7 @@ _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url, char **value, uint32_t *len) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1079,6 +1137,7 @@ _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url, const char *value, uint32_t len) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1091,6 +1150,7 @@ _getauthenticationinfo(NPP npp, const char *protocol, char **password, uint32_t *plen) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1100,6 +1160,7 @@ _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return 0; } @@ -1107,14 +1168,16 @@ _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, void NP_CALLBACK _unscheduletimer(NPP instance, uint32_t timerID) { - NS_NOTYETIMPLEMENTED("Implement me!"); _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); + NS_NOTYETIMPLEMENTED("Implement me!"); } NPError NP_CALLBACK _popupcontextmenu(NPP instance, NPMenu* menu) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return NPERR_GENERIC_ERROR; } @@ -1125,6 +1188,7 @@ _convertpoint(NPP instance, double *destX, double *destY, NPCoordinateSpace destSpace) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); NS_NOTYETIMPLEMENTED("Implement me!"); return 0; } @@ -1135,6 +1199,7 @@ bool PluginModuleChild::AnswerNP_Initialize(NPError* _retval) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); #if defined(OS_LINUX) *_retval = mInitializeFunc(&sBrowserFuncs, &mFunctions); @@ -1164,6 +1229,7 @@ PluginModuleChild::AllocPPluginInstance(const nsCString& aMimeType, NPError* rv) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); nsAutoPtr childInstance( new PluginInstanceChild(&mFunctions)); @@ -1183,6 +1249,7 @@ PluginModuleChild::AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor NPError* rv) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); PluginInstanceChild* childInstance = reinterpret_cast(aActor); @@ -1229,6 +1296,7 @@ PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* aActor, NPError* rv) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); delete aActor; @@ -1240,6 +1308,7 @@ PluginModuleChild::AnswerPPluginInstanceDestructor(PPluginInstanceChild* aActor, NPError* rv) { _MOZ_LOG(__FUNCTION__); + AssertPluginThread(); PluginInstanceChild* inst = static_cast(aActor); *rv = mFunctions.destroy(inst->GetNPP(), 0); diff --git a/dom/plugins/PluginScriptableObjectChild.cpp b/dom/plugins/PluginScriptableObjectChild.cpp index fd1015373b1..d170e352cd3 100644 --- a/dom/plugins/PluginScriptableObjectChild.cpp +++ b/dom/plugins/PluginScriptableObjectChild.cpp @@ -174,6 +174,8 @@ NPObject* PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance, NPClass* aClass) { + AssertPluginThread(); + NS_ASSERTION(aClass == PluginScriptableObjectChild::GetClass(), "Huh?! Wrong class!"); @@ -189,6 +191,8 @@ PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance, void PluginScriptableObjectChild::ScriptableInvalidate(NPObject* aObject) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return; @@ -221,6 +225,8 @@ PluginScriptableObjectChild::ScriptableInvalidate(NPObject* aObject) void PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return; @@ -241,6 +247,8 @@ bool PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject, NPIdentifier aName) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -272,6 +280,8 @@ PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject, uint32_t aArgCount, NPVariant* aResult) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -323,6 +333,8 @@ PluginScriptableObjectChild::ScriptableInvokeDefault(NPObject* aObject, uint32_t aArgCount, NPVariant* aResult) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -371,6 +383,8 @@ bool PluginScriptableObjectChild::ScriptableHasProperty(NPObject* aObject, NPIdentifier aName) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -400,6 +414,8 @@ PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject, NPIdentifier aName, NPVariant* aResult) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -435,6 +451,8 @@ PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject, NPIdentifier aName, const NPVariant* aValue) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -469,6 +487,8 @@ bool PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject, NPIdentifier aName) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -498,6 +518,8 @@ PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject, NPIdentifier** aIdentifiers, uint32_t* aCount) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -549,6 +571,8 @@ PluginScriptableObjectChild::ScriptableConstruct(NPObject* aObject, uint32_t aArgCount, NPVariant* aResult) { + AssertPluginThread(); + if (aObject->_class != PluginScriptableObjectChild::GetClass()) { NS_ERROR("Don't know what kind of object this is!"); return false; @@ -612,10 +636,13 @@ PluginScriptableObjectChild::PluginScriptableObjectChild() : mInstance(nsnull), mObject(nsnull) { + AssertPluginThread(); } PluginScriptableObjectChild::~PluginScriptableObjectChild() { + AssertPluginThread(); + if (mObject) { if (mObject->_class == GetClass()) { if (!static_cast(mObject)->invalidated) { @@ -633,6 +660,8 @@ void PluginScriptableObjectChild::Initialize(PluginInstanceChild* aInstance, NPObject* aObject) { + AssertPluginThread(); + NS_ASSERTION(!(mInstance && mObject), "Calling Initialize class twice!"); if (aObject->_class == GetClass()) { @@ -660,6 +689,8 @@ PluginScriptableObjectChild::Initialize(PluginInstanceChild* aInstance, bool PluginScriptableObjectChild::AnswerInvalidate() { + AssertPluginThread(); + if (mObject) { NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!"); if (mObject->_class && mObject->_class->invalidate) { @@ -675,6 +706,8 @@ bool PluginScriptableObjectChild::AnswerHasMethod(const NPRemoteIdentifier& aId, bool* aHasMethod) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerHasMethod with an invalidated object!"); *aHasMethod = false; @@ -698,6 +731,8 @@ PluginScriptableObjectChild::AnswerInvoke(const NPRemoteIdentifier& aId, Variant* aResult, bool* aSuccess) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerInvoke with an invalidated object!"); *aResult = void_t(); @@ -762,6 +797,8 @@ PluginScriptableObjectChild::AnswerInvokeDefault(const nsTArray& aArgs, Variant* aResult, bool* aSuccess) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerInvokeDefault with an invalidated object!"); *aResult = void_t(); @@ -825,6 +862,8 @@ bool PluginScriptableObjectChild::AnswerHasProperty(const NPRemoteIdentifier& aId, bool* aHasProperty) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerHasProperty with an invalidated object!"); *aHasProperty = false; @@ -847,6 +886,8 @@ PluginScriptableObjectChild::AnswerGetProperty(const NPRemoteIdentifier& aId, Variant* aResult, bool* aSuccess) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerGetProperty with an invalidated object!"); *aResult = void_t(); @@ -886,6 +927,8 @@ PluginScriptableObjectChild::AnswerSetProperty(const NPRemoteIdentifier& aId, const Variant& aValue, bool* aSuccess) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerSetProperty with an invalidated object!"); *aSuccess = false; @@ -913,6 +956,8 @@ bool PluginScriptableObjectChild::AnswerRemoveProperty(const NPRemoteIdentifier& aId, bool* aSuccess) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!"); *aSuccess = false; @@ -934,6 +979,8 @@ bool PluginScriptableObjectChild::AnswerEnumerate(nsTArray* aProperties, bool* aSuccess) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerEnumerate with an invalidated object!"); *aSuccess = false; @@ -978,6 +1025,8 @@ PluginScriptableObjectChild::AnswerConstruct(const nsTArray& aArgs, Variant* aResult, bool* aSuccess) { + AssertPluginThread(); + if (!mObject) { NS_WARNING("Calling AnswerConstruct with an invalidated object!"); *aResult = void_t(); diff --git a/dom/plugins/PluginScriptableObjectParent.cpp b/dom/plugins/PluginScriptableObjectParent.cpp index 454185c5fdb..56ca104cb5e 100644 --- a/dom/plugins/PluginScriptableObjectParent.cpp +++ b/dom/plugins/PluginScriptableObjectParent.cpp @@ -1129,6 +1129,7 @@ PluginScriptableObjectParent::AnswerSetProperty(const NPRemoteIdentifier& aId, PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); + *aResult = void_t(); *aSuccess = false; return true; } @@ -1136,12 +1137,14 @@ PluginScriptableObjectParent::AnswerSetProperty(const NPRemoteIdentifier& aId, const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); + *aResult = void_t(); *aSuccess = false; return true; } if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) { NS_WARNING("Invalid NPIdentifier!"); + *aResult = void_t(); *aSuccess = false; return true; } @@ -1174,6 +1177,7 @@ PluginScriptableObjectParent::AnswerRemoveProperty(const NPRemoteIdentifier& aId PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); + *aResult = void_t(); *aSuccess = false; return true; } @@ -1181,6 +1185,7 @@ PluginScriptableObjectParent::AnswerRemoveProperty(const NPRemoteIdentifier& aId const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); + *aResult = void_t(); *aSuccess = false; return true; } @@ -1211,6 +1216,7 @@ PluginScriptableObjectParent::AnswerEnumerate(nsTArray* aPro PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); + *aResult = void_t(); *aSuccess = false; return true; } diff --git a/dom/plugins/PluginStreamChild.cpp b/dom/plugins/PluginStreamChild.cpp index 34c81cc4781..18735ea095d 100644 --- a/dom/plugins/PluginStreamChild.cpp +++ b/dom/plugins/PluginStreamChild.cpp @@ -51,6 +51,8 @@ PluginStreamChild::PluginStreamChild(PluginInstanceChild* instance) int32_t PluginStreamChild::NPN_Write(int32_t length, void* buffer) { + AssertPluginThread(); + int32_t written = 0; CallNPN_Write(nsCString(static_cast(buffer), length), &written); @@ -63,6 +65,8 @@ PluginStreamChild::NPN_Write(int32_t length, void* buffer) void PluginStreamChild::NPP_DestroyStream(NPError reason) { + AssertPluginThread(); + if (mClosed) return; diff --git a/ipc/glue/AsyncChannel.cpp b/ipc/glue/AsyncChannel.cpp index ca0f5080caf..391383875c9 100644 --- a/ipc/glue/AsyncChannel.cpp +++ b/ipc/glue/AsyncChannel.cpp @@ -112,6 +112,7 @@ AsyncChannel::Close() bool AsyncChannel::Send(Message* msg) { + AssertWorkerThread(); NS_ABORT_IF_FALSE(MSG_ROUTING_NONE != msg->routing_id(), "need a route"); if (!Connected()) @@ -126,6 +127,7 @@ AsyncChannel::Send(Message* msg) void AsyncChannel::OnDispatchMessage(const Message& msg) { + AssertWorkerThread(); NS_ASSERTION(!msg.is_reply(), "can't process replies here"); NS_ASSERTION(!(msg.is_sync() || msg.is_rpc()), "async dispatch only"); @@ -155,6 +157,7 @@ AsyncChannel::OnDispatchMessage(const Message& msg) void AsyncChannel::OnMessageReceived(const Message& msg) { + AssertIOThread(); NS_ASSERTION(mChannelState != ChannelError, "Shouldn't get here!"); // wake up the worker, there's work to do @@ -167,6 +170,7 @@ AsyncChannel::OnMessageReceived(const Message& msg) void AsyncChannel::OnChannelConnected(int32 peer_pid) { + AssertIOThread(); MutexAutoLock lock(mMutex); mChannelState = ChannelConnected; @@ -177,6 +181,7 @@ AsyncChannel::OnChannelConnected(int32 peer_pid) void AsyncChannel::OnChannelError() { + AssertIOThread(); mChannelState = ChannelError; if (XRE_GetProcessType() == GeckoProcessType_Default) { @@ -200,6 +205,7 @@ AsyncChannel::OnChannelError() void AsyncChannel::OnChannelOpened() { + AssertIOThread(); mChannelState = ChannelOpening; /*assert*/mTransport->Connect(); } @@ -207,6 +213,7 @@ AsyncChannel::OnChannelOpened() void AsyncChannel::OnSend(Message* aMsg) { + AssertIOThread(); mTransport->Send(aMsg); // mTransport deletes aMsg } diff --git a/ipc/glue/AsyncChannel.h b/ipc/glue/AsyncChannel.h index e0757447789..d1c6f33ea85 100644 --- a/ipc/glue/AsyncChannel.h +++ b/ipc/glue/AsyncChannel.h @@ -125,6 +125,21 @@ public: NS_OVERRIDE virtual void OnChannelError(); protected: + // Can be run on either thread + void AssertWorkerThread() + { + if (mWorkerLoop != MessageLoop::current()) { + NS_ERROR("not on worker thread!"); + } + } + + void AssertIOThread() + { + if (mIOLoop != MessageLoop::current()) { + NS_ERROR("not on IO thread!"); + } + } + bool Connected() { return ChannelConnected == mChannelState; } diff --git a/ipc/glue/RPCChannel.cpp b/ipc/glue/RPCChannel.cpp index f40b55cce06..de272fe1579 100644 --- a/ipc/glue/RPCChannel.cpp +++ b/ipc/glue/RPCChannel.cpp @@ -58,6 +58,7 @@ namespace ipc { bool RPCChannel::Call(Message* msg, Message* reply) { + AssertWorkerThread(); NS_ABORT_IF_FALSE(!ProcessingSyncMessage(), "violation of sync handler invariant"); NS_ABORT_IF_FALSE(msg->is_rpc(), @@ -207,6 +208,7 @@ RPCChannel::Call(Message* msg, Message* reply) void RPCChannel::OnDelegate(const Message& msg) { + AssertWorkerThread(); if (msg.is_sync()) return SyncChannel::OnDispatchMessage(msg); else if (!msg.is_rpc()) @@ -217,6 +219,7 @@ RPCChannel::OnDelegate(const Message& msg) void RPCChannel::OnMaybeDequeueOne() { + AssertWorkerThread(); Message recvd; { MutexAutoLock lock(mMutex); @@ -236,6 +239,7 @@ RPCChannel::OnMaybeDequeueOne() void RPCChannel::OnIncall(const Message& call) { + AssertWorkerThread(); // We only reach here from the "regular" event loop, when // StackDepth() == 0. That's the "snapshot" of the state of the // RPCChannel we use when processing this message. @@ -245,6 +249,7 @@ RPCChannel::OnIncall(const Message& call) void RPCChannel::ProcessIncall(const Message& call, size_t stackDepth) { + AssertWorkerThread(); mMutex.AssertNotCurrentThreadOwns(); NS_ABORT_IF_FALSE(call.is_rpc(), "should have been handled by SyncChannel"); @@ -298,6 +303,7 @@ RPCChannel::ProcessIncall(const Message& call, size_t stackDepth) void RPCChannel::OnMessageReceived(const Message& msg) { + AssertIOThread(); MutexAutoLock lock(mMutex); // regardless of the RPC stack, if we're awaiting a sync reply, we @@ -414,6 +420,7 @@ RPCChannel::OnMessageReceived(const Message& msg) void RPCChannel::OnChannelError() { + AssertIOThread(); { MutexAutoLock lock(mMutex); diff --git a/ipc/glue/SyncChannel.cpp b/ipc/glue/SyncChannel.cpp index 61517657672..ee3387c4a9a 100644 --- a/ipc/glue/SyncChannel.cpp +++ b/ipc/glue/SyncChannel.cpp @@ -57,6 +57,7 @@ namespace ipc { bool SyncChannel::Send(Message* msg, Message* reply) { + AssertWorkerThread(); NS_ABORT_IF_FALSE(!ProcessingSyncMessage(), "violation of sync handler invariant"); NS_ABORT_IF_FALSE(msg->is_sync(), "can only Send() sync messages here"); @@ -99,6 +100,7 @@ SyncChannel::Send(Message* msg, Message* reply) void SyncChannel::OnDispatchMessage(const Message& msg) { + AssertWorkerThread(); NS_ABORT_IF_FALSE(msg.is_sync(), "only sync messages here"); NS_ABORT_IF_FALSE(!msg.is_reply(), "wasn't awaiting reply"); @@ -145,6 +147,7 @@ SyncChannel::OnDispatchMessage(const Message& msg) void SyncChannel::OnMessageReceived(const Message& msg) { + AssertIOThread(); if (!msg.is_sync()) { return AsyncChannel::OnMessageReceived(msg); } @@ -167,6 +170,7 @@ SyncChannel::OnMessageReceived(const Message& msg) void SyncChannel::OnChannelError() { + AssertIOThread(); { MutexAutoLock lock(mMutex); @@ -183,6 +187,7 @@ SyncChannel::OnChannelError() void SyncChannel::OnSendReply(Message* aReply) { + AssertIOThread(); mTransport->Send(aReply); }