手頭有一個抓取頁面數據的小項目,之前一直使用 Bookmarklet 書簽腳本的方式來實現的。最近發現不能用了,因為涉及到要在抓取頁面插入遠程 JS 腳本,觸發了最新瀏覽器的內容保護策略(Content Security Policy)。無奈之下,只能尋找其他的替代方法,嘗試了一下,發現只能用瀏覽器擴展的方式來實現了。
一個極簡的插件
一個最簡單的火狐插件只需要兩個文件: 插件說明文件和腳本文件。
說明文件是插件的入口,內容為 JSON 格式,對插件進行了一些說明和配置。命名必須為 manifest.json。一個簡單的示例如下:
{
"manifest_version": 2,
"name": "MyFirefoxPlugin",
"version": "1.0",
"content_scripts": [
{
"matches": ["*://*.zzxworld.com/*"],
"js": ["app.js"]
}
]
}
content_scripts
配置項指明了擴展要加載的 JS 腳本和擴展適配的網址,位置相對於當前目錄。腳本內容就是常規的 javascript 代碼,比如:
document.body.style.border = "5px solid red";
插件界面類型
插件界面常用的有三種。一種是彈窗,比如點工具欄按鈕彈出一個彈出窗口,但這個彈出窗口不能失去焦點,否則就會消失,需要重新點擊。這不太適用於我的采集功能,因為我有無法識別的數據需要從頁面復制的操作流程。所以我采用了第二種:側邊欄。這個側邊欄是跟收藏夾在一起的,因為不會自動關閉,所以在腳本代碼中需要添加標簽頁切換事件的支持。第三種就是獨立的插件 tab 頁面了,這個適合復雜的大型擴展,暫時沒有研究。
插件消息機制
網頁是由 HTML + CSS 構建的,插件也是,問題來了:如何獲取網頁的內容傳遞給插件腳本,然后在插件界面現實呢?火狐的提供了插件的消息機制。在獲取頁面內容的腳本中使用 browser.runtime.sendMessage()
方法發起消息。然后在插件界面腳本中用 browser.runtime.onMessage.addListener()
方法來監聽捕獲消息。以此來實現頁面腳本和插件界面腳本的消息通訊。
打包和安裝
火狐提供了 web-ext
工具來輔助生成打包文件,但依賴 node,操作使用有點繁瑣。在 Linux 系統,可以使用 zip
命令。命令格式如下:
zip -r ../my-firefox-plugin.xpi *
以上命令在項目根目錄執行就行了,完成后就會在上一級目錄生成 my-firefox-plugin.xpi 文件,這個就是生成好的插件文件。但並不能直接使用。如果在火狐瀏覽器插件管理頁面用文件導入的方式安裝,得到的會是“文件損壞,無法安裝”的消息。網上查到的消息是使用 about:config
打開瀏覽器高級配置,然后配置 xpinstall.signatures.required 為 false
就能解決。我實際操作后仍然無效。最終的解決方案是到 https://addons.mozilla.org/ 網站注冊賬號,上傳生成的插件文件,通過審核並生成簽名后才能正常安裝。
插件開發調試
插件開發期間會不斷的修改和調整代碼。如果每次修改后都要打包才能測試那就太浪費時間了。在火狐中可以使用 about:debuging
,然后通過“臨時載入組建”的方式來實現快速的代碼重載和功能測試。