From 3b04c93333e4907bb95f1c093d9e4b5b02dcd8a8 Mon Sep 17 00:00:00 2001 From: "jst%mozilla.jstenback.com" Date: Fri, 30 Jul 2004 04:00:05 +0000 Subject: [PATCH] Fixing bug 253570. Add NPP arguments to select new NPN_ methods to make implementation easier and safer. r+sr=brendan@mozilla.org git-svn-id: svn://10.0.0.236/trunk@160110 18797224-902f-48f8-a5cc-f745e15eee43 --- .../modules/plugin/base/public/npruntime.h | 19 +- mozilla/modules/plugin/base/public/npupp.h | 143 +++++--- .../modules/plugin/base/src/ns4xPlugin.cpp | 120 +++++-- mozilla/modules/plugin/base/src/ns4xPlugin.h | 64 +++- .../plugin/base/src/ns4xPluginInstance.h | 6 + .../modules/plugin/base/src/nsJSNPRuntime.cpp | 337 +++++++++++------- .../modules/plugin/base/src/nsJSNPRuntime.h | 24 +- 7 files changed, 494 insertions(+), 219 deletions(-) diff --git a/mozilla/modules/plugin/base/public/npruntime.h b/mozilla/modules/plugin/base/public/npruntime.h index f74c7c80e9c..e210b40ff50 100644 --- a/mozilla/modules/plugin/base/public/npruntime.h +++ b/mozilla/modules/plugin/base/public/npruntime.h @@ -274,7 +274,7 @@ int32_t NPN_IntFromIdentifier(NPIdentifier identifier); The NPVariant *result argument of these functions (where applicable) should be released using NPN_ReleaseVariantValue(). */ -typedef NPObject *(*NPAllocateFunctionPtr)(); +typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp); typedef void (*NPDeallocateFunctionPtr)(NPObject *npobj); typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj); typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name); @@ -286,7 +286,8 @@ typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name, NPVariant *result); typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name, const NPVariant *value); -typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, NPIdentifier name); +typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, + NPIdentifier name); /* NPObjects returned by create, retain, invoke, and getProperty pass @@ -336,7 +337,7 @@ struct NPObject { returned. This method will initialize the referenceCount member of the NPObject to 1. */ -NPObject *NPN_CreateObject(NPClass *aClass); +NPObject *NPN_CreateObject(NPP npp, NPClass *aClass); /* Increment the NPObject's reference count. @@ -362,17 +363,17 @@ void NPN_ReleaseObject(NPObject *npobj); on which the plugin was initialized. */ -bool NPN_Call(NPObject *npobj, NPIdentifier methodName, +bool NPN_Call(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result); bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result); -bool NPN_GetProperty(NPObject *npobj, NPIdentifier propertyName, +bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result); -bool NPN_SetProperty(NPObject *npobj, NPIdentifier propertyName, +bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value); -bool NPN_RemoveProperty(NPObject *npobj, NPIdentifier propertyName); -bool NPN_HasProperty(NPObject *npobj, NPIdentifier propertyName); -bool NPN_HasMethod(NPObject *npobj, NPIdentifier methodName); +bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName); +bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName); +bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName); /* NPN_SetException may be called to trigger a script exception upon diff --git a/mozilla/modules/plugin/base/public/npupp.h b/mozilla/modules/plugin/base/public/npupp.h index dc00fc4f1ff..f9c182c5954 100644 --- a/mozilla/modules/plugin/base/public/npupp.h +++ b/mozilla/modules/plugin/base/public/npupp.h @@ -37,7 +37,7 @@ /* - * npupp.h $Revision: 3.17 $ + * npupp.h $Revision: 3.18 $ * function call mecahnics needed by platform specific glue code. */ @@ -1228,22 +1228,23 @@ typedef int32_t (* NP_LOADDS NPN_IntFromIdentifierUPP)(NPIdentifier identifier); typedef UniversalProcPtr NPN_CreateObjectUPP; enum { uppNPN_CreateObjectProcInfo = kThinkCStackBased - | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPClass*))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPClass*))) | RESULT_SIZE(SIZE_CODE(sizeof(NPObject*))) }; #define NewNPN_CreateObjectProc(FUNC) \ (NPN_CreateObjectUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_CreateObjectProcInfo, GetCurrentArchitecture()) -#define CallNPN_CreateObjectProc(FUNC, ARG1) \ - (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_CreateObjectProcInfo, (ARG1)) +#define CallNPN_CreateObjectProc(FUNC, ARG1, ARG2) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_CreateObjectProcInfo, (ARG1), (ARG2)) #else -typedef NPObject* (* NP_LOADDS NPN_CreateObjectUPP)(NPClass *aClass); +typedef NPObject* (* NP_LOADDS NPN_CreateObjectUPP)(NPP npp, NPClass *aClass); #define NewNPN_CreateObjectProc(FUNC) \ ((NPN_CreateObjectUPP) (FUNC)) -#define CallNPN_CreateObjectProc(FUNC, ARG1) \ - (*(FUNC))((ARG1)) +#define CallNPN_CreateObjectProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) #endif @@ -1306,26 +1307,27 @@ typedef void (* NP_LOADDS NPN_ReleaseObjectUPP)(NPObject *obj); typedef UniversalProcPtr NPN_CallUPP; enum { uppNPN_CallProcInfo = kThinkCStackBased - | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPObject*))) - | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPIdentifier))) - | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const NPVariant*))) - | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32_t))) - | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(NPVariant*))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPObject*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPIdentifier))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(const NPVariant*))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(uint32_t))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPVariant*))) | RESULT_SIZE(SIZE_CODE(sizeof(bool))) }; #define NewNPN_CallProc(FUNC) \ (NPN_CallUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_CallProcInfo, GetCurrentArchitecture()) -#define CallNPN_CallProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ - (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_CallProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#define CallNPN_CallProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_CallProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) #else -typedef bool (* NP_LOADDS NPN_CallUPP)(NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result); +typedef bool (* NP_LOADDS NPN_CallUPP)(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result); #define NewNPN_CallProc(FUNC) \ ((NPN_CallUPP) (FUNC)) -#define CallNPN_CallProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ - (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#define CallNPN_CallProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) #endif @@ -1365,24 +1367,25 @@ typedef bool (* NP_LOADDS NPN_EvaluateUPP)(NPP npp, NPObject *obj, NPString *scr typedef UniversalProcPtr NPN_GetPropertyUPP; enum { uppNPN_GetPropertyProcInfo = kThinkCStackBased - | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPObject*))) - | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPIdentifier))) - | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPVariant*))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPObject*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPIdentifier))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPVariant*))) | RESULT_SIZE(SIZE_CODE(sizeof(bool))) }; #define NewNPN_GetPropertyProc(FUNC) \ (NPN_GetPropertyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetPropertyProcInfo, GetCurrentArchitecture()) -#define CallNPN_GetPropertyProc(FUNC, ARG1, ARG2, ARG3) \ - (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetPropertyProcInfo, (ARG1), (ARG2), (ARG3)) +#define CallNPN_GetPropertyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetPropertyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) #else -typedef bool (* NP_LOADDS NPN_GetPropertyUPP)(NPObject *obj, NPIdentifier propertyName, NPVariant *result); +typedef bool (* NP_LOADDS NPN_GetPropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result); #define NewNPN_GetPropertyProc(FUNC) \ ((NPN_GetPropertyUPP) (FUNC)) -#define CallNPN_GetPropertyProc(FUNC, ARG1, ARG2, ARG3) \ - (*(FUNC))((ARG1), (ARG2), (ARG3)) +#define CallNPN_GetPropertyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) #endif @@ -1393,24 +1396,25 @@ typedef bool (* NP_LOADDS NPN_GetPropertyUPP)(NPObject *obj, NPIdentifier proper typedef UniversalProcPtr NPN_SetPropertyUPP; enum { uppNPN_SetPropertyProcInfo = kThinkCStackBased - | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPObject*))) - | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPIdentifier))) - | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const NPVariant*))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPObject*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPIdentifier))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(const NPVariant*))) | RESULT_SIZE(SIZE_CODE(sizeof(bool))) }; #define NewNPN_SetPropertyProc(FUNC) \ (NPN_SetPropertyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_SetPropertyProcInfo, GetCurrentArchitecture()) -#define CallNPN_SetPropertyProc(FUNC, ARG1, ARG2, ARG3) \ - (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_SetPropertyProcInfo, (ARG1), (ARG2), (ARG3)) +#define CallNPN_SetPropertyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_SetPropertyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) #else -typedef bool (* NP_LOADDS NPN_SetPropertyUPP)(NPObject *obj, NPIdentifier propertyName, const NPVariant *value); +typedef bool (* NP_LOADDS NPN_SetPropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value); #define NewNPN_SetPropertyProc(FUNC) \ ((NPN_SetPropertyUPP) (FUNC)) -#define CallNPN_SetPropertyProc(FUNC, ARG1, ARG2, ARG3) \ - (*(FUNC))((ARG1), (ARG2), (ARG3)) +#define CallNPN_SetPropertyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) #endif @@ -1421,23 +1425,80 @@ typedef bool (* NP_LOADDS NPN_SetPropertyUPP)(NPObject *obj, NPIdentifier proper typedef UniversalProcPtr NPN_RemovePropertyUPP; enum { uppNPN_RemovePropertyProcInfo = kThinkCStackBased - | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPObject*))) - | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPIdentifier))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPObject*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPIdentifier))) | RESULT_SIZE(SIZE_CODE(sizeof(bool))) }; #define NewNPN_RemovePropertyProc(FUNC) \ (NPN_RemovePropertyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_RemovePropertyProcInfo, GetCurrentArchitecture()) -#define CallNPN_RemovePropertyProc(FUNC, ARG1, ARG2) \ - (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_RemovePropertyProcInfo, (ARG1), (ARG2)) +#define CallNPN_RemovePropertyProc(FUNC, ARG1, ARG2, ARG3) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_RemovePropertyProcInfo, (ARG1), (ARG2), (ARG3)) #else -typedef bool (* NP_LOADDS NPN_RemovePropertyUPP)(NPObject *obj, NPIdentifier propertyName); +typedef bool (* NP_LOADDS NPN_RemovePropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName); #define NewNPN_RemovePropertyProc(FUNC) \ ((NPN_RemovePropertyUPP) (FUNC)) -#define CallNPN_RemovePropertyProc(FUNC, ARG1, ARG2) \ - (*(FUNC))((ARG1), (ARG2)) +#define CallNPN_RemovePropertyProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +#endif + +/* NPN_HasProperty */ + +#if _NPUPP_USE_UPP_ + +typedef UniversalProcPtr NPN_HasPropertyUPP; +enum { + uppNPN_HasPropertyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPObject*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPIdentifier))) + | RESULT_SIZE(SIZE_CODE(sizeof(bool))) +}; + +#define NewNPN_HasPropertyProc(FUNC) \ + (NPN_HasPropertyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_HasPropertyProcInfo, GetCurrentArchitecture()) +#define CallNPN_HasPropertyProc(FUNC, ARG1, ARG2, ARG3) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_HasPropertyProcInfo, (ARG1), (ARG2), (ARG3)) + +#else + +typedef bool (* NP_LOADDS NPN_HasPropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName); +#define NewNPN_HasPropertyProc(FUNC) \ + ((NPN_HasPropertyUPP) (FUNC)) +#define CallNPN_HasPropertyProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +#endif + +/* NPN_HasMethod */ + +#if _NPUPP_USE_UPP_ + +typedef UniversalProcPtr NPN_HasMethodUPP; +enum { + uppNPN_HasMethodProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPObject*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPIdentifier))) + | RESULT_SIZE(SIZE_CODE(sizeof(bool))) +}; + +#define NewNPN_HasMethodProc(FUNC) \ + (NPN_HasMethodUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_HasMethodProcInfo, GetCurrentArchitecture()) +#define CallNPN_HasMethodProc(FUNC, ARG1, ARG2, ARG3) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_HasMethodProcInfo, (ARG1), (ARG2), (ARG3)) + +#else + +typedef bool (* NP_LOADDS NPN_HasMethodUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName); +#define NewNPN_HasMethodProc(FUNC) \ + ((NPN_HasMethodUPP) (FUNC)) +#define CallNPN_HasMethodProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) #endif @@ -1564,6 +1625,8 @@ typedef struct _NPNetscapeFuncs { NPN_GetPropertyUPP getproperty; NPN_SetPropertyUPP setproperty; NPN_RemovePropertyUPP removeproperty; + NPN_HasPropertyUPP hasproperty; + NPN_HasMethodUPP hasmethod; NPN_ReleaseVariantValueUPP releasevariantvalue; NPN_SetExceptionUPP setexception; } NPNetscapeFuncs; diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp index be7c56f4a95..5820d83b8ae 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp @@ -1438,18 +1438,26 @@ _identifierisstring(NPIdentifier identifier) } NPObject* NP_EXPORT -_createobject(NPClass* aClass) +_createobject(NPP npp, NPClass* aClass) { + if (!npp) { + NS_ERROR("Null npp passed to _createobject()!"); + + return nsnull; + } + if (!aClass) { NS_ERROR("Null class passed to _createobject()!"); - return 0; + return nsnull; } + NPPAutoPusher nppPusher(npp); + NPObject *npobj; if (aClass->allocate) { - npobj = aClass->allocate(); + npobj = aClass->allocate(npp); } else { npobj = (NPObject *)PR_Malloc(sizeof(NPObject)); } @@ -1490,11 +1498,14 @@ _releaseobject(NPObject* npobj) } bool NP_EXPORT -_call(NPObject* npobj, NPIdentifier method, const NPVariant *args, +_call(NPP npp, NPObject* npobj, NPIdentifier method, const NPVariant *args, uint32_t argCount, NPVariant *result) { - if (!npobj || !npobj->_class || !npobj->_class->invoke) - return PR_FALSE; + if (!npp || !npobj || !npobj->_class || !npobj->_class->invoke) + return false; + + NPPExceptionAutoHolder nppExceptionHolder; + NPPAutoPusher nppPusher(npp); return npobj->_class->invoke(npobj, method, args, argCount, result); } @@ -1502,6 +1513,11 @@ _call(NPObject* npobj, NPIdentifier method, const NPVariant *args, bool NP_EXPORT _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result) { + if (!npp) + return false; + + NPPAutoPusher nppPusher(npp); + JSContext *cx = GetJSContextFromNPP(npp); NS_ENSURE_TRUE(cx, false); @@ -1534,8 +1550,7 @@ _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result) jsval rval; nsresult rv = scx->EvaluateStringWithValue(utf16script, obj, principal, - nsnull, 0, nsnull, &rval, - nsnull); + nsnull, 0, nsnull, &rval, nsnull); NS_ENSURE_SUCCESS(rv, false); if (result) { @@ -1546,47 +1561,63 @@ _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result) } bool NP_EXPORT -_getproperty(NPObject* npobj, NPIdentifier property, NPVariant *result) +_getproperty(NPP npp, NPObject* npobj, NPIdentifier property, + NPVariant *result) { - if (!npobj || !npobj->_class || !npobj->_class->getProperty) - return PR_FALSE; + if (!npp || !npobj || !npobj->_class || !npobj->_class->getProperty) + return false; + + NPPExceptionAutoHolder nppExceptionHolder; + NPPAutoPusher nppPusher(npp); return npobj->_class->getProperty(npobj, property, result); } bool NP_EXPORT -_setproperty(NPObject* npobj, NPIdentifier property, +_setproperty(NPP npp, NPObject* npobj, NPIdentifier property, const NPVariant *value) { - if (!npobj || !npobj->_class || !npobj->_class->setProperty) - return PR_FALSE; + if (!npp || !npobj || !npobj->_class || !npobj->_class->setProperty) + return false; + + NPPExceptionAutoHolder nppExceptionHolder; + NPPAutoPusher nppPusher(npp); return npobj->_class->setProperty(npobj, property, value); } bool NP_EXPORT -_removeproperty(NPObject* npobj, NPIdentifier property) +_removeproperty(NPP npp, NPObject* npobj, NPIdentifier property) { - if (!npobj || !npobj->_class || !npobj->_class->removeProperty) - return PR_FALSE; + if (!npp || !npobj || !npobj->_class || !npobj->_class->removeProperty) + return false; + + NPPExceptionAutoHolder nppExceptionHolder; + NPPAutoPusher nppPusher(npp); return npobj->_class->removeProperty(npobj, property); } bool NP_EXPORT -_hasproperty(NPObject* npobj, NPIdentifier propertyName) +_hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName) { - if (!npobj || !npobj->_class || !npobj->_class->hasProperty) - return PR_FALSE; + if (!npp || !npobj || !npobj->_class || !npobj->_class->hasProperty) + return false; + + NPPExceptionAutoHolder nppExceptionHolder; + NPPAutoPusher nppPusher(npp); return npobj->_class->hasProperty(npobj, propertyName); } bool NP_EXPORT -_hasmethod(NPObject* npobj, NPIdentifier methodName) +_hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName) { - if (!npobj || !npobj->_class || !npobj->_class->hasMethod) - return PR_FALSE; + if (!npp || !npobj || !npobj->_class || !npobj->_class->hasMethod) + return false; + + NPPExceptionAutoHolder nppExceptionHolder; + NPPAutoPusher nppPusher(npp); return npobj->_class->hasProperty(npobj, methodName); } @@ -1634,12 +1665,50 @@ _tostring(NPObject* npobj, NPVariant *result) return PR_FALSE; } +static char *gNPPException; + void NP_EXPORT _setexception(NPObject* npobj, const NPUTF8 *message) { - // XXX: Write me! + if (gNPPException) { + // If a plugin throws multiple exceptions, we'll only report the + // last one for now. + free(gNPPException); + } + + gNPPException = strdup(message); } +const char * +PeekException() +{ + return gNPPException; +} + +void +PopException() +{ + NS_ASSERTION(!gNPPException, "Uh, no NPP exception to pop!"); + + if (gNPPException) { + free(gNPPException); + + gNPPException = nsnull; + } +} + +NPPExceptionAutoHolder::NPPExceptionAutoHolder() + : mOldException(gNPPException) +{ + gNPPException = nsnull; +} + +NPPExceptionAutoHolder::~NPPExceptionAutoHolder() +{ + NS_ASSERTION(!gNPPException, "NPP exception not properly cleared!"); + + gNPPException = mOldException; +} //////////////////////////////////////////////////////////////////////// NPError NP_EXPORT @@ -1973,3 +2042,6 @@ _getJavaPeer(NPP npp) } #endif /* OJI */ + + +NPP NPPStack::sCurrentNPP = nsnull; diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.h b/mozilla/modules/plugin/base/src/ns4xPlugin.h index c2eafd23d12..459529398a5 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.h +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.h @@ -207,7 +207,7 @@ int32_t NP_EXPORT _intfromidentifier(NPIdentifier identifier); NPObject* NP_EXPORT -_createobject(NPClass* aClass); +_createobject(NPP npp, NPClass* aClass); NPObject* NP_EXPORT _retainobject(NPObject* npobj); @@ -216,26 +216,28 @@ void NP_EXPORT _releaseobject(NPObject* npobj); bool NP_EXPORT -_call(NPObject* npobj, NPIdentifier method, const NPVariant *args, +_call(NPP npp, NPObject* npobj, NPIdentifier method, const NPVariant *args, uint32_t argCount, NPVariant *result); bool NP_EXPORT _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result); bool NP_EXPORT -_getproperty(NPObject* npobj, NPIdentifier property, NPVariant *result); +_getproperty(NPP npp, NPObject* npobj, NPIdentifier property, + NPVariant *result); bool NP_EXPORT -_setproperty(NPObject* npobj, NPIdentifier property, const NPVariant *value); +_setproperty(NPP npp, NPObject* npobj, NPIdentifier property, + const NPVariant *value); bool NP_EXPORT -_removeproperty(NPObject* npobj, NPIdentifier property); +_removeproperty(NPP npp, NPObject* npobj, NPIdentifier property); bool NP_EXPORT -_hasproperty(NPObject* npobj, NPIdentifier propertyName); +_hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName); bool NP_EXPORT -_hasmethod(NPObject* npobj, NPIdentifier methodName); +_hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName); void NP_EXPORT _releasevariantvalue(NPVariant *variant); @@ -245,4 +247,52 @@ _setexception(NPObject* npobj, const NPUTF8 *message); PR_END_EXTERN_C +const char * +PeekException(); + +void +PopException(); + +class NPPStack +{ +public: + static NPP Peek() + { + return sCurrentNPP; + } + +protected: + static NPP sCurrentNPP; +}; + +class NPPAutoPusher : public NPPStack +{ +public: + NPPAutoPusher(NPP npp) + : mOldNPP(sCurrentNPP) + { + NS_ASSERTION(npp, "Uh, null npp passed to NPPAutoPusher!"); + + sCurrentNPP = npp; + } + + ~NPPAutoPusher() + { + sCurrentNPP = mOldNPP; + } + +private: + NPP mOldNPP; +}; + +class NPPExceptionAutoHolder +{ +public: + NPPExceptionAutoHolder(); + ~NPPExceptionAutoHolder(); + +protected: + char *mOldException; +}; + #endif // ns4xPlugin_h__ diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.h b/mozilla/modules/plugin/base/src/ns4xPluginInstance.h index 40c4db0e35d..96ee7f0b6ef 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.h +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.h @@ -163,6 +163,12 @@ public: nsresult SetCached(PRBool aCache) { mCached = aCache; return NS_OK; }; virtual JSObject *GetJSObject(JSContext *cx); + + // Non-refcounting accessor for faster access to the peer. + nsIPluginInstancePeer *Peer() + { + return mPeer; + } protected: diff --git a/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp b/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp index fb67a4c7734..e640a8040f1 100644 --- a/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp +++ b/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp @@ -47,10 +47,16 @@ #include "nsIJSContextStack.h" #include "prmem.h" -// Hash of NPObject wrappers that wrap JSObjects. +// Hash of JSObject wrappers that wraps JSObjects as NPObjects. There +// will be one wrapper per JSObject per plugin instance, i.e. if two +// plugins access the JSObject x, two wrappers for x will be +// created. This is needed to be able to properly drop the wrappers +// when a plugin is torn down in case there's a leak in the plugin (we +// don't want to leak the world just because a plugin leaks an +// NPObject). static PLDHashTable sJSObjWrappers; -// Hash of JSObject wrappers that wrap NPObjects. +// Hash of NPObject wrappers that wrap NPObjects as JSObjects. static PLDHashTable sNPObjWrappers; // Global wrapper count. This includes JSObject wrappers *and* @@ -177,12 +183,12 @@ OnWrapperDestroyed() static JSContext * GetJSContext(NPP npp) { + NS_ENSURE_TRUE(npp, nsnull); + ns4xPluginInstance *inst = (ns4xPluginInstance *)npp->ndata; NS_ENSURE_TRUE(inst, nsnull); - nsCOMPtr pip; - inst->GetPeer(getter_AddRefs(pip)); - nsCOMPtr pp (do_QueryInterface(pip)); + nsCOMPtr pp(do_QueryInterface(inst->Peer())); NS_ENSURE_TRUE(pp, nsnull); nsCOMPtr owner; @@ -204,7 +210,7 @@ GetJSContext(NPP npp) static NPP -FindNPPForJSObject(JSObject *obj, NPObject *npobj); +LookupNPP(NPObject *npobj); static jsval @@ -271,6 +277,8 @@ NPVariantToJSVal(NPP npp, JSContext *cx, const NPVariant *variant) bool JSValToNPVariant(NPP npp, JSContext *cx, jsval val, NPVariant *variant) { + NS_ASSERTION(npp, "Must have an NPP to wrap a jsval!"); + if (JSVAL_IS_PRIMITIVE(val)) { if (val == JSVAL_VOID) { VOID_TO_NPVARIANT(*variant); @@ -304,18 +312,8 @@ JSValToNPVariant(NPP npp, JSContext *cx, jsval val, NPVariant *variant) return true; } - if (!npp) { - npp = FindNPPForJSObject(JSVAL_TO_OBJECT(val), nsnull); - - if (!npp) { - NS_ERROR("Must have an NPP to wrap a JSObject!"); - - return false; - } - } - - NPObject *npobj = nsJSObjWrapper::GetNewOrUsed(npp, cx, - JSVAL_TO_OBJECT(val)); + NPObject *npobj = + nsJSObjWrapper::GetNewOrUsed(npp, cx, JSVAL_TO_OBJECT(val)); if (!npobj) { return false; } @@ -329,14 +327,53 @@ JSValToNPVariant(NPP npp, JSContext *cx, jsval val, NPVariant *variant) static void ThrowJSException(JSContext *cx, const char *message) { - // Add exception throwing code here. + const char *ex = PeekException(); - printf ("JS Error: %s\n", message); + if (ex) { + nsAutoString ucex; + + if (message) { + AppendASCIItoUTF16(message, ucex); + + AppendASCIItoUTF16(" [plugin exception: ", ucex); + } + + AppendUTF8toUTF16(ex, ucex); + + if (message) { + AppendASCIItoUTF16("].", ucex); + } + + JSString *str = ::JS_NewUCStringCopyN(cx, (jschar *)ucex.get(), + ucex.Length()); + + if (str) { + ::JS_SetPendingException(cx, STRING_TO_JSVAL(str)); + } + + PopException(); + } else { + ::JS_ReportError(cx, message); + } +} + +static JSBool +ReportExceptionIfPending(JSContext *cx) +{ + const char *ex = PeekException(); + + if (!ex) { + return JS_TRUE; + } + + ThrowJSException(cx, nsnull); + + return JS_FALSE; } -nsJSObjWrapper::nsJSObjWrapper() - : mJSObj(nsnull), mCx(nsnull), mNpp(nsnull) +nsJSObjWrapper::nsJSObjWrapper(NPP npp) + : nsJSObjWrapperKey(nsnull, npp) { OnWrapperCreated(); } @@ -351,9 +388,9 @@ nsJSObjWrapper::~nsJSObjWrapper() // static NPObject * -nsJSObjWrapper::NP_Allocate() +nsJSObjWrapper::NP_Allocate(NPP npp) { - return new nsJSObjWrapper; + return new nsJSObjWrapper(npp); } // static @@ -376,13 +413,13 @@ nsJSObjWrapper::NP_Invalidate(NPObject *npobj) if (sJSObjWrappers.ops) { // Remove the wrapper from the hash - PL_DHashTableOperate(&sJSObjWrappers, jsnpobj->mJSObj, PL_DHASH_REMOVE); + + nsJSObjWrapperKey key(jsnpobj->mJSObj, jsnpobj->mNpp); + PL_DHashTableOperate(&sJSObjWrappers, &key, PL_DHASH_REMOVE); } - // Forget our reference to the JSObject etc. + // Forget our reference to the JSObject. jsnpobj->mJSObj = nsnull; - jsnpobj->mCx = nsnull; - jsnpobj->mNpp = nsnull; } } @@ -409,16 +446,19 @@ GetProperty(JSContext *cx, JSObject *obj, NPIdentifier identifier, jsval *rval) bool nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier identifier) { - if (!npobj) { + NPP npp = NPPStack::Peek(); + JSContext *cx = GetJSContext(npp); + + if (!cx || !npobj) { return PR_FALSE; } nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; jsval v; - JSBool ok = GetProperty(npjsobj->mCx, npjsobj->mJSObj, identifier, &v); + JSBool ok = GetProperty(cx, npjsobj->mJSObj, identifier, &v); return ok && !JSVAL_IS_PRIMITIVE(v) && - ::JS_ObjectIsFunction(npjsobj->mCx, JSVAL_TO_OBJECT(v)); + ::JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(v)); } // static @@ -427,7 +467,10 @@ nsJSObjWrapper::NP_Invoke(NPObject *npobj, NPIdentifier identifier, const NPVariant *args, uint32_t argCount, NPVariant *result) { - if (!npobj || !result) { + NPP npp = NPPStack::Peek(); + JSContext *cx = GetJSContext(npp); + + if (!cx || !npobj || !result) { // XXX: Throw null-ptr exception return PR_FALSE; @@ -439,10 +482,10 @@ nsJSObjWrapper::NP_Invoke(NPObject *npobj, NPIdentifier identifier, nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; jsval fv; - AutoCXPusher pusher(npjsobj->mCx); + AutoCXPusher pusher(cx); - if (!GetProperty(npjsobj->mCx, npjsobj->mJSObj, identifier, &fv) || - ::JS_TypeOfValue(npjsobj->mCx, fv) != JSTYPE_FUNCTION) { + if (!GetProperty(cx, npjsobj->mJSObj, identifier, &fv) || + ::JS_TypeOfValue(cx, fv) != JSTYPE_FUNCTION) { return PR_FALSE; } @@ -463,18 +506,18 @@ nsJSObjWrapper::NP_Invoke(NPObject *npobj, NPIdentifier identifier, // Convert args for (PRUint32 i = 0; i < argCount; ++i) { - jsargs[i] = NPVariantToJSVal(npjsobj->mNpp, npjsobj->mCx, args + i); + jsargs[i] = NPVariantToJSVal(npp, cx, args + i); } jsval v; - JSBool ok = ::JS_CallFunctionValue(npjsobj->mCx, npjsobj->mJSObj, fv, - argCount, jsargs, &v); + JSBool ok = ::JS_CallFunctionValue(cx, npjsobj->mJSObj, fv, argCount, jsargs, + &v); if (jsargs != jsargs_buf) PR_Free(jsargs); if (ok) - ok = JSValToNPVariant(npjsobj->mNpp, npjsobj->mCx, v, result); + ok = JSValToNPVariant(npp, cx, v, result); // return ok == JS_TRUE to quiet down compiler warning, even if // return ok is what we really want. @@ -485,29 +528,31 @@ nsJSObjWrapper::NP_Invoke(NPObject *npobj, NPIdentifier identifier, bool nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier identifier) { - if (!npobj) { + NPP npp = NPPStack::Peek(); + JSContext *cx = GetJSContext(npp); + + if (!cx || !npobj) { + // XXX: Throw null ptr exception + return PR_FALSE; } nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; jsval id = (jsval)identifier; - jsval found; - JSBool ok = JS_FALSE; + JSBool found, ok = JS_FALSE; if (JSVAL_IS_STRING(id)) { JSString *str = JSVAL_TO_STRING(id); - ok = ::JS_LookupUCProperty(npjsobj->mCx, npjsobj->mJSObj, - ::JS_GetStringChars(str), - ::JS_GetStringLength(str), &found); + ok = ::JS_HasUCProperty(cx, npjsobj->mJSObj, ::JS_GetStringChars(str), + ::JS_GetStringLength(str), &found); } else { NS_ASSERTION(JSVAL_IS_INT(id), "id must be either string or int!\n"); - ok = ::JS_LookupElement(npjsobj->mCx, npjsobj->mJSObj, JSVAL_TO_INT(id), - &found); + ok = ::JS_HasElement(cx, npjsobj->mJSObj, JSVAL_TO_INT(id), &found); } - return ok && !JSVAL_IS_VOID(found); + return ok && found; } // static @@ -515,16 +560,19 @@ bool nsJSObjWrapper::NP_GetProperty(NPObject *npobj, NPIdentifier identifier, NPVariant *result) { - if (!npobj) + NPP npp = NPPStack::Peek(); + JSContext *cx = GetJSContext(npp); + + if (!cx || !npobj) return PR_FALSE; nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; - AutoCXPusher pusher(npjsobj->mCx); + AutoCXPusher pusher(cx); jsval v; - return GetProperty(npjsobj->mCx, npjsobj->mJSObj, identifier, &v) && - JSValToNPVariant(npjsobj->mNpp, npjsobj->mCx, v, result); + return (GetProperty(cx, npjsobj->mJSObj, identifier, &v) && + JSValToNPVariant(npp, cx, v, result)); } // static @@ -532,27 +580,29 @@ bool nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier identifier, const NPVariant *value) { - if (!npobj) + NPP npp = NPPStack::Peek(); + JSContext *cx = GetJSContext(npp); + + if (!cx || !npobj) return PR_FALSE; nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; jsval id = (jsval)identifier; JSBool ok = JS_FALSE; - AutoCXPusher pusher(npjsobj->mCx); + AutoCXPusher pusher(cx); - jsval v = NPVariantToJSVal(npjsobj->mNpp, npjsobj->mCx, value); + jsval v = NPVariantToJSVal(npp, cx, value); if (JSVAL_IS_STRING(id)) { JSString *str = JSVAL_TO_STRING(id); - ok = ::JS_SetUCProperty(npjsobj->mCx, npjsobj->mJSObj, - ::JS_GetStringChars(str), + ok = ::JS_SetUCProperty(cx, npjsobj->mJSObj, ::JS_GetStringChars(str), ::JS_GetStringLength(str), &v); } else { NS_ASSERTION(JSVAL_IS_INT(id), "id must be either string or int!\n"); - ok = ::JS_SetElement(npjsobj->mCx, npjsobj->mJSObj, JSVAL_TO_INT(id), &v); + ok = ::JS_SetElement(cx, npjsobj->mJSObj, JSVAL_TO_INT(id), &v); } // return ok == JS_TRUE to quiet down compiler warning, even if @@ -564,26 +614,28 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier identifier, bool nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier) { - if (!npobj) + NPP npp = NPPStack::Peek(); + JSContext *cx = GetJSContext(npp); + + if (!cx || !npobj) return PR_FALSE; nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj; jsval id = (jsval)identifier; JSBool ok = JS_FALSE; - AutoCXPusher pusher(npjsobj->mCx); + AutoCXPusher pusher(cx); if (JSVAL_IS_STRING(id)) { JSString *str = JSVAL_TO_STRING(id); jsval unused; - ok = ::JS_DeleteUCProperty2(npjsobj->mCx, npjsobj->mJSObj, - ::JS_GetStringChars(str), + ok = ::JS_DeleteUCProperty2(cx, npjsobj->mJSObj, ::JS_GetStringChars(str), ::JS_GetStringLength(str), &unused); } else { NS_ASSERTION(JSVAL_IS_INT(id), "id must be either string or int!\n"); - ok = ::JS_DeleteElement(npjsobj->mCx, npjsobj->mJSObj, JSVAL_TO_INT(id)); + ok = ::JS_DeleteElement(cx, npjsobj->mJSObj, JSVAL_TO_INT(id)); } // return ok == JS_TRUE to quiet down compiler warning, even if @@ -594,27 +646,38 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier) class JSObjWrapperHashEntry : public PLDHashEntryHdr { public: - nsJSObjWrapper *mNPObj; + nsJSObjWrapper *mJSObjWrapper; }; +PR_STATIC_CALLBACK(PLDHashNumber) +JSObjWrapperHash(PLDHashTable *table, const void *key) +{ + const nsJSObjWrapperKey *e = NS_STATIC_CAST(const nsJSObjWrapperKey *, key); + + return (PLDHashNumber)((PRWord)e->mJSObj ^ (PRWord)e->mNpp) >> 2; +} + PR_STATIC_CALLBACK(const void *) -NPObjWrapperHashGetKey(PLDHashTable *table, PLDHashEntryHdr *entry) +JSObjWrapperHashGetKey(PLDHashTable *table, PLDHashEntryHdr *entry) { JSObjWrapperHashEntry *e = NS_STATIC_CAST(JSObjWrapperHashEntry *, entry); - return e->mNPObj->mJSObj; + return NS_STATIC_CAST(nsJSObjWrapperKey *, e->mJSObjWrapper); } PR_STATIC_CALLBACK(PRBool) -NPObjWrapperHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry, +JSObjWrapperHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry, const void *key) { + const nsJSObjWrapperKey *objWrapperKey = + NS_STATIC_CAST(const nsJSObjWrapperKey *, key); const JSObjWrapperHashEntry *e = NS_STATIC_CAST(const JSObjWrapperHashEntry *, entry); - return e->mNPObj->mJSObj == key; + return (e->mJSObjWrapper->mJSObj == objWrapperKey->mJSObj && + e->mJSObjWrapper->mNpp == objWrapperKey->mNpp); } @@ -659,9 +722,9 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JSObject *obj) { PL_DHashAllocTable, PL_DHashFreeTable, - NPObjWrapperHashGetKey, - PL_DHashVoidPtrKeyStub, - NPObjWrapperHashMatchEntry, + JSObjWrapperHashGetKey, + JSObjWrapperHash, + JSObjWrapperHashMatchEntry, PL_DHashMoveEntryStub, PL_DHashClearEntryStub, PL_DHashFinalizeStub @@ -675,22 +738,24 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JSObject *obj) } } + nsJSObjWrapperKey key(obj, npp); + JSObjWrapperHashEntry *entry = NS_STATIC_CAST(JSObjWrapperHashEntry *, - PL_DHashTableOperate(&sJSObjWrappers, obj, PL_DHASH_ADD)); + PL_DHashTableOperate(&sJSObjWrappers, &key, PL_DHASH_ADD)); - if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->mNPObj) { + if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->mJSObjWrapper) { // Found a live nsJSObjWrapper, return it. - return _retainobject(entry->mNPObj); + return _retainobject(entry->mJSObjWrapper); } // No existing nsJSObjWrapper, create one. - nsJSObjWrapper *npobj = - (nsJSObjWrapper *)_createobject(&sJSObjWrapperNPClass); + nsJSObjWrapper *wrapper = + (nsJSObjWrapper *)_createobject(npp, &sJSObjWrapperNPClass); - if (!npobj) { + if (!wrapper) { // OOM? Remove the stale entry from the hash. PL_DHashTableRawRemove(&sJSObjWrappers, entry); @@ -698,25 +763,25 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JSObject *obj) return nsnull; } - entry->mNPObj = npobj; + wrapper->mJSObj = obj; - npobj->mJSObj = obj; - npobj->mCx = cx; - npobj->mNpp = npp; + entry->mJSObjWrapper = wrapper; + + NS_ASSERTION(wrapper->mNpp == npp, "nsJSObjWrapper::mNpp not initialized!"); // Root the JSObject, its lifetime is now tied to that of the // NPObject. - if (!::JS_AddNamedRoot(cx, &npobj->mJSObj, "nsJSObjWrapper::mJSObject")) { + if (!::JS_AddNamedRoot(cx, &wrapper->mJSObj, "nsJSObjWrapper::mJSObject")) { NS_ERROR("Failed to root JSObject!"); - _releaseobject(npobj); + _releaseobject(wrapper); PL_DHashTableRawRemove(&sJSObjWrappers, entry); return nsnull; } - return npobj; + return wrapper; } static NPObject * @@ -755,7 +820,7 @@ NPObjWrapper_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_FALSE; } - return JS_TRUE; + return ReportExceptionIfPending(cx); } JS_STATIC_DLL_CALLBACK(JSBool) @@ -776,7 +841,7 @@ NPObjWrapper_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_FALSE; } - return JS_TRUE; + return ReportExceptionIfPending(cx); } JS_STATIC_DLL_CALLBACK(JSBool) @@ -798,8 +863,18 @@ NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_FALSE; } + // Find out what plugin (NPP) is the owner of the object we're + // manipulating, and make it own any JSObject wrappers created here. + NPP npp = LookupNPP(npobj); + + if (!npp) { + ThrowJSException(cx, "No NPP found for NPObject!"); + + return JS_FALSE; + } + NPVariant npv; - if (!JSValToNPVariant(nsnull, cx, *vp, &npv)) { + if (!JSValToNPVariant(npp, cx, *vp, &npv)) { ThrowJSException(cx, "Error converting jsval to NPVariant!"); return JS_FALSE; @@ -813,9 +888,11 @@ NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) if (!ok) { ThrowJSException(cx, "Error setting property on scriptable plugin " "object!"); + + return JS_FALSE; } - return ok; + return ReportExceptionIfPending(cx); } JS_STATIC_DLL_CALLBACK(JSBool) @@ -841,13 +918,15 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_FALSE; } - NPP npp = nsnull; + // Find out what plugin (NPP) is the owner of the object we're + // manipulating, and make it own any JSObject wrappers created + // here. + NPP npp = LookupNPP(npobj); - if (NPVARIANT_IS_OBJECT(npv)) { - // We'll only need an npp if npv is an object, so don't waste time - // looking it up in other cases. + if (!npp) { + ThrowJSException(cx, "No NPP found for NPObject!"); - npp = FindNPPForJSObject(obj, npobj); + return JS_FALSE; } *vp = NPVariantToJSVal(npp, cx, &npv); @@ -858,14 +937,14 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_TRUE; } - if (npobj->_class->hasMethod(npobj, (NPIdentifier)id)) { - return PR_TRUE; + if (!npobj->_class->hasMethod(npobj, (NPIdentifier)id)) { + ThrowJSException(cx, "Trying to get unsupported property on scriptable " + "plugin object!"); + + return JS_FALSE; } - ThrowJSException(cx, "Trying to get unsupported property on scriptable " - "plugin object!"); - - return JS_FALSE; + return ReportExceptionIfPending(cx); } JS_STATIC_DLL_CALLBACK(JSBool) @@ -890,10 +969,12 @@ CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, return JS_FALSE; } - NPP npp = FindNPPForJSObject(obj, npobj); + // Find out what plugin (NPP) is the owner of the object we're + // manipulating, and make it own any JSObject wrappers created here. + NPP npp = LookupNPP(npobj); if (!npp) { - ThrowJSException(cx, "Error finding NPP for JSObject!"); + ThrowJSException(cx, "Error finding NPP for NPObject!"); return JS_FALSE; } @@ -939,8 +1020,9 @@ CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, _releasevariantvalue(npargs + i); } - if (npargs != npargs_buf) + if (npargs != npargs_buf) { PR_Free(npargs); + } if (!ok) { ThrowJSException(cx, "Error calling method on NPObject!"); @@ -953,7 +1035,7 @@ CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, // *rval now owns the value, release our reference. _releasevariantvalue(&v); - return JS_TRUE; + return ReportExceptionIfPending(cx); } @@ -999,7 +1081,7 @@ NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, return fnc != nsnull; } - return JS_TRUE; + return ReportExceptionIfPending(cx); } JS_STATIC_DLL_CALLBACK(void) @@ -1115,7 +1197,7 @@ JSObjWrapperPluginDestroyedCallback(PLDHashTable *table, PLDHashEntryHdr *hdr, { JSObjWrapperHashEntry *entry = (JSObjWrapperHashEntry *)hdr; - nsJSObjWrapper *npobj = entry->mNPObj; + nsJSObjWrapper *npobj = entry->mJSObjWrapper; if (npobj->mNpp == arg) { // Prevent invalidate() and _releaseobject() from touching the hash @@ -1183,39 +1265,30 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp) } } -// Find the NPP for a JSObject or from its NPObject counter-part, if any. + +// Find the NPP for a NPObject. static NPP -FindNPPForJSObject(JSObject *obj, NPObject *npobj) +LookupNPP(NPObject *npobj) { - if (npobj) { - if (npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass) { - nsJSObjWrapper *jsnpobj = (nsJSObjWrapper *)npobj; + if (npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass) { + NS_ERROR("NPP requested for NPObject of class " + "nsJSObjWrapper::sJSObjWrapperNPClass!\n"); - return jsnpobj->mNpp; - } - - NPObjWrapperHashEntry *entry = - NS_STATIC_CAST(NPObjWrapperHashEntry *, - PL_DHashTableOperate(&sNPObjWrappers, npobj, - PL_DHASH_ADD)); - - if (PL_DHASH_ENTRY_IS_BUSY(entry)) { - return entry->mNpp; - } + return nsnull; } - if (sNPObjWrappers.ops) { - NPObjWrapperHashEntry *entry = - NS_STATIC_CAST(NPObjWrapperHashEntry *, - PL_DHashTableOperate(&sNPObjWrappers, npobj, - PL_DHASH_ADD)); - if (PL_DHASH_ENTRY_IS_BUSY(entry)) { - return entry->mNpp; - } + + NPObjWrapperHashEntry *entry = + NS_STATIC_CAST(NPObjWrapperHashEntry *, + PL_DHashTableOperate(&sNPObjWrappers, npobj, + PL_DHASH_ADD)); + + if (PL_DHASH_ENTRY_IS_FREE(entry)) { + return nsnull; } - return nsnull; + NS_ASSERTION(entry->mNpp, "Live NPObject entry w/o an NPP!"); + + return entry->mNpp; } - - diff --git a/mozilla/modules/plugin/base/src/nsJSNPRuntime.h b/mozilla/modules/plugin/base/src/nsJSNPRuntime.h index 0d9ee6daf8b..86e83209ae6 100644 --- a/mozilla/modules/plugin/base/src/nsJSNPRuntime.h +++ b/mozilla/modules/plugin/base/src/nsJSNPRuntime.h @@ -50,16 +50,30 @@ public: static void OnPluginDestroy(NPP npp); }; -class nsJSObjWrapper : public NPObject +class nsJSObjWrapperKey +{ +public: + nsJSObjWrapperKey(JSObject *obj, NPP npp) + : mJSObj(obj), mNpp(npp) + { + } + + JSObject *mJSObj; + + const NPP mNpp; +}; + +class nsJSObjWrapper : public NPObject, + public nsJSObjWrapperKey { public: static NPObject *GetNewOrUsed(NPP npp, JSContext *cx, JSObject *obj); protected: - nsJSObjWrapper(); + nsJSObjWrapper(NPP npp); ~nsJSObjWrapper(); - static NPObject * NP_Allocate(); + static NPObject * NP_Allocate(NPP npp); static void NP_Deallocate(NPObject *obj); static void NP_Invalidate(NPObject *obj); static bool NP_HasMethod(NPObject *, NPIdentifier identifier); @@ -74,10 +88,6 @@ protected: static bool NP_RemoveProperty(NPObject *obj, NPIdentifier property); public: - JSObject *mJSObj; - JSContext *mCx; - NPP mNpp; - static NPClass sJSObjWrapperNPClass; };