在NPAPI开发火狐浏览器插件在NPAPI插件
1.插件是什么
插件是一种遵循一定规范的应用程序接口编写出来的程序。插件必须依附于一个宿主程序,为宿主程序提供增强功能。插件的种类有很多,这里主要讨论浏览器插件。
IE下利用OLE和COM技术开发的浏览器插件称为ActiveX控件。一般以.ocx为扩展名。IE浏览器通过OLE标准与ActiveX控件之间进行交互,完成对现有功能的扩充。
IE和OLE技术都是微软出的,所以如果在非IE浏览器下开发插件,就不能使用现有的COM技术标准。NPAPI技术提供了一种新的开发浏览器下插件的标准。浏览器和插件共同遵守这一标准,完成功能和交互。
2.Netscape插件
支持NPAPI标准的浏览器有很多,这里以Firefox为例进行说明,不同的浏览器在具体的实现上可能有所不同。
Netscape插件是遵循NPAPI标准开发出的对浏览器扩展的插件模块。 在firefox下,将插件(dll)放入firefox安装目录下的plugins文件夹中,启动firefox,浏览器会通过插件的MimeType属性识别出该插件。可以在地址栏中输入about:plugins来查看插件是否被firefox正确识别,也可以通过设置注册表的方式来安装该插件,可以创建HKEY_LOCAL_MACHINE\Software\\MozillaPlugins\\@xxx.cn/xxxx,添加Path字符串项保存插件路径。浏览器会自动加载。
3.MimeType
Mimetype,媒体资源类型,一般用于设定某种扩展名的文件用一种应用程序打开的方式。在编写Netscape插件时,在资源文件中设置该插件的MimeType属性值。如:
- BEGIN
- BLOCK "040904e4"
- BEGIN
- VALUE "CompanyName", "?????"
- VALUE "FileDescription", "TODO: <File description>"
- VALUE "FileVersion", "1.0.0.1"
- VALUE "InternalName", "npplugins.dll"
- VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
- VALUE "OriginalFilename", "npplugins.dll"
- VALUE "ProductName", "????"
- VALUE "ProductVersion", "1.0.0.1"
- VALUE "MIMEType", "application/test-plugins"
- END
- END
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "?????"
VALUE "FileDescription", "TODO: <File description>"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "npplugins.dll"
VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
VALUE "OriginalFilename", "npplugins.dll"
VALUE "ProductName", "????"
VALUE "ProductVersion", "1.0.0.1"
VALUE "MIMEType", "application/test-plugins"
END
END
当浏览器启动后,会在默认的plugins文件夹中加载插件,并读取插件的MimeType属性,并保存到浏览器内部。输入about:plugins即可以获取所有当前识别出的插件已经MimeType属性。当浏览器加载页面遇到<Embed ID = 'plugins1' type='application/test-plugins'/>这样的文件内容时,即知道应该调用MimeType属性值为type的插件来打开该文件。就会在浏览器中查找到该插件,并进行加载和初始化。如果不存在该属性的插件,则因为找不到指定类型的插件而无法打开该媒体文件。
微软的IE浏览器下的ActiveX控件遵循了COM标准,所以使用Object标签的CLSID来标识应该调用那个插件来读取该文件,不需要为插件设定MIME 的编码。
4.Netscape插件的生命周期
1.打开firefox浏览器。Firefox主动读取安装目录下的plugins文件夹,读取该文件夹下的插件的信息,比如mimetype,并保存起来,输入about:plugins可以查看
2.载入相关页面。当遇到标签为<Embed ID = 'plugins1' type='application/test-plugins'/>这样的文件内容时,浏览器主动查找加载mimetype相匹配的插件。加载的过程也是初始化调用接口的过程。初始化完毕后,浏览器会调用插件相关接口创建一个插件实例,与该页面相关联。
3..载入另一个新的页面。如果已经有页面载入,则此后的所有重新打开的web页面都将跳过插件初始化这一步骤,不过要创建新的插件实例与新的页面相对应。
4..关闭一个页面。销毁与该页面关联的插件实例,如果是最后一个页面,则执行反初始化插件操作。
5. NPAPI标准的接口说明
NPAPI标准定义在一组包含了数据结构和接口函数的头文件中。在实际的开发中,需要将这些头文件加入到工程中,并对头文件定义的部分接口编写实现。用到的主要四个头文件有npapi.h,npfunction.h,npruntime.h,nptype.h,这四个头文件可以在firefox的源码例子插件中找到,同时还提供了一组C++编写的框架用来更方便的开发Netscape插件。
简单介绍一下三类接口函数
1..前缀NP_是npapi的插件库提供给浏览器的最上层的接口,一般为动态链接库的导出接口,主要有NP_GetEntryPoints、NP_Initialize、NP_GetMIMEDescription、 NP_GetValue、NP_Shutdown的等几个函数,不同平台的接口可能略有不同,但基本功能都是一样的,都是通过接口来初始化、销毁以及认知此动态库.
- LIBRARY "npplugins"
- EXPORTS
- ; Explicit exports can go here
- NP_GetEntryPoints @1
- NP_Initialize @2
- NP_Shutdown @3
LIBRARY "npplugins" EXPORTS
; Explicit exports can go here
NP_GetEntryPoints @1
NP_Initialize @2
NP_Shutdown @3
2. 前缀NPP_即NP Plugin是插件本身提供给浏览器调用的接口,主要被用来填充NPPluginFuncs的结构体,主要包括:NPP_New、NPP_Destroy、NPP_SetWindow、NPP_GetMIMEDescription 、NPP_NewStream、NPP_DestroyStream、NPP_StreamAsFile、NPP_WriteReady、NPP_Write、NPP_Print、NPP_HandleEvent、NPP_URLNotify、NPP_GetValue、NPP_SetValue等,详细介绍
NPP_Destroy 删除插件的一个运行实例(instance) NPP_DestroyStream 告知插件将要删除一个流数据 NPP_GetValue 供浏览器查询插件的内部信息 NP_GetValue 供浏览器查询插件的内部信息 NPP_HandleEvent 注册关心的事件,当事件发生时浏览会通知插件 NP_Initialize 只调用一次,在插件加载时调用 NPP_New 创建插件的一个实例 NPP_NewStream 通知插件实例出现了新的流数据 NPP_Print 请求嵌入式打印还是全屏打印 NPP_SetValue 插件添加变量信息 NPP_SetWindow 当窗口创建、移动、改变大小或者销毁时通知插件 NP_Shutdown 销毁插件,与NP_Initialize对应 NPP_StreamAsFile 为数据流提供一个本地文件名 NPP_URLNotify 插件要求通知后,当对于某个URL的请求完成后,浏览器通知插件 NPP_Write 插件读取流数据 NPP_WriteReady 调用NPP_Write之前调用,确实插件可以接收多少字节的数据
3.前缀NPN_XXX类接口一般为浏览器引擎提供给plugin调用的接口主要包括NPN_GetURL、NPN_PostURL、NPN_GetValue、NPN_SetValue、NPN_Status等
当浏览器开始加载插件时,首先调用NP_GetEntryPoint函数用于获取NPP_类函数的地址,为后续调用做初始化工作。接着调用NP_Initialize函数,将浏览器提供的NPN_函数地址通知插件。以上两个动态库导出接口完成了插件后续调用和被调用的初始化工作。当所有插件相关页面退出时,浏览器调用NP_Shutdown来完成反初始化。
接下来当firefox加载页面时,浏览器调用插件的NPP_New函数来创建一个插件实例。当页面退出时,浏览器调用NPP_Destroy来销毁插件实例。注意,只有在第一次加载页面时才会初始化调用插件,后续打开的页面不再重新初始化,因为在第一次初始化时浏览器已经获取了函数接口信息,后续的页面只需要调用NPP_New创建新的插件实例与页面对应即可。同理,只有当最后一个页面退出时,才调用插件的反初始化,即NP_Shutdown函数。这时,浏览器会清除该插件的对象实例,释放资源。
6.NPAPI的主要数据结构
1. 结构NPPluginFuncs:包含了NPP_函数地址的结构体。浏览器中定义一个这样的结构体对象,通过NP_GetEntryPoint函数对该结构体对象赋值,将NPP_函数地址通知浏览器,供浏览器后续调用
2. 结构NPNetscapeFuncs:包含了浏览器中定义的NPN_函数的结构体。插件中定义一个这样的结构体指针,浏览器通过NP_Initialize函数赋值给这个结构体指针,为后续插件调用浏览器中的这些接口服务。
3. 结构NPObject:包含NPClass *_class和uint32_t referenceCount. 插件实例对象
4. 结构NPClass: 包含了访问插件的一组方法。包含在NPObject对象中。主要包含的函数有pluginHasMethod :询问插件是否支持某一js方法。pluginHasProperty :询问插件是否具有某一属性 pluginInvoke :当插件支持该方法时,浏览器调用给方法传递参数和获取返回值。
5. 结构NPVariant:带类型定义的数据信息结构
定义为
typedef struct _NPVariant {
NPVariantType type;
union {
bool boolValue;
int32_t intValue;
double doubleValue;
NPString stringValue;
NPObject *objectValue;
} value;
} NPVariant;
对该结构体的访问可以通过以下的标准宏进行:
NPVARIANT_IS_STRING或者NPVARIANT_TO_BOOLEAN,NPVARIANT_TO_INT32,NPVARIANT_TO_DOUBLE,NPVARIANT_TO_STRING,NPVARIANT_TO_OBJECT等。
NPAPI接口同时提供了一些将其他类型转换为NPVariant结构的宏。如INT32_TO_NPVARIANT,STRINGZ_TO_NPVARIANT,OBJECT_TO_NPVARIANT等,可以很方便的进行数据转换。
7.插件与JS的交互
NPAPI标准提供了一套插件与JS的交互机制。
1. javascript调用插件方法: 浏览器首先会调用NPP_GetValue(NPP instance, NPPVariable variable, void* value)取得NPObject对象的地址。Variable参数为NPPVpluginScriptableNPObject。在取得该对象后浏览器就可以调用插件提供的NPClass函数。最主要的函数有下面几个: pluginHasMethod :询问插件是否支持某一js方法。 pluginHasProperty :询问插件是否具有某一属性 pluginInvoke : 当插件支持某一方法时,浏览器将会调用该函数执行插件为js提供的这一方法。那么对于提供的很多方法插件如何在该函数内区分。分析这个函数: pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result); obj是插件里的NPObject对象地址。 Name表示插件提供方法的名字,通过对比这个参数来区分插件提供的不同方法。 args和argcount分别表示js传来的参数地址和参数个数。 result是函数返回给js的结果。
2. 插件调用js内部的回调函数: Js可以通过2种方式为插件设置回调函数。示例如下: <script language=javascript> Plugin.Onfun = fun;//方式一 通过设置插件属性传入回调函数地址 Plugin.Onfun(fun);//方式二 通过调用插件函数传入回调函数地址 Function fun(){} < /script>
在插件内部,当js函数地址传到插件时,浏览器把它封装为一个NPObject对象,里面存有函数地址 方式一: 在插件内部,浏览器会调用pluginHasproperty确认插件是否有该属性。如果有然后浏览器调用pluginSetproperty函数。pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant)的第二个参数判断是哪个属性,第三个参数就是NPObject对象地址。 方式二:在插件内部,浏览器会调用pluginHasmethod确定是否支持该方法。然后调用pluginInvoke,这里面的args参数包含了回调函数NPObject地址。 js设置完回调函数后,插件就可以调用该函数了。需要使用NPN_InvokeDefault,示例代码如下: bool bret = gBrowser->invokeDefault(npp, callbackNPObject, &pV, 1, &result);
另外,插件也可以直接调用js中的函数。在插件内部调用浏览器的getUrl函数。具体格式如下: gBrowser->geturl(inst(), “javascript:function()”, "_self"); 如果想传入整数参数,上面函数第二个参数应写成: “javascript:function(“+num+”)”。 如果传入字符串参数,上面函数第二个参数为: “javascript:function(/’“+”string”+”/’)”。如果字符串含有中文,需要进行url encode。
8.开发Netscape插件的一般方法
尽管开发netscape插件有不少可用框架。但是开发一个典型的netscape插件主要要做的工作有以下:
1.编写一个动态链接库。 插件的表现形式就是一个动态链接库,所以首先编写一个dll文件或者.so文件供浏览器调用。注意,插件的名称应该以np开头,NPAPI标准的默认规则。
2.添加dll导出接口。 在xx.def文件中添加dll的导出函数,如图
上面导出了三个NP_函数,供浏览器调用。这三个函数的作用前面已经说过,不再细述
3.添加插件的mimetype。首先为插件添加一个.rc文件,注意该资源文件的默认语言应该是英文,简体中文的话浏览器识别不出,然后在.rc文件中添加mimetype属性。
如图
4.实现npapi.h中声明的NPP函数。
5.在Np_GetEntryPoints中将NPP_函数地址赋值给传出参数。
6..在NP_Initialize中保存传入的NPNetscapeFuncs对象指针,供插件后续调用
7.在Np_Shutdown中处理反初始化操作。
8.对NPClass中的函数进行实现
在NPAPI开发火狐浏览器插件在NPAPI插件的更多相关文章
- 火狐浏览器安装 Modify Headers 插件
一.火狐浏览器插件安装 这里以火狐浏览器的Modify Headers插件安装为例,展示火狐插件的安装: 1.打开火狐浏览器,右上角选择“附加组件” 2.搜索Modify Headers插件 3.安装 ...
- 用FireFox火狐浏览器的3D Tilt 插件查看网页3D视图效果
逛博客发现了网页的3D视图效果,一搜原来是Firefox特有的一个功能,先看效果: 相当炫酷,接下来介绍如何实现. 1.首先安装3d tilt 插件: 从火狐浏览器的添加插件页面,搜索:3D Tilt ...
- 火狐浏览器Firefox上DownThemAll插件
DownThemAll插件支持断点续传.多线程下载,可以大幅度提高下载速度. 在Windows平台上,要下载大量的文件,迅雷自然是首选:但在非Windows平台上,只要安装一个火狐浏览器,再安装Dow ...
- HiJson工具 && 火狐浏览器中的jsonHandle插件(以及乱码问题的解决)-->来转换json串的格式
原文:http://blog.csdn.net/cjm2484836553/article/details/72453907 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] ...
- linux下火狐浏览器安装flash player插件
1 去官方网站下载flash player 安装包.后缀名为.tar.gz,假设名称为flash.tar.gz 默认在桌面 2 下载后解压缩,使用以下命令 #tar -zxvf /root/Deskt ...
- 火狐浏览器Firefox如何使用插件,火狐有哪些好用的插件
1 CoorPreviews 不打开网页链接预览该网页的内容. 预览如图所示: 点击关闭旁边的钉子可以让该窗口保持开着并且浏览速度加快.这对于快速浏览图片时非常有用. 2 FoxTab 3D方式预览网 ...
- Linux 火狐浏览器安装Flash插入
Linux系统安装完毕,找到Firefox浏览器和视频播放器不能总是提示安装Flash.而据火狐浏览器的提示Flash插件安装总是失败,能手动安装Flash插件啦. 到Flash官网:http://g ...
- php开发工具之火狐浏览器插件
相信做开发的都有一种火狐情怀吧! 下面来介绍下一些自己在php开发工程中用到几个火狐浏览器插件. 1.[firebug]: 这个插件可以说是一个神奇,功能不用过对介绍. 2.[hostAdmin]: ...
- 【转发】NPAPI开发详解,Windows版
NPAPI开发详解,Windows版 9 jiaofeng601, +479 9人支持,来自Meteor.猪爪.hanyuxinting更多 .是非黑白 .Yuan Xulei.hyolin.Andy ...
随机推荐
- RequireJS入门与进阶
RequireJS由James Burke创建,他也是AMD规范的创始人. RequireJS会让你以不同于往常的方式去写JavaScript.你将不再使用script标签在HTML中引入JS文件,以 ...
- SIM900A访问HTTP的简单方法
最近做项目,使用Arduino控制设备,读取数据,然后通过移动网络传送到服务器. 我选用的是正点原子的SIM900A模块.在服务器部署了一个监听程序,Arduino控制SIM900A通过TCP方式把数 ...
- fedora -- java多版本切换
一般java开发时会下载多个版本的SDK,所以需要多个版本中进行切换 1. 设置JAVA_HOME环境变量需要打开.bashrc文件 2. 安装时使用alternatives将不同版本的java连接到 ...
- SVM整理
SVM整理 Last modified: 2015.9.2 1.算法总结 支持向量机是Cortes和Vapnik于1995年首先提出的,它在解决小样本,非线性及高维模式识别中表现出许多特有的优势,并能 ...
- how to get sharepoint lookup value
SPFieldLookup lookUp1 = properties.ListItem.ParentList.Fields.GetField("Leave_x0020_Type") ...
- (转)Linux 文件系统:procfs, sysfs, debugfs 用法简介
网址:http://www.tinylab.org/show-the-usage-of-procfs-sysfs-debugfs/ 1 前言 内核中有三个常用的伪文件系统:procfs,debugfs ...
- 人生规划和GTD——“知”、“得”与“合”
写在前面:非常不错的一篇GTD入门以及人生目标与规划的文章,值得收藏. 本文来自 零折 作为<小强升职记>的读书感悟,给我自己.作为分享,也送给或许需要的给你. 我不知道你是否真的需要.但 ...
- poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)
http://poj.org/problem?id=2449 Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Subm ...
- 第二天就跳票 将wikipedia上的英文词条翻译为中文 手动
忙着改简历一整天,刚说完一天一博,就要跳票了. 还是写点东西吧. 今天又翻译了一个维基百科上的条目,刚过一天就忘了怎么弄,还得回头翻帖子.在这先记一下,省的以后找不到. 1.注册个wiki账号,轻松过 ...
- springMVC+MyBatis+Spring 整合(2)
mybatis 与Spring 的整合. 1.导入Spring 和Springmvc的包 pom <project xmlns="http://maven.apache.org/POM ...