NPAPI开发常识
其实,就在几天前,我根本不知道什么是NPAPI插件。因为最近的项目中用到需要在非IE下检测客户端是否安装,最终找到浏览器插件NPAPI。
以下资料来源于网络收集,以此给那些和我一样迷茫的人。本文的目的不是将网络上资源拼凑出来,而是在于寻找资料的途径及好资料链接。并希望大家以后,无论在找什么资料都可以找到最核心最有用的。
NPAPI是什么
所谓NPAPI,就是指网景插件应用程序接口(Netscape Plugin Application Programming Interface)[1][2],是一种外部程序作为插件和浏览器共同完成网页展示的调用通道
为什么使用NPAPI插件?插件就相当于运行在网页上的应用程序。比如你想在网页上播放音乐,在网页上使用<embed>标签,浏览器会自动调用Windows Media Player运行,又如pdf等。还有,也可以用作在浏览器检测和启动客户端应用程序。
我们通常称为"火狐插件",真实意思是基于火狐内核的插件,火狐是Gecko引擎,因此基于Gecko引擎的插件开发类似,以下将火狐浏览器称作Gecko。火狐插件NPAPI,在页面上<embed>标签,对应于IE的ActiveX插件,页面上用<object>标签。
NPAPI 原本是由 Netscape 所制定的一组单纯的 C Plugin API,起初是无法支持 Scriptability;于是到了 2004 年底,各家 Browser ( IE , Opera, Mozilla 等) 都同意支持NPRuntime 延伸 API 以支持 Scriptability,所以目前若是想写 Plugin则应该以 NPRuntime API 才能跨不同的 Browsers
尽管这种插件在当时很流行,但自从HTML5出来后似乎就被排挤了。谷歌将会从2014年1月开始禁用大部分的Chrome插件。Mozilla也计划在2013年12月阻挡NPAPI插件的使用.
Netscape插件的生命周期
当用户用Gecko引擎的浏览器打开一个包括embed标签的网页时,浏览器会响应以下行为:
- 检测带有MIME type的插件
- 加载插件代码到内存中
- 初始化插件
- 创建插件的实例
Gecko引擎可以加载同一插件的多个实例在一个网页上,或者同时在几个打开的窗口。当用户离开或关闭窗口,插件实例被删除。当最后一个实例被删除,插件代码从内存中卸载。
所以在火狐中需要标注插件的mime类型,而在IE下,因为在系统中以COM方式注册,所以只需要classid。差异如下如下:
浏览器 |
用法 |
|
IE(Trident引擎) |
<object classid="clsid:7017318C-BC50-4DAF-9E4A-10AC8364C315" > </object> |
|
Firefox,chrome (Gecko引擎) |
<embed id=iStylePDF type=application/npistyleax /> |
请注意区分,浏览器插件和浏览器扩展是不同的。浏览器插件是利用给出的api嵌入的一种插件,而扩展则是基于浏览器实现的扩展功能。
如果只是想检测用的话,一个简单的demo足够,但是如果你还想偷懒,连一个简单的demo也不想做,只是向注册表注册mime类型,并用别人的dll,这是不允许的。
插件检测
Gecko引擎以特定的顺序查找不同地方的插件(Plug-ins).
Gecko如果发现NPAPI插件
当一个基于Gecko引擎的浏览器启动时,它会检测某些路径以查找插件,按以下顺序:
Windows:
直接由环境变量MOZ_PLUGIN_PATH指定的路径
%APPDATA%\Mozilla\plugins,此处" %APPDATA%"指每个用户应用程序数据目录
在工具包内的插件
Profile directory\plugins,
由HKEY_CURRENT_USER\Software\MozillaPlugins\*\Path 注册表值指定,其中*可以是任何名字,通常这里是插件的名称。
由HKEY_
LOCAL_MACHINE\Software\MozillaPlugins\*\Path 注册表值指定,其中*可以是任何名字,通常这里是插件的名称。
Mac OS X
~/Library/Internet Plug-Ins.
/Library/Internet Plug-Ins.
/System/Library/Frameworks/JavaVM.framework/Versions/Current/Resources.
在工具包内的插件
Profile directory/plugins, where Profile directory is a user profile directory
Linux
由MOZ_PLUGIN_PATH 环境变量指定路径.
~/.mozilla/plugins.
/usr/lib/mozilla/plugins (on 64-bit systems, /usr/lib64/mozilla/plugins is used instead).
在工具包内的插件.
Profile directory/plugins, where Profile directory is a user profile directory.
为了找出当前注册了哪些插件,可以在Firefox中输入"about:plugins".Gecko引擎会显示一个页面列出所有注册的插件和它们所用的MIME类型,还有插件提供的可选的描述信息。
在windows,注册的插件是自动配置处理它们支持的MIME类型。如果多个插件处理相同的MIME类型,则由第一个注册的插件处理。
通过MIME类型检测插件
启用的插件的属性在JavaScript中可以用来确定一个特定的MIME类型使用哪个插件。尽管插件也许支持多个MIME类型,而且每个MIME类型也许被多个插件支持,但是只有一个插件可以被识别为特定的一个MIME类型。启用插件的属性是插件实例的一个参考
如下例子利用JavaScript来确定Adobe Flash是否注册。如果注册了,则显示一个movie。
// Can we display Adobe Flash movies? var mimetype = navigator.mimeTypes["application/x-shockwave-flash"];
if // Yes, so can we display with a plug-in? var plugin = mimetype.enabledPlugin; if // Yes, so show the data in-line document.writeln("Here\'s a movie: <object data='mymovie.swf' height='100' width='100'></object>"); } // No, so provide a link to the data document.writeln("<a href='mymovie.swf'>Click here</a> to see a movie."); } } // No, so tell them so document.writeln("Sorry, can't show you this movie."); } |
开发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中的函数进行实现
要下班了,就先写到这里吧。各位想看更多资料查看下面链接吧。
更多信息请参考:
首先是MDN火狐开发者中心官网的资料最可靠。
火狐插件基础:
MDN扩展开发:
https://developer.mozilla.org/en-US/Add-ons
其它参考:
http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/
http://www-archive.mozilla.org/owners.html
NPAPI开发常识的更多相关文章
- 【转发】NPAPI开发详解,Windows版
NPAPI开发详解,Windows版 9 jiaofeng601, +479 9人支持,来自Meteor.猪爪.hanyuxinting更多 .是非黑白 .Yuan Xulei.hyolin.Andy ...
- Mozilla NPAPI开发示例之一(VS2012 + Win7(64位))
入门级的NPAPI开发. NPAPI & NPRuntime 简介 Netscape Plugin Application Programming Interface (NPAPI) NPAP ...
- 在NPAPI开发火狐浏览器插件在NPAPI插件
1.插件是什么 插件是一种遵循一定规范的应用程序接口编写出来的程序.插件必须依附于一个宿主程序,为宿主程序提供增强功能.插件的种类有很多,这里主要讨论浏览器插件. IE下利用OLE和COM技术开发的浏 ...
- web开发常识
web开发基本常识 服务器(硬件) 维基百科定义: 服务器作为硬件来说,通常是指那些具有较高计算能力,能够提供给多个用户使用的计算机.服务器与PC机的不同点很多,例如PC机在一个时刻通常只为一个用户服 ...
- ios开发常识(1)开发语言和参考资料
学iphone开发用的语言是object-c,object-c和c++,java还是有很大区别,如果你坚持学习iphone开发的话可以不学c++,java,直接学习这个语言,先入为主,可能觉得这个语言 ...
- iOS开发——常识swift篇&随机数获取
随机数获取 arc4random()这个全局函数会生成9位数的随机整数 1,下面是使用arc4random函数求一个1~100的随机数(包括1和100) var temp:Int = ...
- iOS开发常识
一.NSString 创建字符串. NSString *astring = @"This is a String!"; 创建空字符串,给予赋值. NSString *astri ...
- NPAPI火狐插件VS2013开发示例
NPAPI火狐插件VS2013开发示例 下面是我根据网上开发示例自己做的一个demo,并提供代码下载. 开发环境 Windows 8.1 x64 Visual studio 2013 准备工作 首先需 ...
- NPAPI插件开发详细记录:用VS2010开发NPAPI插件步骤<转>
原帖地址:https://blog.csdn.net/z6482/article/details/7660748 ------------------------------------------- ...
随机推荐
- FJ省队集训DAY4 T1
直接上题解 #include<cstdio> #include<iostream> #include<cmath> #include<cstring> ...
- poj3164 (朱刘算法 最小树形图)
题目大意:给定n个点坐标,m条有向边,要求最小树形图. 题解:直接上模板,前面打的 vis[v]=i一直把i打成1,一直TLE. #include<iostream> #include&l ...
- TVS和一般的稳压二极管有什么区别
电压及电流的瞬态干扰是造成电子电路及设备损坏的主要原因,常给人们带来无法估量的损失.这些干扰通常来自于电力设备的起停操作.交流电网的不稳定.雷击干扰及静电放电等,瞬态干扰几乎无处不在.无时不有,使人感 ...
- C++中实现回调机制的几种方式(一共三种方法,另加三种)
(1)Callback方式Callback的本质是设置一个函数指针进去,然后在需要需要触发某个事件时调用该方法, 比如Windows的窗口消息处理函数就是这种类型. 比如下面的示例代码,我们在Down ...
- 自定义高级QFileDialog文件过滤器
QFileDialog提供了一个函数---setproxyModel..就是用这个来玩了.就是override filterAcceptsRow的虚函数,里面定制自己的过滤需求.返回bool 下面 ...
- 【转】NPAPI 插件无法在 Chrome 42 版及更高版本上正常运行
原文网址:https://support.google.com/chrome/answer/6213033 NPAPI 插件无法在 Chrome 42 版及更高版本上正常运行 您可以利用插件在浏览器中 ...
- JQuery的父、子、兄弟节点查找,节点的子节点循环
Query.parent(expr) //找父元素 jQuery.parents(expr) //找到所有祖先元素,不限于父元素 jQuery.children( ...
- Makefile学习(三)执行make
9 执行make 一般方法:make. 某些情况:1.可能需要使用make更新一部分过时文件而不是全部 2.需要使用另外的编译器或者重新定义编译选项 3.只需要查看哪些文件被修改,不需要重新编译 所以 ...
- linux core dump学习
1. core dump是什么? core dump又叫核心转储,当操作系统收到特定的signal时, 会生成某个进程的core dump文件.这样程序员可以根据 已经生成的core dump文件来d ...
- [Cycle.js] Fine-grained control over the DOM Source
Currently in our main() function, we get click$ event. function main(sources) { const click$ = sour ...