diff --git a/modules/plugin/test/mochitest/test_GCrace.html b/modules/plugin/test/mochitest/test_GCrace.html new file mode 100644 index 000000000000..40e4f04e14df --- /dev/null +++ b/modules/plugin/test/mochitest/test_GCrace.html @@ -0,0 +1,59 @@ + + GC race with actors on the parent + + + + + +

+ + + + diff --git a/modules/plugin/test/testplugin/nptest.cpp b/modules/plugin/test/testplugin/nptest.cpp index 393eeebe346d..0b203c7dac51 100644 --- a/modules/plugin/test/testplugin/nptest.cpp +++ b/modules/plugin/test/testplugin/nptest.cpp @@ -46,6 +46,7 @@ #ifdef XP_WIN #include #include +#include #define getpid _getpid #else #include @@ -144,6 +145,7 @@ static bool setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, static bool getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); static bool getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); static const NPUTF8* sPluginMethodIdentifierNames[] = { "npnEvaluateTest", @@ -181,6 +183,7 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = { "getCookie", "getAuthInfo", "asyncCallbackTest", + "checkGCRace", }; static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)]; static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMethodIdentifierNames)] = { @@ -219,6 +222,7 @@ static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMetho getCookie, getAuthInfo, asyncCallbackTest, + checkGCRace, }; struct URLNotifyData @@ -2450,3 +2454,101 @@ asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPV return true; } + +static bool +GCRaceInvoke(NPObject*, NPIdentifier, const NPVariant*, uint32_t, NPVariant*) +{ + return false; +} + +static bool +GCRaceInvokeDefault(NPObject* o, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (1 != argCount || !NPVARIANT_IS_INT32(args[0]) || + 35 != NPVARIANT_TO_INT32(args[0])) + return false; + + return true; +} + +static const NPClass kGCRaceClass = { + NP_CLASS_STRUCT_VERSION, + NULL, + NULL, + NULL, + NULL, + GCRaceInvoke, + GCRaceInvokeDefault, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +struct GCRaceData +{ + GCRaceData(NPP npp, NPObject* callback, NPObject* localFunc) + : npp_(npp) + , callback_(callback) + , localFunc_(localFunc) + { + NPN_RetainObject(callback_); + NPN_RetainObject(localFunc_); + } + + ~GCRaceData() + { + NPN_ReleaseObject(callback_); + NPN_ReleaseObject(localFunc_); + } + + NPP npp_; + NPObject* callback_; + NPObject* localFunc_; +}; + +static void +FinishGCRace(void* closure) +{ + GCRaceData* rd = static_cast(closure); + +#ifdef XP_WIN + Sleep(5000); +#else + sleep(5); +#endif + + NPVariant arg; + OBJECT_TO_NPVARIANT(rd->localFunc_, arg); + + NPVariant result; + bool ok = NPN_InvokeDefault(rd->npp_, rd->callback_, &arg, 1, &result); + if (!ok) + return; + + NPN_ReleaseVariantValue(&result); + delete rd; +} + +bool +checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0])) + return false; + + NPP npp = static_cast(npobj)->npp; + + NPObject* localFunc = + NPN_CreateObject(npp, const_cast(&kGCRaceClass)); + + GCRaceData* rd = + new GCRaceData(npp, NPVARIANT_TO_OBJECT(args[0]), localFunc); + NPN_PluginThreadAsyncCall(npp, FinishGCRace, rd); + + OBJECT_TO_NPVARIANT(localFunc, *result); + return true; +}