浏览器插件编程NPAPI

NPAPI就是Netscape Plugin Application Programming Interface的缩写,Netscape应该大家都不陌生吧,曾经的浏览器鼻祖,虽然Netscape早已离我们而去,但Netscape很多技术却被保留了下来(尤其是Mozila),在各主流的浏览器中都得以实现,其中就包括NPAPI这套接口。

NPAPI是一套用C语言编写的跨平台的浏览器插件接口,所以对NPAPI的学习也是非常有意义的,比如在Mac OSX平台上面利用NPAPI编写的插件,就可以在Safari、Chrome、FireFox中同时使用。NPAPI式的插件环境允许插件访问的脚本语言,如JavaScript。它可以让脚本语言来访问和控制元素。

插件与扩展的差异(部分参考于Google的搜索结果)

插件(Plugins):在浏览器中,插件的功能就是将第三方的库提供的功能通过embed,object标签在页面中应用起来,比如Flash插件,Silverlight插件,Quicktime插件。这些插件就像驱动程序一样,使得你的浏览器可以调用本地方法,系统的接口,实现浏览器无法独立实现的功能,或者这么讲,插件使得别的程序才能处理的内容在浏览器的页面中得以展现和处理。

扩展(Extensions or Add-ones):扩展通常是通过程序自身所开放的api来实现的用于扩展程序自身功能的东西,在浏览器中,比如Firefox的Firebug,浏览器的Twitter的插件,这些插件很多都是增加一些浏览器上的窗口或者按钮,来扩展浏览器的功能。这里有一点需要说明一下,扩展本身可以包含一个或者多个插件,但是插件不包含扩展。

附2:Apple关于NPAPI的插件的示例:NPAPI_Core_Animation_Movie_Plugin


代码实现:

插件要与浏览器进行通信,所以必须实现以下的接口:

     
     
1
2
3
     
     
NPError NP_Initialize(NPNetscapeFuncs *browserFuncs);
NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs);
void NP_Shutdown( void);

NP_Initialize是插件实例化时将浏览器的结构体指针(NPNetscapeFuncs*)传递给插件的方法,NP_GetEntryPoints方法是用于浏览器取得插件的结构体指针(NPPluginFuncs*),NS_Shutdown是指当插件关闭时调用的方法。

以下是接口的实现:

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
     
     
//通过此方法将浏览器的对象返回给插件
NPError NP_Initialize(NPNetscapeFuncs* browserFuncs)
{
browser = browserFuncs;
return NPERR_NO_ERROR;
}
//通过此方法将插件的接口返回给浏览器(填充NPPluginFuncs结构体中的方法指针,让浏览器可以调用本插件)
NPError NP_GetEntryPoints(NPPluginFuncs* pluginFuncs)
{
pluginFuncs->version = 11;
pluginFuncs->size = sizeof(pluginFuncs);
pluginFuncs->newp = NPP_New;
pluginFuncs->destroy = NPP_Destroy;
pluginFuncs->setwindow = NPP_SetWindow;
pluginFuncs->newstream = NPP_NewStream;
pluginFuncs->destroystream = NPP_DestroyStream;
pluginFuncs->asfile = NPP_StreamAsFile;
pluginFuncs->writeready = NPP_WriteReady;
pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write;
pluginFuncs->print = NPP_Print;
pluginFuncs->event = NPP_HandleEvent;
pluginFuncs->urlnotify = NPP_URLNotify;
pluginFuncs->getvalue = NPP_GetValue;
pluginFuncs->setvalue = NPP_SetValue;
return NPERR_NO_ERROR;
}
void NP_Shutdown( void)
{
browser = NULL;
}

其中NP_Initialize方法体中,我们使用了一个全局指针browser来保存对浏览器的引用,NP_Shutdown是当插件关闭时调用的方法。NP_GetEntryPoints方法体中,就是对参数中的pluginFuncs结构体进行填充,pluginFuncs结构体是插件提供给浏览器所有方法的集合,是浏览器对于插件的一个引用,浏览器也是通过pluginFuncs中包含的方法与插件进行交互。所以如NPP_New、NPP_Destroy等方法便对应了main中实现的这些方法:

NPP_New方法的实现

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
     
     
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved)
{
//创建一个插件实例对象
PluginObject *obj = (PluginObject *)malloc( sizeof(PluginObject));
bzero(obj, sizeof(PluginObject));
obj->npp = instance;
instance->pdata = obj;
//每一个实例对应了一个WindowController
obj->dwc = [[DownloadWindowController alloc] init];
// 询问浏览器是否支持 Core Animation 绘制模式
NPBool supportsCoreAnimation;
if (browser->getvalue(instance, NPNVsupportsCoreAnimationBool, &supportsCoreAnimation) != NPERR_NO_ERROR)
supportsCoreAnimation = FALSE;
if (!supportsCoreAnimation)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
// 询问浏览器是否支持 Core Animation 绘制, 如果支持便开启它
browser->setvalue(instance, NPPVpluginDrawingModel, ( void *)NPDrawingModelCoreAnimation);
// 询问浏览器是否支持 Cocoa event model, 如果支持便开启它
NPBool supportsCocoa;
if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NPERR_NO_ERROR)
supportsCocoa = FALSE;
if (!supportsCocoa)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
browser->setvalue(instance, NPPVpluginEventModel, ( void *)NPEventModelCocoa);
for (int16_t i = 0; i < argc; i++) {
//保存下载的链接地址
if (strcasecmp(argn[i], "src") == 0) {
NSString *urlString = [ NSString stringWithUTF8String:argv[i]];
if (urlString)
{
[obj->dwc setUrl:[ NSURL URLWithString:urlString]];
break;
}
}
}
return NPERR_NO_ERROR;
}

此方法主要是对浏览器环境的配置和对应一个实例的默认设置,在方法的最后面我们通过参数获取了下载地址的url,并设置了WindowController对应的值。

NPP_Destroy方法的实现

     
     
1
2
3
4
5
6
7
8
9
10
     
     
NPError NPP_Destroy(NPP instance, NPSavedData** save)
{
PluginObject *obj = instance->pdata;
[obj->dwc release];
free(obj);
return NPERR_NO_ERROR;
}

此方法主要完成对实例内存的释放,以完成内存清理。

NPP_GetValue方法的实现

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
     
     
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
PluginObject *obj = instance->pdata;
switch (variable) {
case NPPVpluginCoreAnimationLayer:
*( CALayer **)value = NULL;
[[obj->dwc window] center];
[[obj->dwc window] orderFrontRegardless];
return NPERR_NO_ERROR;
default:
return NPERR_GENERIC_ERROR;
}
return NPERR_NO_ERROR;
}

此处NPP_GetValue的实现完成了的功能是,当浏览器需要询问插件的显示视图时,我们在此处保持默认不显示,而是弹出我们的下载框。
到处为止主要的方法我们便都实现了,其它的几个方法实现都留了空或保持默认返回值,具体编码见源码。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值