NPAPI外掛開發學習:Webkit的外掛機制
轉載CSDN博友的一篇關於NPAPI外掛機制的博文。
# 外掛機制(NPAPI plugin)
## 概述
Chromium中的NPAPI外掛(plugin)來源於mozilla的外掛機制。因為它被廣泛的應用,很多外掛廠商或者開發者基於它編寫了數以萬計的外掛,因而chromium對它也提供了支援,不過chromium有自己獨特的外掛架構,後面我們會詳細介紹。
NPAPI提供兩組介面,一類以NPP打頭,由外掛來實現,被瀏覽器呼叫,主要包括一些外掛建立,初始化,關閉,銷燬,資訊查詢及事件處理,資料流,視窗設定,URL等;另一類以NPN打頭,由瀏覽器來實現,被外掛所呼叫,主要包括圖形繪製,資料流處理,瀏覽器資訊查詢,記憶體分配和釋放,瀏覽器的外掛設定,URL等。
原始的NPAPI的介面使用起來不是很方便,因而有貢獻者對其進行了封裝以利於其使用。一個比較著名的開源專案是Firebreath。它將原始的C風格的NPAPI進行封裝成C++風格的介面,非常方便使用者使用,而且有針對Windows和X window的移植,使用者無需對底層特別瞭解。特別的是,Firebreath也有對ActiveX的封裝,因而對於現在主流的兩種外掛介面,你都可以基於Firebreath的介面進行程式設計,極大地方便了開發者。詳情請參考Firebreath主頁http://www.firebreath.org/display/documentation/FireBreath+Home
## 架構
因為chromium的安全模型,renderer程序沒有訪問除I/O讀寫等之外的許可權,因而外掛需要有自己的程序,這就是外掛的out-of-process模型。下圖給出chromium中外掛的架構和程序模型。
每一種型別的plugin只有一個程序,這就是說,如果有兩個或者多個renderer程序同時使用同一個外掛,那麼該外掛會共享同一個程序。因為多個renderer程序共享同一種的plugin程序,那麼plugin程序如何為它們服務呢?答案是為每個外掛使用點在plugin程序中建立一個外掛例項(PluginInstance).
值得注意的是,plugin程序是由browser程序來負責建立和銷燬, 而不是renderer程序。 原因在於renderer程序沒有建立的許可權,而且plugin程序由browser程序來統一管理也更方便。 當plugin程序建立成功時,browser程序會返回IPCchannel handle用於建立和plugin程序通訊的PluginChannelHost. 那它什麼時候被銷燬呢?當沒有任何外掛例項並且空閒一段事件後,它才會被銷燬,這樣做的好處是避免頻繁的建立和銷燬plugin程序。
下圖描述了browser和plugin程序間的通訊機制及其所涉及的相關的模組(類)。Browser程序通過PluginProcessHost傳送訊息呼叫Plugin程序的函式,響應動作由PluginThread完成。而Plugin程序則是通過WebPluginProxy傳送訊息呼叫browser的函式,響應動作有PluginProcessHost完成。
Browser和Plugin僅有較少的訊息傳遞,用於建立等管理工作。主要的部分在renderer程序和plugin程序之間,機制也相對更復雜一些。HTMLPluginElement會包含一個WebPluginContainerImpl,而它包含一個WebPluginImpl,對plugin的呼叫有WebPluginDelegateProxy負責中轉。在Plugin程序中,由WebPluginDelegateStub處理所有renderer過來的請求,並由WebPluginDelegateImpl呼叫建立好的PluginInstance物件。PluginInstance最終呼叫PluginLib讀取的外掛的函式入口地址,最終完成對外掛實現的呼叫。而對外掛實現中對NPN開頭函式的呼叫,則是通過PluginHost來完成。
PluginHost主要負責實現NPN開頭的函式,如前面所描述,這些函式被plugin程序所呼叫。可以在plugin和renderer程序被呼叫。當在plugin程序呼叫這些函式時,chromium會覆蓋PluginHost的部分函式,而這些新的callback函式會呼叫NPObjectProxy來通過IPC傳送請求到renderer程序。
PluginInstance實現了NPP開頭的函式,被render所呼叫(webpluginImpl通過webplugindelegateImpl來呼叫),PluginInstance通過PluginLib獲得了外掛庫的函式地址,從而把實際的呼叫橋接到具體的外掛中。
具體的見下圖所示,主要結構來源於chromium的官網,略有修改。
對於NPObject相關的函式呼叫, 有專門的類來處理。NPObject的呼叫或者訪問是雙向的(renderer程序<->plugin程序),他們的具體實現是通過NPObjectProxy和NPObjectStub來完成。 NPObjectProxy接受來自對方的訪問請求,轉發給NPObjectStub,最後NPObjectStub呼叫真正的NPObject並返回結果。見下圖所示。
下面示例給出一個外掛如何被renderer程序觸發建立的過程。
當頁面中包含一個“embed”或者“object”元素,renderer程序會建立一個HTMLEmbedElement元素,當該元素被訪問是,會觸發建立相應的外掛。HTMLEmbedElement會請求建立自己對應的RenderWidget(WebPluginContainerImpl),進而建立WebPluginImpl和WebPluginDelegateProxy。WebPluginDelegateProxy會發送訊息來建立Plugin程序。Plugin程序被browser程序建立後,會響應renderer的請求來建立PluginInstance並初始化它。這樣它們之間的聯絡就建立好了。
## Window和windowless外掛
可以通過設定”embed”或者”object”元素的屬性。兩者的區別主要在於繪圖的方式不同。Window外掛由renderer程序提供一個視窗(window), 外掛直接在該視窗上進行繪製;而windowless外掛則不同,外掛將繪製的結構(Pixmap),通過共享記憶體方式(Transport DIB)傳遞給renderer程序,renderer繪製該內容到自己內部的儲存結構(backing store)上。好處是,可以把外掛繪製的結構和網頁上的其他內容做各種形式的合成。但是,從上面不能看出,一般來講,window模式的效能是要高於windowless的。
## 相關目錄和檔案
third_party/WebKit/Source/WebKit/chromium/public/webplugin.h:
定義Webkit::WebPlugin介面,用於建立和銷燬外掛,及傳送事件給外掛
content/common/plugin_messages.h:
定義plugin程序與renderer程序和browser程序間的訊息結構體,包括五類:
PluginProcessMsg開頭的訊息- browser程序發給plugin程序
PluginProcessHostMsg開頭的訊息- plugin程序發給browser程序
PluginMsg開頭的訊息- renderer程序發給plugin程序
PluginHostMsg開頭的訊息- plugin程序發給renderer程序
NPObjectMsg開頭的訊息- plugin程序與render程序相互編碼和解碼NPObject
content/common/npobject_stub.(h&cc):
類NPObjectStub的定義和實現
content/common/npobject_Proxy.(h&cc):
類NPObjectProxy的定義和實現
content/plugin:
該目錄用於存放Plugin程序使用的IPC和WebPlugin相關的函式和類
content/plugin/webplugin_proxy.(h&cc):
實現WebKit::npapi::WebPlugin介面,把外掛的呼叫通過IPC傳送給renderer程序
content/plugin/webplugin_delegate_stub.(h&cc):
把WebPluginDelegateProxy的訊息轉換為對WebPluginDelegateImpl的呼叫
content/plugin/plugin_channel.(h&cc):
定義Plugin程序與renderer程序通訊的通道
webkit/plugins/npapi/:
該目錄用於存放Plugin程序使用的對WebKit介面實現和外掛庫處理的相關的函式和類
webkit/plugins/npapi/webplugin.h:
定義WebPlugin介面,用於plugin端同web frame和webcore物件的互動
webkit/plugins/npapi/webplugin_impl.(h&cc):
實現WebKit::WebPlugin和WebPlugin介面,通過WebPluginPageDelegate來建立WebPluginDelegate
webkit/plugins/npapi/plugin_instance.(h&cc)
PluginInstance類的介面和實現,代表一個Plugin例項,對應於renderer程序的一個請求建立的plugin例項
webkit/plugins/npapi/webplugin_delegate.h:
定義WebPlugin代理,用來分離具體的外掛的實現方式,例如可以使來實現程序內或者跨程序的外掛架構,對WebPlugin來說,具體架構是透明的
webkit/plugins/npapi/webplugin_delegate_impl.(h&cc):
響應renderer程序實現對PluginInstance的呼叫請求,有gtk,win和aura三種不同的實現
webkit/plugins/npapi/plugin_host.(h&cc):
實現NPN開頭的函式,在plugin程序和renderer程序有不同的實現
webkit/plugins/npapi/plugin_lib.(h&cc):
PluginLib用來管理實際外掛庫的生命週期
content/renderer/webplugin_delegate_proxy.(h&cc)
定義和實現WebPluginDelegateProxy類,橋接所有來自於WebPlugin的請求到WebPluginDelegateImpl
content/browser/plugin_process_host.(h&cc):
類PluginProcessHost的定義和實現,用於Browser程序與plugin程序的互動
content/browser/plugin_service_impl.(h&cc):
類PluginServiceImpl的定義和實現,用於響應Renderer程序建立外掛請求及其他一些外掛管理工作
## 參考文件:
相關推薦
NPAPI外掛開發學習:Webkit的外掛機制
轉載CSDN博友的一篇關於NPAPI外掛機制的博文。 # 外掛機制(NPAPI plugin) ## 概述 Chromium中的NPAPI外掛(plugin)來源於mozilla的外掛機制。因為它被廣泛的應用,很多外掛廠商或者開發者基於它編寫了數以萬計的外掛,因而
NPAPI外掛開發學習:實現非IE瀏覽器的類似ActiveX的本地程式(外掛)呼叫
轉載CSDN博友的一篇文章,方便以後學習。 一.Netscape Plugin Interface(NPAPI) 大致的說明可以看下官方文件Plugin 本文主要針對於javascript與外掛互動部分做一些交流,比如用於數字證書的操作(淘寶和支
ArcMap外掛開發初識:Add In
之前一直在做ArcEngine的相關開發,做的winform相關,新換了工作,又開始新的學習旅程! Add In 這個東西很早就知道有,但是一直沒有用過,因為之前的公司有自己框架,介面,雖然我也是做外掛開發,但是都是基於原公司的平臺。新公司的同事希望能幫忙做個小工具,用C#+winform介面,做了個小型的
Chrome外掛開發入門:如何實現一鍵上班賴皮
很多人介紹過Chrome外掛,但必須要說,外掛開發就是擺弄一個小玩具,第一要素是實用,其次是好玩。 單純羅列各種功能是非常無趣的。 所以把一篇舊文拿出來與大家分享。 人,活著就是為了賴皮。 作為一個合格的開發人員,把30%的時間用來賴皮(上班偷懶)是值得推薦的。 因為,如果你工作時間無法賴皮,
前端開發神器:Emmet外掛
今天在逛CSDN時,發現了一個前端神器,IDEA內建了這個外掛。所有操作按下“Tab”鍵完成 生成HTML基本結構 !或html:5或html:4s,按下Tab鍵 巢狀操作 使用“>”生成子元素 使用“+”生成兄弟元素 使用“^”生成父元素 使用“”生成
Eclips外掛開發學習資源
最近斷斷續續的在研究Eclipse平臺的外掛開發,感覺這方面的資源比較少,所以整理在這裡,和大家分享 書籍: Eclipse Plug-ins (3rd Edition) (中文書名
使用Cordova進行iOS開發 (第三方外掛的使用:Camera外掛)
var pictureSource; var destinationType; document.addEventListener("deviceready",onDeviceReady,false); func
jQuery外掛開發學習
1、jQuery外掛編寫準備 要使用jQuery進行自定義外掛的編寫,首先應該的是瞭解jQuery的外掛機制或者說是通過jQuery庫本身提供的哪些函式進行外掛的編寫,主要涉及的兩個函式是:jQuery.extend(object)和jQuery.fn.extend(o
jquery外掛開發學習筆記(五)——動態選擇觸發器
(function ($) { //var trigger_chosen; // if($("#test002").attr("checked")){ // trigger_chosen=$("#test002").val(); //
CloudIDE外掛開發實戰:教你如何除錯程式碼
摘要:今天我們來重點介紹下CloudIDE外掛的除錯技巧,在外掛開發過程中除錯作為重要的問題分析和定位手段能夠有效幫助開發者提升外掛質量。 今天文章中的樣例工程我們繼續以上一篇《實戰CloudIDE外掛開發-快速上手》中的專案為基礎,深入介紹外掛的除錯方法。可能有的開發者對於外掛的前後端相關概念會有所疑惑,大
java反射機制學習:初始反射機制
pro sta 加載 初始 完整 tac demo 獲得 sys 本人小白一枚,想和大家一起分享我學習java的筆記和心得。 反射機制: 指的是可以於運行時加載、探知、使用編譯期間完全未知的類。 程序在運行狀態中,可以動態加載一個只有名稱的類,對於任意一個已加載的
java開發學習:陣列總結
要論Java開發學習哪一部分重要?我一定斬釘截鐵的回答你:一定不是框架,其中Java基礎相對框架來講要重要一百倍。因為每個公司用的框架總有差異,但萬變不離其宗,都是基礎知識搭建起來的,所以我們想要學好Java,就一定要打好基礎。 今天小編給大家分享的Java基礎知識之一——陣列! 用來儲存
微信開發學習:輸入城市+天氣接收天氣預報,非非非非常好玩
這次實踐一下這篇 http://www.jb51.net/article/51923.htm 輸入城市+天氣四個字,接收天氣預報,資料來源是百度天氣預報介面。原來的程式碼功能多,比較複雜,我精簡了一下,相對容易看懂。 完成後的效果: wx_token
【eclipse外掛開發實戰】 Eclipse外掛開發6——eclipse線上翻譯外掛Translator開發例項詳解
Eclipse外掛開發6——eclipse線上翻譯外掛Translator開發例項詳解 在上一篇文章中講到了一個簡單的eclipse外掛開發例項,主要是對外掛工程的基本建立步驟進行了講解,這篇文章當中給出一個翻譯小外掛的例項,呼叫有道翻譯API實現實時取
NPAPI外掛開發詳細記錄:用VS2010開發NPAPI外掛步驟
前面一段時間關注了用firebreath開發外掛,但是感覺用起來不是那麼得心應手,還是回到NPAPI開發外掛上來。 本文根據NPAPI開發詳解,Windows版進行開發,其中以VS2008為例進行開發,在VS2010中基本上是相同的。 必須的plugin sdk,將其解壓到
NPAPI外掛開發詳細記要:外掛執行流程分析
NPAPI外掛開發詳細記錄:外掛執行流程分析本文詳細分析外掛的程式碼是如何執行的,主要分析np_entry.cpp、npn_gate.cpp和npp_gate.cpp.希望能夠有所收穫。 在windows平臺下,外掛就是一個dll,注意到這個dll的def檔案內容是:LIB
VSCODE外掛開發:使用者輸入輸出
閱讀這篇文章之前,假設你已經具有開發helloworld的外掛的能力。 vscode.window 簡介 vscode.window 負責當前啟用視窗的輸入輸出,比如展示資訊,和使用者輸入等功能都是用vscode.window實現 程式碼輸出提示資訊 簡單的輸出提示資訊 使用vscode.windo
Eclipse二次開發:Eclipse 外掛開發法則
擴充套件者 貢獻法則( Contribution Rule ):一切皆是貢獻。 遵循法則( Conformance Rule):外掛必須遵循預期的介面。 &nbs
使用 PySide2 開發 Maya 外掛系列三:qt語言國際化(internationalization)
使用 PySide2 開發 Maya 外掛系列三:qt語言國際化(internationalization) 前言: 這是 qt for python 的語言國際化,基於 UI 的,python 也有自身的語言國際化,兩者是不同的。 先來看最終效果: 前期準備: 這次建立一個 main wind
使用 PySide2 開發 Maya 外掛系列一:QT Designer 設計GUI, pyside-uic 把 .ui 檔案轉為 .py 檔案 Maya Max python PySide整合 shiboken版本對應關係
使用 PySide2 開發 Maya 外掛系列一:QT Designer 設計GUI, pyside-uic 把 .ui 檔案轉為 .py 檔案 前期準備: 安裝 python:https://www.python.org/downloads/ 安裝 PySide2:安裝 python 後,在安裝目錄下