其實,就在幾天前,我根本不知道什么是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 (mimetype) { // Yes, so can we display with a plug-in? var plugin = mimetype.enabledPlugin; if (plugin) { // Yes, so show the data in-line document.writeln("Here\'s a movie: <object data='mymovie.swf' height='100' width='100'></object>"); } else { // No, so provide a link to the data document.writeln("<a href='mymovie.swf'>Click here</a> to see a movie."); } } else { // 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