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;
}
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;
obj->dwc = [[DownloadWindowController alloc] init];
NPBool supportsCoreAnimation;
if (browser->getvalue(instance, NPNVsupportsCoreAnimationBool, &supportsCoreAnimation) != NPERR_NO_ERROR)
supportsCoreAnimation =
FALSE ;
if (!supportsCoreAnimation)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
browser->setvalue(instance, NPPVpluginDrawingModel, (
void *)NPDrawingModelCoreAnimation);
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的实现完成了的功能是,当浏览器需要询问插件的显示视图时,我们在此处保持默认不显示,而是弹出我们的下载框。 到处为止主要的方法我们便都实现了,其它的几个方法实现都留了空或保持默认返回值,具体编码见源码。