diff --git a/mozilla/modules/plugin/base/public/npapi.h b/mozilla/modules/plugin/base/public/npapi.h index 7cc73aa5e84..b39e93cfa01 100644 --- a/mozilla/modules/plugin/base/public/npapi.h +++ b/mozilla/modules/plugin/base/public/npapi.h @@ -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 diff --git a/mozilla/modules/plugin/base/public/npruntime.h b/mozilla/modules/plugin/base/public/npruntime.h index 2d1dc0253f4..29eae21db75 100644 --- a/mozilla/modules/plugin/base/public/npruntime.h +++ b/mozilla/modules/plugin/base/public/npruntime.h @@ -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 diff --git a/mozilla/modules/plugin/base/public/npupp.h b/mozilla/modules/plugin/base/public/npupp.h index f7e8e5d62d9..1d0d4c1592f 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.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 diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp index 01c621e2083..4a37ac1b520 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp @@ -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) { diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.h b/mozilla/modules/plugin/base/src/ns4xPlugin.h index aebfbfaa9ae..39aaf6ca6c7 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.h +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.h @@ -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); diff --git a/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp b/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp index bbe9af4573f..7219f11c76a 100644 --- a/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp +++ b/mozilla/modules/plugin/base/src/nsJSNPRuntime.cpp @@ -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, diff --git a/mozilla/modules/plugin/base/src/nsJSNPRuntime.h b/mozilla/modules/plugin/base/src/nsJSNPRuntime.h index a2bb27cee59..2715e39df7e 100644 --- a/mozilla/modules/plugin/base/src/nsJSNPRuntime.h +++ b/mozilla/modules/plugin/base/src/nsJSNPRuntime.h @@ -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;