Landing fix for bug 296159. Adding support for NPObject enumeration to npruntime. Patch by alfred.peng@sun.com, r=mrbkap@gmail.com, sr=jst@mozilla.org
git-svn-id: svn://10.0.0.236/trunk@191449 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* npapi.h $Revision: 3.41 $
|
||||
* npapi.h $Revision: 3.42 $
|
||||
* Netscape client plug-in API spec
|
||||
*/
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define NP_VERSION_MAJOR 0
|
||||
#define NP_VERSION_MINOR 16
|
||||
#define NP_VERSION_MINOR 17
|
||||
|
||||
|
||||
/* The OS/2 version of Netscape uses RC_DATA to define the
|
||||
|
||||
@@ -292,6 +292,8 @@ typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
|
||||
const NPVariant *value);
|
||||
typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj,
|
||||
NPIdentifier name);
|
||||
typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value,
|
||||
uint32_t *count);
|
||||
|
||||
/*
|
||||
NPObjects returned by create, retain, invoke, and getProperty pass
|
||||
@@ -310,6 +312,11 @@ typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj,
|
||||
will typically return immediately, with 0 or NULL, from an attempt
|
||||
to dispatch to a NPObject, but this behavior should not be
|
||||
depended upon.)
|
||||
|
||||
The NPEnumerationFunctionPtr function may pass an array of
|
||||
NPIdentifiers back to the caller. The callee allocs the memory of
|
||||
the array using NPN_MemAlloc(), and it's the caller's responsibility
|
||||
to release it using NPN_MemFree().
|
||||
*/
|
||||
struct NPClass
|
||||
{
|
||||
@@ -324,9 +331,14 @@ struct NPClass
|
||||
NPGetPropertyFunctionPtr getProperty;
|
||||
NPSetPropertyFunctionPtr setProperty;
|
||||
NPRemovePropertyFunctionPtr removeProperty;
|
||||
NPEnumerationFunctionPtr enumerate;
|
||||
};
|
||||
|
||||
#define NP_CLASS_STRUCT_VERSION 1
|
||||
#define NP_CLASS_STRUCT_VERSION 2
|
||||
#define NP_CLASS_STRUCT_VERSION_ENUM 2
|
||||
|
||||
#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
|
||||
((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
|
||||
|
||||
struct NPObject {
|
||||
NPClass *_class;
|
||||
@@ -381,6 +393,8 @@ bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
|
||||
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);
|
||||
bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
|
||||
uint32_t *count);
|
||||
|
||||
/*
|
||||
NPN_SetException may be called to trigger a script exception upon
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* npupp.h $Revision: 3.20 $
|
||||
* npupp.h $Revision: 3.21 $
|
||||
* function call mecahnics needed by platform specific glue code.
|
||||
*/
|
||||
|
||||
@@ -1638,6 +1638,35 @@ typedef bool (* NP_LOADDS NPN_PopPopupsEnabledStateUPP)(NPP npp);
|
||||
|
||||
#endif
|
||||
|
||||
/* NPN_Enumerate */
|
||||
|
||||
#if _NPUPP_USE_UPP_
|
||||
|
||||
typedef UniversalProcPtr NPN_EnumerateUPP;
|
||||
enum {
|
||||
uppNPN_EnumerateProcInfo = 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**)))
|
||||
| STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32_t*)))
|
||||
| RESULT_SIZE(SIZE_CODE(sizeof(bool)))
|
||||
};
|
||||
|
||||
#define NewNPN_EnumerateProc(FUNC) \
|
||||
(NPN_EnumerateUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_EnumerateProcInfo, GetCurrentArchitecture())
|
||||
#define CallNPN_EnumerateProc(FUNC, ARG1, ARG2, ARG3, ARG4) \
|
||||
(jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_EnumerateProcInfo, (ARG1), (ARG2), (ARG3), (ARG4))
|
||||
|
||||
#else
|
||||
|
||||
typedef bool (* NP_LOADDS NPN_EnumerateUPP)(NPP npp, NPObject *obj, NPIdentifier **identifier, uint32_t *count);
|
||||
#define NewNPN_EnumerateProc(FUNC) \
|
||||
((NPN_EnumerateUPP) (FUNC))
|
||||
#define CallNPN_EnumerateProc(FUNC, ARG1, ARG2, ARG3, ARG4) \
|
||||
(*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/******************************************************************************************
|
||||
@@ -1714,6 +1743,7 @@ typedef struct _NPNetscapeFuncs {
|
||||
NPN_SetExceptionUPP setexception;
|
||||
NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate;
|
||||
NPN_PopPopupsEnabledStateUPP poppopupsenabledstate;
|
||||
NPN_EnumerateUPP enumerate;
|
||||
} NPNetscapeFuncs;
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
||||
@@ -396,6 +396,9 @@ ns4xPlugin::CheckClassInitialized(void)
|
||||
CALLBACKS.hasmethod =
|
||||
NewNPN_HasMethodProc(FP2TV(_hasmethod));
|
||||
|
||||
CALLBACKS.enumerate =
|
||||
NewNPN_EnumerateProc(FP2TV(_enumerate));
|
||||
|
||||
CALLBACKS.releasevariantvalue =
|
||||
NewNPN_ReleaseVariantValueProc(FP2TV(_releasevariantvalue));
|
||||
|
||||
@@ -1828,6 +1831,26 @@ _hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName)
|
||||
return npobj->_class->hasProperty(npobj, methodName);
|
||||
}
|
||||
|
||||
bool NP_EXPORT
|
||||
_enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
|
||||
uint32_t *count)
|
||||
{
|
||||
if (!npp || !npobj || !npobj->_class)
|
||||
return false;
|
||||
|
||||
if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj->_class) ||
|
||||
!npobj->_class->enumerate) {
|
||||
*identifier = 0;
|
||||
*count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
NPPExceptionAutoHolder nppExceptionHolder;
|
||||
NPPAutoPusher nppPusher(npp);
|
||||
|
||||
return npobj->_class->enumerate(npobj, identifier, count);
|
||||
}
|
||||
|
||||
void NP_EXPORT
|
||||
_releasevariantvalue(NPVariant* variant)
|
||||
{
|
||||
|
||||
@@ -241,6 +241,10 @@ _hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName);
|
||||
bool NP_EXPORT
|
||||
_hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName);
|
||||
|
||||
bool NP_EXPORT
|
||||
_enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
|
||||
uint32_t *count);
|
||||
|
||||
void NP_EXPORT
|
||||
_releasevariantvalue(NPVariant *variant);
|
||||
|
||||
|
||||
@@ -103,7 +103,8 @@ NPClass nsJSObjWrapper::sJSObjWrapperNPClass =
|
||||
nsJSObjWrapper::NP_HasProperty,
|
||||
nsJSObjWrapper::NP_GetProperty,
|
||||
nsJSObjWrapper::NP_SetProperty,
|
||||
nsJSObjWrapper::NP_RemoveProperty
|
||||
nsJSObjWrapper::NP_RemoveProperty,
|
||||
nsJSObjWrapper::NP_Enumerate
|
||||
};
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
@@ -118,6 +119,10 @@ NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
NPObjWrapper_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSObject **objp);
|
||||
@@ -135,9 +140,9 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj,
|
||||
|
||||
static JSClass sNPObjectJSWrapperClass =
|
||||
{
|
||||
"NPObject JS wrapper class", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
|
||||
"NPObject JS wrapper class", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
|
||||
NPObjWrapper_AddProperty, NPObjWrapper_DelProperty,
|
||||
NPObjWrapper_GetProperty, NPObjWrapper_SetProperty, JS_EnumerateStub,
|
||||
NPObjWrapper_GetProperty, NPObjWrapper_SetProperty, (JSEnumerateOp)NPObjWrapper_newEnumerate,
|
||||
(JSResolveOp)NPObjWrapper_NewResolve, JS_ConvertStub,
|
||||
NPObjWrapper_Finalize, nsnull, nsnull, NPObjWrapper_Call, nsnull, nsnull,
|
||||
nsnull
|
||||
@@ -496,6 +501,9 @@ nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier identifier)
|
||||
JSContext *cx = GetJSContext(npp);
|
||||
|
||||
if (!cx || !npobj) {
|
||||
ThrowJSException(cx,
|
||||
"Null npobj or cx in nsJSObjWrapper::NP_HasMethod!");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
@@ -515,7 +523,7 @@ doInvoke(NPObject *npobj, NPIdentifier method, const NPVariant *args,
|
||||
JSContext *cx = GetJSContext(npp);
|
||||
|
||||
if (!cx || !npobj || !result) {
|
||||
// XXX: Throw null-ptr exception
|
||||
ThrowJSException(cx, "Null npobj, cx, or result in doInvoke!");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
@@ -544,9 +552,8 @@ doInvoke(NPObject *npobj, NPIdentifier method, const NPVariant *args,
|
||||
// Our stack buffer isn't large enough to hold all arguments,
|
||||
// malloc a buffer.
|
||||
jsargs = (jsval *)PR_Malloc(argCount * sizeof(jsval));
|
||||
|
||||
if (!jsargs) {
|
||||
// XXX: throw an OOM exception!
|
||||
::JS_ReportOutOfMemory(cx);
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
@@ -601,7 +608,8 @@ nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier identifier)
|
||||
JSContext *cx = GetJSContext(npp);
|
||||
|
||||
if (!cx || !npobj) {
|
||||
// XXX: Throw null ptr exception
|
||||
ThrowJSException(cx,
|
||||
"Null cx or npobj in nsJSObjWrapper::NP_HasProperty!");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
@@ -632,8 +640,12 @@ nsJSObjWrapper::NP_GetProperty(NPObject *npobj, NPIdentifier identifier,
|
||||
NPP npp = NPPStack::Peek();
|
||||
JSContext *cx = GetJSContext(npp);
|
||||
|
||||
if (!cx || !npobj)
|
||||
if (!cx || !npobj) {
|
||||
ThrowJSException(cx,
|
||||
"Null cx or npobj in nsJSObjWrapper::NP_GetProperty!");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||
|
||||
@@ -652,8 +664,12 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier identifier,
|
||||
NPP npp = NPPStack::Peek();
|
||||
JSContext *cx = GetJSContext(npp);
|
||||
|
||||
if (!cx || !npobj)
|
||||
if (!cx || !npobj) {
|
||||
ThrowJSException(cx,
|
||||
"Null cx or npobj in nsJSObjWrapper::NP_SetProperty!");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||
jsval id = (jsval)identifier;
|
||||
@@ -686,8 +702,12 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier)
|
||||
NPP npp = NPPStack::Peek();
|
||||
JSContext *cx = GetJSContext(npp);
|
||||
|
||||
if (!cx || !npobj)
|
||||
if (!cx || !npobj) {
|
||||
ThrowJSException(cx,
|
||||
"Null cx or npobj in nsJSObjWrapper::NP_RemoveProperty!");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||
jsval id = (jsval)identifier;
|
||||
@@ -712,6 +732,74 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier identifier)
|
||||
return ok == JS_TRUE;
|
||||
}
|
||||
|
||||
//static
|
||||
bool
|
||||
nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **identifier,
|
||||
uint32_t *count)
|
||||
{
|
||||
NPP npp = NPPStack::Peek();
|
||||
JSContext *cx = GetJSContext(npp);
|
||||
|
||||
*identifier = 0;
|
||||
*count = 0;
|
||||
|
||||
if (!cx || !npobj) {
|
||||
ThrowJSException(cx,
|
||||
"Null cx or npobj in nsJSObjWrapper::NP_Enumerate!");
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
|
||||
|
||||
AutoCXPusher pusher(cx);
|
||||
|
||||
JSIdArray *ida = ::JS_Enumerate(cx, npjsobj->mJSObj);
|
||||
if (!ida) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
*count = ida->length;
|
||||
*identifier = (NPIdentifier *)PR_Malloc(*count * sizeof(NPIdentifier));
|
||||
if (!*identifier) {
|
||||
ThrowJSException(cx, "Memory allocation failed for NPIdentifier!");
|
||||
|
||||
::JS_DestroyIdArray(cx, ida);
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < *count; i++) {
|
||||
jsval v;
|
||||
if (!::JS_IdToValue(cx, ida->vector[i], &v)) {
|
||||
::JS_DestroyIdArray(cx, ida);
|
||||
PR_Free(*identifier);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
JSString *str = JSVAL_TO_STRING(v);
|
||||
|
||||
if (!JS_InternUCStringN(cx, ::JS_GetStringChars(str),
|
||||
::JS_GetStringLength(str))) {
|
||||
::JS_DestroyIdArray(cx, ida);
|
||||
PR_Free(*identifier);
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(JSVAL_IS_INT(v),
|
||||
"The element in ida must be either string or int!\n");
|
||||
}
|
||||
|
||||
(*identifier)[i] = (NPIdentifier)v;
|
||||
}
|
||||
|
||||
::JS_DestroyIdArray(cx, ida);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
class JSObjWrapperHashEntry : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
@@ -1129,6 +1217,82 @@ CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return ReportExceptionIfPending(cx);
|
||||
}
|
||||
|
||||
struct NPObjectEnumerateState {
|
||||
PRUint32 index;
|
||||
PRUint32 length;
|
||||
NPIdentifier *value;
|
||||
};
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
NPObjWrapper_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
NPObject *npobj = GetNPObject(cx, obj);
|
||||
NPIdentifier *enum_value;
|
||||
PRUint32 length;
|
||||
NPObjectEnumerateState *state;
|
||||
|
||||
if (!npobj || !npobj->_class) {
|
||||
ThrowJSException(cx, "Bad NPObject as private data!");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(statep, "Must have a statep to enumerate!");
|
||||
|
||||
switch(enum_op) {
|
||||
case JSENUMERATE_INIT:
|
||||
state = new NPObjectEnumerateState();
|
||||
if (!state) {
|
||||
ThrowJSException(cx, "Memory allocation failed for "
|
||||
"NPObjectEnumerateState!");
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(npobj->_class) ||
|
||||
!npobj->_class->enumerate) {
|
||||
enum_value = 0;
|
||||
length = 0;
|
||||
} else if (!npobj->_class->enumerate(npobj, &enum_value, &length)) {
|
||||
ThrowJSException(cx, "Error enumerating properties on scriptable "
|
||||
"plugin object");
|
||||
delete state;
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
state->value = enum_value;
|
||||
state->length = length;
|
||||
state->index = 0;
|
||||
*statep = PRIVATE_TO_JSVAL(state);
|
||||
if (idp) {
|
||||
*idp = INT_TO_JSVAL(length);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case JSENUMERATE_NEXT:
|
||||
state = (NPObjectEnumerateState *)JSVAL_TO_PRIVATE(*statep);
|
||||
enum_value = state->value;
|
||||
length = state->length;
|
||||
if (state->index != length) {
|
||||
return ::JS_ValueToId(cx, (jsval)enum_value[state->index++], idp);
|
||||
}
|
||||
|
||||
// FALL THROUGH
|
||||
|
||||
case JSENUMERATE_DESTROY:
|
||||
state = (NPObjectEnumerateState *)JSVAL_TO_PRIVATE(*statep);
|
||||
if (state->value)
|
||||
PR_Free(state->value);
|
||||
delete state;
|
||||
*statep = JSVAL_NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
|
||||
@@ -88,6 +88,8 @@ protected:
|
||||
static bool NP_SetProperty(NPObject *obj, NPIdentifier property,
|
||||
const NPVariant *value);
|
||||
static bool NP_RemoveProperty(NPObject *obj, NPIdentifier property);
|
||||
static bool NP_Enumerate(NPObject *npobj, NPIdentifier **identifier,
|
||||
uint32_t *count);
|
||||
|
||||
public:
|
||||
static NPClass sJSObjWrapperNPClass;
|
||||
|
||||
Reference in New Issue
Block a user