8

我正在编写一个网络浏览器插件(NPAPI。)

我的插件启动了一个工作线程,随着工作的进展,我想将事件传递回 Javascript。但是由于NPAPI线程模型,工作线程直接回调NPAPI是不合法的,所以工作线程不能调用Javascript。

一种解决方案是 NPN_PluginThreadAsyncCall 函数。但这是一个相对较新的功能。例如,它仅从 Firefox 3 开始受支持。

有没有办法在不使用 NPN_PluginThreadAsyncCall 的情况下从 NPAPI 插件获取异步事件传递/javascript 执行?在添加此功能之前人们做了什么?

4

1 回答 1

5

答案是肯定的……而且不是……

如果需要支持旧版浏览器(firefox 3 之前),可以自己实现 NPN_PluginThreadAsyncCall 函数。在 Windows 上,您可以通过创建一个可以保存函数指针和 void* opaque 指针的数据结构来做到这一点,然后将自定义消息发布到主窗口,并将指向您的数据结构的指针作为 LPARAM。

主窗口 WINPPROC 在 UI 线程上运行,这是可以与 Javascript 对话的线程。因此,当您在 WINPROC 中收到该消息时,您只需将 LPARAM 转换回指针,使用不透明数据调用方法,然后释放数据结构。

在 Mac 上,您可以使用队列执行类似的操作来存储事件,然后在 NULL 事件(Mac OS 大约在每个滴答声中发送)检查其中是否有任何内容。如果是这样,将其弹出,调用该方法,释放它,然后继续。

在linux上可能也有一种方法可以做到这一点,但我不知道它是什么。

您可以在firebreath 项目中找到 windows 版本的示例。

winproc 消息的处理在这个文件中: https ://github.com/firebreath/FireBreath/blob/master/src/PluginWindow/Win/PluginWindowWin.cpp

事件和数据结构在其头文件中定义: https ://github.com/firebreath/FireBreath/blob/master/src/PluginWindow/Win/PluginWindowWin.h

触发该事件的方法在这里:

void ActiveXBrowserHost::ScheduleAsyncCall(void (*func)(void *), void *userData)
{
    if (m_hWnd != NULL) 
        ::PostMessage(m_hWnd, WM_ASYNCTHREADINVOKE, NULL, 
            (LPARAM)new FB::WINDOWS_ASYNC_EVENT(func, userData));
}
于 2009-12-20T07:17:30.893 回答