【问题标题】:NPAPI invoke argument wrappingNPAPI 调用参数包装
【发布时间】:2012-09-04 08:35:12
【问题描述】:

我编写了一个包含两种插件类型的 NPAPI 插件:

  • x-capture 用于从相机捕捉一些视频
  • x-display 用于显示由 x-capture 对象捕获的图像

我有以下使用该插件的 HTML/JavaScript 代码:

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

我的问题是我的库中的 addDisplay 调用接收到一个不同的 NPObject 指针作为调用参数,然后是与提供的 x-display 实例关联的那个。 此外,收到的 NPObject 结构的 _class 成员与我在创建 x-display 可脚本化对象时提供的成员不同。

在尝试枚举接收对象的方法(来自 handleAddDisplay 函数)以了解有关接收参数类型的更多信息后,我得到了一个调用堆栈,其中包括 nsJSObjWrapper(我正在 Firefox/Windows 上对其进行测试)。我的库是 npCaptureDemoPlugin.dll。最后包装器正在调用显示对象的枚举。

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

所以它看起来像 Firefox 将我的 NPObject 包装到另一个我无法处理的类型的 NPObject 中,并且这个 NPObject 用作​​调用我的对象的代理。

我的问题:有没有一种方法可以将相同的 NPObject 传递给与我与插件实例关联的函数调用相同的函数调用?或者是否有另一种方法来检查接收到的对象作为 Invoke 调用的参数,它是我之前创建的预期类型?或者唯一的方法是使用某种原生 id 传递给 JS 并返回到原生代码,这样我就可以在我的对象之间建立关联?

【问题讨论】:

  • 经过更多调查后,收到的 NPObject 看起来像是一个包装器,其中还包括 DOM 功能(如 with/height 属性等)。一种解决方案可能是添加一个函数,该函数返回我的脚本对象,如果类型不是预期的类型(包装器),则在 addDisplay 函数中调用。
  • 请注意,无窗口插件和不绘图插件之间存在很大差异。在将其标记为无窗口之前,请确保您了解差异 =]
  • 我的错误。我在考虑隐藏与可见插件。

标签: c++ c npapi


【解决方案1】:

浏览器通常会先包装一个插件中的 NPObject,然后再将其提供给另一个插件;我认为这是一种安全预防措施,它实际上意味着你不能做你想做的事。但是,您可以做的是,您可以为每个 NPObject 提供某种形式的唯一 ID,并在对象上使用 getID 方法。然后,您只需要一个地图或内部类似的东西,您可以在通过 NPObject 接口查询 getID 后使用它来获取您需要的实际对象。

【讨论】:

  • 当属于一个插件实例的 NPObject 被赋予另一个插件实例时,它看起来就像发生了包装。这样做是因为销毁插件实例也将销毁属于被销毁插件实例的所有 NPObject,即使 referenceCount 未达到 0。它看起来像包装器,除其他外,通过实现 no- 来防止访问被销毁的 NPObject如果包装的对象被破坏,则操作。至少这似乎发生在 Firefox/Windows 上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多