您的位置:首页 > 其它

npapi总结--发文于2013-12-13

2016-01-15 22:48 309 查看
一个插件中的方法分为插件方法(Plug-in Methods)和浏览器方法(Browser Methods)。

插件方法是你在插件中自己去执行的那些方法,以NPP为前缀命名。

浏览器方法是被Gecko所执行的那些方法,以NPN为前缀命名。数据结构(Data Structures)以NP开头。

extension可以和web页面交互,或者通过content script 或者cross-original XMLHttpRequests与服务器交互。

extension还可以访问浏览器提供的内部功能,例如标签或者书签等。

几个关键接口的调用顺序.

NP_GetEntryPoints====> 在插件加载之后立即调用该接口,用于浏览器获取所有可能需要调用的API函数的指针。插件用NPP_New, NPP_Destroy, NPP_SetWindow等函数的入口地址填充一个函数表。

NP_Initialize  ====>被载入内存时,全局初始化,初始化浏览器实现的函数.插件存储一个NPN_CreateObject, NPN_MemAlloc,等函数入口地址组成的函数表的拷贝。

NPP_New               ====> 浏览器插件实例化时,创建插件对象实例. 插件创建一个新的插件实例并初始化

NPP_SetWindow   ====> 建立窗口时,浏览器传入插件窗口信息.每个实例都会多次调用这个函数——每次实例窗口创建、改变大小或者其他变化都会调用。

NPP_GetValue      ====> 设置NPObject对象时,浏览器用来获取插件信息. 插件创建一个支持脚本的NPObject并返回其指针(调用NPN_RetainObject)。

— 标准的插件活动 —

NPP_Destroy        ====> 插件销毁内存实例

NP_Shutdown     ====>最后一个插件实例被销毁时,反初始化

np_entry.cpp文件中可以找到上面的几个函数。

与js的交互方法, 主要依赖的是NPObject对象, 该对象的NPClass成员携带的是处理js交互的方法:

NPAllocateFunctionPtr            ==> 生成此NPClass对象的方法

NPDeallocateFunctionPtr       ==> 销毁此NPClass对象的方法

NPHasMethodFunctionPtr      ==> 检查获取的id是否是想要处理的

NPInvokeFunctionPtr               ==> 在上个函数设置为需要处理时, 会调用此函数

NPInvokeDefaultFunctionPtr  ==> 默认被调用的函数

NPHasPropertyFunctionPtr    ==> 

NPGetPropertyFunctionPtr     ==> 

NPSetPropertyFunctionPtr     ==>

插件的加载过程:

当一个页面打开时,如果该页面上有嵌入一个插件,浏览器将会做以下事情:

通过MIMEType检查是否有匹配插件

加载插件代码到内存

初始化插件

创建一个新的插件实例

插件可以在一个页面上被实例多个对象,也可以在同一时刻在不同的窗口中被实例化。当页面被关闭时,插件的实例就会被销毁。当最后一个实例被删除后,插件代码就会从内存中被卸载掉。

下面是插件内的函数调用过程:

如果插件是首次被载入内存,浏览器会调用插件的NP_Initialize方法。为了方便起见,所有的插件定义函数以“NPP”开头,所有的浏览器定义函数以“NPN”开头。

当浏览器创建插件实例时,会调用NPP_New方法。

当插件实例被删除时(如关闭页面、关闭窗口),会调用NPP_Destroy方法。

当最后一个实例被删除,插件从内存中卸载时,会调用NP_Shutdown方法

浏览器会传入NPPVpluginScriptableNPObject(作为variable参数)来查询插件是否支持Scriptable功能(即和脚本语言交互的功能),在这里,我们可以利用NPN_CreateObject方法来创建一个NPObject对象,并且作为value返回给浏览器。这样,浏览器就通过这个NPObject对象和我们的插件建立了连接。当页面上Javascript调用了我们插件对象的某个方法时,浏览器会调用该NPObject对象的HasMethod方法来查询是否支持这个方法,如果支持,则会调用NPObject对象的Invoke方法,传入方法名、参数等信息。这样,我们就可以让网页上的脚本语言来执行我们编写的函数了。在Windows上,我们编写的函数就如同编写普通的应用程序一样,可以使用很多Windows
API来完成许多复杂的工作。

plugin创建时,浏览器会创建一个子窗口,作为plugin的窗口(对于有窗口的plugin)。

对于windowed的plugin确实是窗口的句柄,而对于winless的plugin,window成员是一个HDC。因此,如果是winless的plugin,可以直接将pNPWindow->window强制转换为HDC然后在窗口中进行绘制、输出内容。

插件分为winless和windowed的,其主要区别是winless的插件窗口不是真正意义上的窗口只是网页的一部分,而windowed的插件窗口是浏览器的一个子窗口。由于winless的插件没有窗口所以其事件处理有一个专门的函数NPP_HandleEvent来对窗口的事件进行处理。对于winless的插件,事件响应函数就需要继承nsPluginInstanceBase类并实现函数HandleEvent;而对于windowed 的插件,插件窗口完全由插件控制,因此需要根据这个窗口句柄自行在插件中实现各种功能,包括事件消息响应等等。

npn_gate.cpp:在插件实例初始化的时候,将浏览器实现的这些函数的入口地址保存到一个NPNetscapeFuncs结构中,NPN_开头的这些函数名其实是开发插件时需要由开发者定义的,这些函数的实现就直接根据NPNetscapeFuncs结构中的入口地址调用浏览器实现的相关功能。但这些基本都是固定不变的,因此sdk中已经帮我们开发者写好了这些代码,在开发插件时只需要调用NPN_开头的全局函数即可。

NPP接口函数

可能调用的nsPluginInstanceBase成员函数或全局函数

备注

NPP_New

NS_NewPluginInstance

创建插件实例

NPP_Destroy

NS_DestroyPluginInstance、plugin->shut

删除插件实例

NPP_SetWindow

plugin->SetWindow、plugin->isInitialized、plugin->init、NS_DestroyPluginInstance

窗口创建、移动、改变大小或销毁时调用

NPP_NewStream

plugin->NewStream

通知插件实例有新的数据流

NPP_WriteReady

plugin->WriteReady

确定插件是否准备好接收数据(以及其准备接收的最大字节数)

NPP_Write

plugin->Write

调用以将数据读入插件this might be better named “NPP_DataArrived”

NPP_DestroyStream

plugin->DestroyStream

通知插件实例数据流将要关闭或销毁

NPP_StreamAsFile

plugin->StreamAsFile

为创建流数据提供本地文件名

NPP_Print

plugin->Print

为嵌入或全屏插件请求平台特定的打印操作

NPP_URLNotify

plugin->URLNotify

通知插件已完成URL请求

NPP_GetValue

plugin->GetValue

调用以查询插件信息(还用来获取NPObject/Scriptable 插件的实例)

NPP_SetValue

plugin->SetValue

这是用来为浏览器提供插件变量信息的

NPP_HandleEvent

plugin->HandleEvent

事件处理函数,对windowed的插件只在MAC操作系统上可用,对于winless的插件所有平台都可用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息