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:
jst%mozilla.jstenback.com
2006-03-01 00:13:38 +00:00
parent f9659c1a5b
commit dc4b19a5f8
7 changed files with 251 additions and 14 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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