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
This commit is contained in:
jst%mozilla.jstenback.com
2004-07-30 04:00:05 +00:00
parent f79f989daf
commit 3b04c93333
7 changed files with 494 additions and 219 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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__

View File

@@ -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:

View File

@@ -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<nsIPluginInstancePeer> pip;
inst->GetPeer(getter_AddRefs(pip));
nsCOMPtr<nsPIPluginInstancePeer> pp (do_QueryInterface(pip));
nsCOMPtr<nsPIPluginInstancePeer> pp(do_QueryInterface(inst->Peer()));
NS_ENSURE_TRUE(pp, nsnull);
nsCOMPtr<nsIPluginInstanceOwner> 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;
}

View File

@@ -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;
};