NPAPI 插件运行流程分析

本文详细分析插件的代码是如何执行的,主要分析np_entry.cpp、npn_gate.cpp和npp_gate.cpp.希望能够有所收获。

在windows平台下,插件就是一个dll,注意到这个dll的def文件内容是:

NP_GetEntryPointsNP_InitializeNP_Shutdown

NP_GetEntryPoints – 在插件加载之后立即调用该接口,用于浏览器获取所有可能需要调用的API函数的指针。NP_Initialize – 为插件提供全局初始化。NP_Shutdown – 为插件提供全局反初始化。在np_entry.cpp文件中可以找到上面的几个函数。第一个:

NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* aNPPFuncs) { return fillPluginFunctionTable(aNPPFuncs); }

其调用的fillPluginFunctionTable为:

static NPError fillPluginFunctionTable(NPPluginFuncs* aNPPFuncs) { if (!aNPPFuncs) return NPERR_INVALID_FUNCTABLE_ERROR; // Set up the plugin function table that Netscape will use to call us. aNPPFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; aNPPFuncs->newp = NPP_New; aNPPFuncs->destroy = NPP_Destroy; aNPPFuncs->setwindow = NPP_SetWindow; aNPPFuncs->newstream = NPP_NewStream; aNPPFuncs->destroystream = NPP_DestroyStream; aNPPFuncs->asfile = NPP_StreamAsFile; aNPPFuncs->writeready = NPP_WriteReady; aNPPFuncs->write = NPP_Write; aNPPFuncs->print = NPP_Print; aNPPFuncs->event = NPP_HandleEvent; aNPPFuncs->urlnotify = NPP_URLNotify; aNPPFuncs->getvalue = NPP_GetValue; aNPPFuncs->setvalue = NPP_SetValue; return NPERR_NO_ERROR; }

fillPluginFunctionTable函数设置了一系列的函数入口,都是很熟悉的在mozilla的开发文档中经常提到的以NPP开头的函数。这些函数是需要在插件中加以实现的。第二个:

NPError OSCALL NP_Initialize(NPNetscapeFuncs* aNPNFuncs) { NPError rv = fillNetscapeFunctionTable(aNPNFuncs); if (rv != NPERR_NO_ERROR) return rv; return NS_PluginInitialize(); }

其调用的fillNetscapeFunctionTable为:

static NPError fillNetscapeFunctionTable(NPNetscapeFuncs* aNPNFuncs) { if (!aNPNFuncs) return NPERR_INVALID_FUNCTABLE_ERROR; if (HIBYTE(aNPNFuncs->version) > NP_VERSION_MAJOR) return NPERR_INCOMPATIBLE_VERSION_ERROR; if (aNPNFuncs->size < sizeof(NPNetscapeFuncs)) return NPERR_INVALID_FUNCTABLE_ERROR; NPNFuncs.size = aNPNFuncs->size; NPNFuncs.version = aNPNFuncs->version; NPNFuncs.geturlnotify = aNPNFuncs->geturlnotify; NPNFuncs.geturl = aNPNFuncs->geturl; NPNFuncs.posturlnotify = aNPNFuncs->posturlnotify; NPNFuncs.posturl = aNPNFuncs->posturl; NPNFuncs.requestread = aNPNFuncs->requestread; NPNFuncs.newstream = aNPNFuncs->newstream; NPNFuncs.write = aNPNFuncs->write; NPNFuncs.destroystream = aNPNFuncs->destroystream; NPNFuncs.status = aNPNFuncs->status; NPNFuncs.uagent = aNPNFuncs->uagent; NPNFuncs.memalloc = aNPNFuncs->memalloc; NPNFuncs.memfree = aNPNFuncs->memfree; NPNFuncs.memflush = aNPNFuncs->memflush; NPNFuncs.reloadplugins = aNPNFuncs->reloadplugins; NPNFuncs.getvalue = aNPNFuncs->getvalue; NPNFuncs.setvalue = aNPNFuncs->setvalue; NPNFuncs.invalidaterect = aNPNFuncs->invalidaterect; NPNFuncs.invalidateregion = aNPNFuncs->invalidateregion; NPNFuncs.forceredraw = aNPNFuncs->forceredraw; return NPERR_NO_ERROR; }

这里获取一系列函数的入口,这些函数是浏览器中实现的。NP_Initialize还调用了一个函数NS_PluginInitialize(),NS_PluginInitialize是我们在plugin.cpp中实现的,随便提一句,NP_Shutdown调用的NS_PluginShutdown也是在plugin.cpp中由我们自己去实现的。通过对上面的代码的分析,可以发现虽然在def里面只定义了三个接口,但实际上却包括浏览器实现的由浏览器调用的接口21个以及浏览器要调用的由插件实现的接口13个(实际上NPNetscapeFuncs结构定义了55个函数指针,NPPluginFuncs结构定义了19个函数指针)。换句话说,我们开发插件就是要来实现这13个接口。接口的标准已经由浏览器定义好了,我们怎么去实现以及要实现什么样的功能就全凭我们自己了。np_entry.cpp这个文件已经分析得差不多了,这个文件包含了两个头文件,"npplat.h"和"pluginbase.h",打开这两个文件来看看里面定义了些什么。npplat.h很简单:

天再高又怎样,踮起脚尖就更接近阳光。

NPAPI 插件运行流程分析

相关文章:

你感兴趣的文章:

标签云: