firefox插件开发和调试
目錄(?)[+]
原文:http://huandu.me/2010/02/11/595/
Firefox插件(plugins)開(kāi)發(fā)實(shí)用指南
Firefox插件可實(shí)現(xiàn)強(qiáng)大功能,但其中麻煩事情不少。寫(xiě)這個(gè)實(shí)用指南首先是為了方便自己記憶,免得以后再次栽倒一些坑里面,如果能幫助其他人,則是更好。這個(gè)指南不是為了手把手教讀者開(kāi)發(fā)插件,而是作為一個(gè)FAQ,解決各種詭異問(wèn)題。
Firefox擁有眾多的擴(kuò)展(Extension),開(kāi)發(fā)擴(kuò)展也非常容易,不過(guò)有一些事情還是無(wú)法用擴(kuò)展解決,需要訪問(wèn)操作系統(tǒng)的底層功能,這就需要寫(xiě)插件(plugins)。例如flash就是一個(gè)插件而不是擴(kuò)展。
Mozilla提供了一系列的教程和文檔,雖然很不詳盡,眾多重要的API語(yǔ)焉不詳,但至少是一個(gè)好的開(kāi)始。
最需要閱讀的是plugins API和使用入門。這是一個(gè)相當(dāng)長(zhǎng)的文檔,如果看完所有的內(nèi)容會(huì)花費(fèi)大量的時(shí)間而且還會(huì)很暈,這里列一些重點(diǎn)供參考。
- plugins基礎(chǔ)概念
- 寫(xiě)第一個(gè)插件(只需要關(guān)注Writing Plug-ins這一節(jié)所談到的內(nèi)容)
- 獲得一份firefox的源碼,比如firefox 3.6。plugins的例子可以在源碼里找到(modules/plugin/sdk/samples),如果出了問(wèn)題還可以自己編譯一個(gè)debug版的firefox來(lái)調(diào)試。
- 了解瀏覽器能提供什么功能
- 制作插件的安裝程序,推薦用擴(kuò)展的方式安裝插件,有無(wú)數(shù)的好處
完成以上這些內(nèi)容以后差不多就已經(jīng)可以實(shí)現(xiàn)自己的插件了,一般而言,參照著例子來(lái)做開(kāi)發(fā)不會(huì)有什么問(wèn)題,只是有不少細(xì)節(jié)需要留意。
Firefox plugins開(kāi)發(fā)的眾多奇怪的約定(假設(shè)plugins已經(jīng)被正確安裝)
有些約定非常奇怪,不要問(wèn)我為什么,天曉得開(kāi)發(fā)firefox的牛人們?cè)趺聪氲摹?/p>
在Windows下,plugins必須滿足以下條件才能被firefox檢測(cè)到:
- 插件的名字必須是np*.dll,也就是必須以np開(kāi)頭,.dll結(jié)尾
- 插件dll資源的語(yǔ)言必須為L(zhǎng)ANG_ENGLISH,code page必須為1252。在rc文件里是這么寫(xiě)的:
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
- 插件dll的VERSION_INFO里面必須包含以下值:
VALUE "MIMEType", "application/x-your-mimetype"
這個(gè)MIME就是<object>標(biāo)簽引用插件的唯一憑證。
在Linux下,plugins必須滿足以下條件才能被檢測(cè)到:
- 插件的名字必須是lib*plugin.so,即以lib開(kāi)頭,plugin.so結(jié)尾
- 插件必須實(shí)現(xiàn)NP_GetMIMEDescription和NP_GetPluginVersion,并返回合適MIME字符串。注意,這個(gè)字符串并不是普通的MIME,是有特殊規(guī)則的,詳見(jiàn)前面這個(gè)鏈接的內(nèi)容。
- 插件so不要靜態(tài)鏈接gtk、opensll、pthread、z等系統(tǒng)庫(kù),這會(huì)在不同linux平臺(tái)上因?yàn)榉?hào)表的問(wèn)題遇到各種運(yùn)行時(shí)錯(cuò)誤
特別需要說(shuō)明的是,NP_GetPluginVersion、NP_GetEntryPoints等關(guān)鍵函數(shù)沒(méi)有任何官方文檔介紹它們,只能根據(jù)例子來(lái)猜,反正沒(méi)事就別改它們的實(shí)現(xiàn),copy例子中的代碼就好。
firefox插件開(kāi)發(fā)注意事項(xiàng)
寫(xiě)firefox插件的一個(gè)基本習(xí)慣是,經(jīng)常編譯代碼并運(yùn)行它,保證你的插件還能工作。只要firefox無(wú)法加載dll/so,或者加載出現(xiàn)任何錯(cuò)誤,都會(huì)悄無(wú)聲息的忽略這個(gè)插件。時(shí)常關(guān)注一下about:plugins,看看插件是不是還在這個(gè)列表里。
firefox插件從窗口模式上可分為windowless和windowed兩種。其中,windowless模式的文檔較多較全,是firefox比較推薦的模式,坑比較少,這里就不多說(shuō)了。windowed模式則相反,需要好好說(shuō)說(shuō)。
無(wú)論在Windows還是Linux上,windowed的插件都擁有獨(dú)立于瀏覽器頁(yè)面的窗口。firefox會(huì)通過(guò)插件的NPP_SetWindow來(lái)告訴插件當(dāng)前窗口的情況。
關(guān)于windowed插件有兩個(gè)詭異問(wèn)題需要注意:
- Windows平臺(tái)下,插件窗口默認(rèn)會(huì)響應(yīng)WM_CTLCOLOREDIT、WM_CTLCOLORLISTBOX、WM_CTLCOLORBTN、WM_CTLCOLORSTATIC消息,并設(shè)置一個(gè)默認(rèn)的背景色。這本來(lái)沒(méi)問(wèn)題,但在Windows XP下,這個(gè)顏色居然永遠(yuǎn)是黑色,而不是默認(rèn)系統(tǒng)背景色(通常是白色)。最好subclass這個(gè)窗口并且攔截這些消息,不要讓firefox去處理它們。對(duì)于插件來(lái)說(shuō),firefox處理這些消息只是幫倒忙而已。至于firefox還幫了哪些倒忙,可以去源碼widget/src/windows/nsWindows.cpp的nsWindow::ProcessMessage()去圍觀。
- Linux平臺(tái)下,NPP_SetWindow傳入的NPWindow指針中雖然有一個(gè)ws_info成員,這個(gè)成員里面也確實(shí)有一個(gè)display變量指向X Window的Display結(jié)構(gòu),但絕對(duì)不要真正使用它,否則可能會(huì)導(dǎo)致firefox直接退出,據(jù)說(shuō)這可能是firefox的一個(gè)bug。
測(cè)試firefox插件小技巧,測(cè)試方面的高手可以無(wú)視
測(cè)試插件前建議先在firefox里面創(chuàng)建一個(gè)新的profile(帳號(hào))。這樣可以創(chuàng)造一個(gè)最干凈的開(kāi)發(fā)環(huán)境,避免被其他擴(kuò)展/插件干擾。
默認(rèn)的profile名叫default,在命令行里輸入firefox -p default就可以使用這個(gè)profile。如果只是輸入firefox -p,會(huì)彈出一個(gè)對(duì)話框用于選擇profile。這個(gè)命令在Windows和Linux下都可使用。
無(wú)論是哪個(gè)平臺(tái),調(diào)試插件的方法都很類似。
Windows下可以用VC以調(diào)試方式啟動(dòng)firefox,載入插件時(shí)調(diào)試器會(huì)自動(dòng)載入對(duì)應(yīng)的符號(hào),捕捉發(fā)生的異常或者設(shè)斷點(diǎn)都很方便。
Linux下直接用gdb就好,細(xì)節(jié)應(yīng)該不用多說(shuō)。有一點(diǎn)需要注意,系統(tǒng)默認(rèn)安裝的firefox命令(默認(rèn)放在/usr/bin/firefox)是一個(gè)shell腳本,真正的可執(zhí)行文件名字需要打開(kāi)這個(gè)腳本自行查找。
實(shí)現(xiàn)firefox插件的基本功能
firefox為插件提供的接口十分原始,很多功能默認(rèn)沒(méi)有實(shí)現(xiàn),下面提供了一些思路和方法。
- 讓插件接受焦點(diǎn):默認(rèn)情況下,<object>標(biāo)簽不能獲得焦點(diǎn),必須指定tabindex。
- 在插件中使用tab鍵跳到下一個(gè)element:沒(méi)有好辦法,必須自己手動(dòng)將焦點(diǎn)還給瀏覽器窗口(Linux下不必如此),然后自己用NPN_*系列函數(shù)找到應(yīng)該獲得focus的DOM element,然后調(diào)用這個(gè)element的focus()方法。
- 隱藏和顯示插件:直接設(shè)置<object>標(biāo)簽的style.display = “none”即可,但這里有個(gè)嚴(yán)重的副作用,firefox會(huì)調(diào)用插件的NS_PluginShutdown,銷毀這個(gè)插件。如果不期望造成這種效果,要么別用這種方式隱藏插件,要么把插件狀態(tài)保存在js里,再次顯示的時(shí)候把狀態(tài)設(shè)回去。
- 觸發(fā)DOM事件:firefox沒(méi)有提供任何便利的方法觸發(fā)DOM事件,要在插件中做到這點(diǎn),必須自己模擬js觸發(fā)DOM事件的過(guò)程。例如,對(duì)于HTML事件,假設(shè)self是DOM element,js會(huì)這么做。
evt = document.createEvent("KeyboardEvent");
evt.initKeyEvent(
"blur", // in DOMString typeArg,
false, // in boolean canBubbleArg,
false); // in boolean cancelableArg,
self.dispatchEvent(evt);
對(duì)應(yīng)的C代碼就是
暫時(shí)先寫(xiě)到這里,如果還有什么疑難雜癥,歡迎評(píng)論,我繼續(xù)添加。
如何對(duì)于plugin進(jìn)行調(diào)試。
如firefox安裝路徑如下: C:\Program Files\Mozilla Firefox1)在配置屬性/調(diào)試/命令, 設(shè)置為你的firefo.exe路徑:
C:\Program Files\Mozilla Firefox\firefox.exe
2)在配置屬性/常規(guī)/輸出目錄, 設(shè)置為:
C:\Program Files\Mozilla Firefox\plugins
3) 在配置屬性/生成事件/生成后事件/命令行, 設(shè)置為
copy "$(OutDir)\$(ProjectName).dll" "C:\Program Files\Mozilla Firefox\plugins\$(ProjectName).dll"
< 2和3任選其一 >
運(yùn)行, 打開(kāi)測(cè)試的htm, 就可以調(diào)試?
樓上的方法現(xiàn)在應(yīng)該行不通了。
我的環(huán)境是firefox 5, VS2008,斷點(diǎn)進(jìn)不去,但是可以肯定調(diào)用的是我自己的插件。
目前我發(fā)現(xiàn)的調(diào)試插件dll的解決方法如下:
按照上述設(shè)置(也可以做成xpi安裝后,安裝目錄在appdata下一個(gè)文件夾內(nèi),將插件放到那里,只要firefox能找到插件正常調(diào)用就好了)后,正常F5進(jìn)入調(diào)試狀態(tài),再attach到進(jìn)程:plugin_container上,斷點(diǎn)就可以進(jìn)入調(diào)試了。
總結(jié)
以上是生活随笔為你收集整理的firefox插件开发和调试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 多彩泡泡屏保特效(JAVA版)
- 下一篇: 程序员在大城市奋斗的理由,仅为追求那些不