I writting a NPAPI plugin which contains two plugin types:
and I have the following HTML/JavaScript code which uses the plugin:
<html>
<embed id="display" type="application/x-display" width=640 height=480 /></td>
<embed id="capture" type="application/x-capture" width=0 height=0 /><br> <!-- windowless plugin -->
<script>
var capture = document.getElementById('capture');
var display = document.getElementById('display');
capture.addDisplay(display);
</script>
</html>
My problem is that the call of addDisplay in my library receive a different NPObject pointer as call argument then the one associated with the instance of the provided x-display. Also the _class member of the received NPObject structure is different then the one I provided when I've created the x-display scriptable object.
After trying to enumerate the methods of the received objects (from handleAddDisplay function) to find out more about the type of received argument I've get a call stack which includes nsJSObjWrapper (I'm testing it on Firefox/Windows). My library is npCaptureDemoPlugin.dll. In the end the wrapper is calling the enumerate of the display object.
npCaptureDemoPlugin.dll!RendererPlugin::hasMethod(void * name=0x06311d00) Line 84 C++
npCaptureDemoPlugin.dll!ScriptableObject<RendererPlugin>::Class::hasMethod(NPObject* object=0x191fd0b4, void * name=0x06311d00) Line 382 + 0x43 bytes C++
xul.dll!NPObjWrapper_NewResolve(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c4c0, int id=0x06311d00, unsigned int flags=0x00000001, JSObject * * objp=0x003cb838) Line 1659 C++
mozjs.dll!CallResolveOp(JSContext * cx=0x13bf8f60, JSObject * start=0x0650c4a0, JS::Handle<JSObject *> obj={...}, JS::Handle<int> id={...}, unsigned int flags=0x00000000, JSObject * * objp=0x003cb8dc, JSProperty * * propp=0x003cb8d4, bool * recursedp=0x003cb883) Line 4637 + 0x1b bytes C++
mozjs.dll!js_LookupProperty(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c4a0, int id=0x06311d00, JSObject * * objp=0x003cb8dc, JSProperty * * propp=0x003cb8d4) Line 4745 + 0x7a bytes C++
mozjs.dll!JS_LookupPropertyById(JSContext * cx=0x00000000, JSObject * obj=0x0650c4a0, int id=0x06311d00, JS::Value * vp=0x003cb8e4) Line 3502 + 0x49 bytes C++
xul.dll!xpc_ForcePropertyResolve(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c4a0, int id=0x06311d00) Line 652 + 0x13 bytes C++
xul.dll!XPC_WN_Shared_Enumerate(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c4a0) Line 605 + 0xe bytes C++
xul.dll!XPC_WN_JSOp_Enumerate(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c4a0, JSIterateOp enum_op=JSENUMERATE_INIT, JS::Value * statep=0x003cbaf4, int * idp=0x00000000) Line 1275 + 0x1b bytes C++
mozjs.dll!Snapshot(JSContext * cx=0x00000000, JSObject * obj=0x00000000, unsigned int flags=0x00000008, JS::AutoIdVector * props=0x003cbb78) Line 364 + 0x25 bytes C++
mozjs.dll!js::GetPropertyNames(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c4a0, unsigned int flags=0x00000008, JS::AutoIdVector * props=0x003cbb78) Line 440 + 0x1a bytes C++
mozjs.dll!JS_Enumerate(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c4a0) Line 4241 + 0x34 bytes C++
xul.dll!nsJSObjWrapper::NP_Enumerate(NPObject * npobj=0x089cbd90, void * * * idarray=0x003cbf74, unsigned int * count=0x003cbf68) Line 968 + 0xe bytes C++
xul.dll!mozilla::plugins::parent::_enumerate(_NPP * npp=0x10eff7c8, NPObject * npobj=0x089cbd90, void * * * identifier=0x003cbf74, unsigned int * count=0x003cbf68) Line 1900 + 0xc bytes C++
npCaptureDemoPlugin.dll!NPN_Enumerate(_NPP * npp=0x10eff7c8, NPObject * obj=0x089cbd90, void * * * identifier=0x003cbf74, unsigned int * count=0x003cbf68) Line 254 + 0x18 bytes C++
npCaptureDemoPlugin.dll!CapturePlugin::handleAddDisplay(NPObject * object=0x089cbd90) Line 382 + 0x18 bytes C++
npCaptureDemoPlugin.dll!CapturePlugin::invoke(void * name=0x13855280, const _NPVariant * args=0x003cc270, unsigned int argCount=0x00000001, _NPVariant * result=0x003cc248) Line 142 + 0xf bytes C++
npCaptureDemoPlugin.dll!ScriptableObject<CapturePlugin>::Class::invoke(NPObject * object=0x191feb04, void * name=0x13855280, const _NPVariant * args=0x003cc270, unsigned int argCount=0x00000001, _NPVariant * result=0x003cc248) Line 414 + 0x4f bytes C++
xul.dll!CallNPMethodInternal(JSContext * cx=0x13bf8f60, JSObject * obj=0x0650c3a0, unsigned int argc=0x00000001, JS::Value * argv=0x05cd0070, JS::Value * rval=0x05cd0060, bool ctorCall=false) Line 1482 + 0x11 bytes C++
So its look like Firefox wrap my NPObject into another NPObject whose type I cannot handle and this NPObject is used as a proxy to call my object.
My question: is there a way of passing the same NPObject to a function call as the same one which I've associated with a plugin instance? Or is there another way to check for the received object as argument to an Invoke call that it is the expected type which I previously created? Or the only way is to use some kind of native id passed to JS and back to native code so I can make the associations between my objects?
The browsers often will wrap the NPObject from one plugin before giving it to another; I assume this is a security precaution and it effectively means you can't do what you want to do. What you can do, however, is you can give each NPObject some form of unique ID and have a getID method on the object. Then you just need a map or something similar internally that you can use to get the actual object that you need after you query getID through the NPObject interface.