Chrome 插件开发
文章目錄
- chrome 插件的控制能力
- chrome 插件的主要模塊
- 1. manifesh.json
- 2. background
- 3. content_scripts
- 4. popup
- 5. 五種JS之間的消息通信(比較關鍵!)
- 6. 簡單了解:event_pages
- 7. 有待深入:injected-script,涉及到消息通訊
- Chrome插件的 8 種展示方式
- 幾種腳本的API權限對比
- 零碎知識
- 常見問題
- 參考
chrome 插件的控制能力
除了支持傳統的一切 web API、JavaScript API 以外,chrome插件額外支持以下API(chrome.xxx):
- 瀏覽器窗口(chrome.window)
- tab標簽(chrome.tabs)
- 書簽(chrome.bookmark)
- 歷史(chrome.history)
- 下載(chrome.download)
- 網絡請求(chrome.webRequest)
- 各類事件監聽?
- 自定義右鍵菜單(chrome.contextMenus)
- 開發者工具擴展(chrome.devtool)
- 插件管理(chrome.extension)
chrome 插件的主要模塊
1. manifesh.json
{// 清單文件的版本,必須是2"minifest_version": 2,”name“: "demo","version": "1.0.0","description": "簡單的chrome插件demo","icons": {"16": "img/icon.png","48": "img/icon@48x.png","128": "img/icon@128x.png",},// 會一直常駐在后臺運行的js文件或html頁面。有 2 種指定方式:// ①指定js,那么會自動生成一個背景頁"background": {"scripts": ["js/background.js"]},// ②指定html頁面,可以通過script標簽引入多個js文件// "background": {// "page": "background.html"// },"browser_action": {"default_icon": "img/icon.png",// (可選)鼠標懸停在右上角圖標上的標題"default_title": "這是一個示例chrome插件","default_popup": "popup.html"},// 對某些特性網頁才顯示的圖標"page_action": {"default_icon": "img/icon.png","default_title": "這是page action","default_popup": "popup.html"},// 需要注入頁面的JS"content_scripts": [{// ["http://*/*", "https://*/*"] 表示匹配這兩個協議的所有地址// "<all_urls>" 表示匹配所有地址"matches": ["<all_urls>"],// 多個JS按順序注入"js": ["js/util.js", "js/content.js"],// CSS的注入容易影響全局,一定要謹慎!"css": ["css/custom.css"],// 代碼注入的時間,可選值:"document_start", "document_end", "document_idle",最后一個表示頁面空閑時,默認document_idle"run_at": "document_start"},// content_script 可配置多個規則{"matches": ["*://*/*.png", "*://*/*.jpg", "*://*/*.gif", "*://*/*.bmp"],"js": ["js/show-image-size.js"]}],// 申請權限"premissions": ["contextMenus","tabs","notifications","webRequest","storage","http://*/*", // 可以通過executeScript或者insertCSS訪問的網站???"https://*/*", // 可以通過executeScript或者insertCSS訪問的網站???],// 普通頁面能夠直接訪問的插件資源列表,如果不設置是無法直接訪問的???"web_accessible_resources": ["js/inject.js"],// 插件主頁,廣告位"homepage_url": "http://github.com/...",// 覆蓋瀏覽器默認頁"chrome_url_overrides": {// 覆蓋瀏覽器默認的新標簽頁"newtab": "newTab.html"},// 插件配置頁"options_ui": {"page": "options.html",// 添加官方的默認樣式,推薦使用"chrome_style": true},//"omnibox": { "keyword": "go" },//"default_locale": "zh_CN",// devtools 頁面入口??注意只能指向一個HTML文件,不能是JS文件"devtools_page": "devtools.html" }2. background
- 常駐在后臺一直運行的腳本或頁面,生命周期最長,隨著瀏覽器打開而打開,隨著瀏覽器關閉而關閉。通常把需要一直運行的、啟動就運行的、全局代碼放在這里面。
- background的權限非常大,幾乎可以調用所有的 chrome API(除了 devtools),而且它可以無限跨域,也就是可以跨域訪問任意網站而無需對方設置CORS。
- 【有待驗證:】(其實不止是background,所有的直接通過chrome-extension://id/xx.html這種方式打開的網頁都可以無限制跨域。)
- 后臺頁面只可調試代碼邏輯,是沒有界面的。
3. content_scripts
注意:
- content_scripts 里的js可以訪問頁面的DOM,但不能訪問頁面里的JS環境對象(比如某個JS變量),只能通過 injected js 來實現。
- content_scripts 不能訪問大部分的 chrome API,除了下面幾種:
- chrome.extension(getURL , inIncognitoContext , lastError , onRequest , sendRequest) 這是???
- chrome.i18n 國際化
- chrome.runtime(connect , getManifest , getURL , id , onConnect , onMessage , sendMessage) 訪問配置文件,本頁url
- chrome.storage 訪問本地存儲
- 這些API絕大部分時候都夠用了,非要調用其它API的話,你還可以通過通信來實現讓background來幫你調用
Content script是在一個特殊環境中運行的,這個環境成為isolated world(隔離環境)。它們可以訪問所注入頁面的DOM,但是不能訪問里面的任何javascript變量和函數。 對每個content script來說,就像除了它自己之外再沒有其它腳本在運行。 反過來也是成立的: 頁面里的javascript也不能訪問content script中的任何變量和函數。
4. popup
- popup是點擊browser_action或者page_action圖標時打開的一個小窗口網頁,焦點離開網頁就立即關閉,一般用來做一些臨時性的交互,或者作為一個需要頻繁操作的快捷入口。
- popup可以包含任意你想要的HTML內容,并且會自適應大小。可以通過default_popup字段來指定popup頁面,也可以調用setPopup()方法。
- 【注意】需要特別注意的是,由于單擊圖標打開popup,焦點離開又立即關閉,所以popup頁面的生命周期一般很短,需要長時間運行的代碼千萬不要寫在popup里面。
- 在權限上,它和background非常類似,它們之間最大的不同是生命周期的不同,popup中可以直接通過chrome.extension.getBackgroundPage()獲取background的window對象。
5. 五種JS之間的消息通信(比較關鍵!)
- 記憶的關鍵在于,理解這些通信路徑的目的和使用場景!
- popup和background其實幾乎可以視為一種東西,因為它們可訪問的API都一樣、通信機制一樣、都可以跨域。
- 閱讀這篇文章有助于理解插入腳本和內容腳本直接的通信方式:https://crxdoc-zh.appspot.com/extensions/content_scripts
注:第一列為發起方,第一行為接收
popup 可以直接調用 background 的JS方法,也可以直接訪問background的DOM:
網上有很多老代碼用的是 chrome.extension.onMessage,沒有搞清楚 chrome.extension 和 chrome.runtime 之間的區別,可能只是別名。建議統一使用 chrome.runtime。
- content 向 popup 主動發送消息的前提是 popup 必須打開,否則需要利用 background 作中轉;
- 如果 background 和 popup 存在多個地方監聽,那么他們都可以同時收到消息,但只有一個可以 senderResponse,一個先發送了,另外的就無效了。
嵌入頁面的JS 與 content 之間
(待續。。。暫未發現使用場景)
主要通過window.postMessage和window.addEventListener來實現二者消息通訊。
補充:長連接
相對于 chrome.tabs.sendMessage、chrome.runtime.sendMessage 這類短連接而言的,類似于 websocket 的概念。
接口:port = chrome.tabs.connect 和 port = chrome.runtime.connect
監聽:chrome.runtime.onConnect.addListener((port) => {…})
6. 簡單了解:event_pages
鑒于background生命周期太長,長時間掛載后臺可能會影響性能,所以Google又弄一個event-pages,在配置文件上,它與background的唯一區別就是多了一個persistent參數:
{"background": {"scripts": ["event-page.js"],"persistent": false} }它的生命周期是:在被需要時加載,在空閑時被關閉,什么叫被需要時呢?比如第一次安裝、插件更新、有content-script向它發送消息,等等。
7. 有待深入:injected-script,涉及到消息通訊
- 使用場景:因為content-script有一個很大的“缺陷”,也就是無法訪問頁面中的JS,雖然它可以操作DOM,但是DOM卻不能調用它,也就是無法在DOM中通過綁定事件的方式調用content-script中的代碼(包括直接寫onclick和addEventListener2種方式都不行),但是,“在頁面上添加一個按鈕并調用插件的擴展API”是一個很常見的需求
Chrome插件的 8 種展示方式
- browserAction(瀏覽器右上角)
- 圖標
- tooltip
- badge
- pageAction(地址欄右側)
- contextMenus(右鍵菜單)
- override(覆蓋特定頁)
- devtool(開發者工具)
- option(選項頁)
- omnibox(向地址欄注冊一個關鍵字以提供搜索建議)
- notification(桌面通知)
幾種腳本的API權限對比
零碎知識
-
沒有嚴格的項目結構要求,只要求保證根目錄有一個 manifest.json 即可。
-
chrome插件除了Chrome瀏覽器之外,還可以運行在所有webkit內核的國產瀏覽器,比如360極速瀏覽器、360安全瀏覽器、搜狗瀏覽器、QQ瀏覽器等等。
-
調試:打開開發者模式。在 chrome://extensions 里找到本插件,點擊“背景頁”,就可以打開 Devtools
- 如果要調試vue頁面
- 全局安裝包 npm install -g @vue/devtools
- 執行命令 vue-devtools 啟動
- 在頁面中加入
- 參見 https://www.jianshu.com/p/036c8eda1e7c
-
chrome.* API 中的方法通常是異步的:它們不等待操作完成就立即返回。如果您需要知道某個操作的結果,您應該向方法傳遞一個回調函數。
常見問題
-
關于插件ID
- chrome依靠插件ID而不是插件名字,來判斷是否為同一個插件。
- 開發測試時,使用的是未壓縮的文件夾,而其插件ID是根據插件所在的絕對路徑計算而來的。
- 想要為插件定制一個不變的ID,需要每次打包都輸入同一個私鑰文件,如圖
-
關于 pem 密鑰文件有何用?
- 用于生成插件ID,區分插件的。假設,你當前插件叫做MyFirstExtension,版本號為1.0,而下一次升級時,你想把產品名稱改為MySecondExtension,版本號為2.0。但,如何保證Chrome認為它們是一款插件呢?這個時候,就需要pem密鑰文件了,再次生成crx文件時,選擇pem文件。所以該文件要保存包,以便后續更新。
-
【與chrome插件無關】在websocket協議頭里無法通過自定義header字段添加 Token 鑒權信息。
- 解決方法:只能通過其他方式傳遞token,比如cookie。
-
如果要讓chrome插件與本地原生應用通訊,需要把插件id配置在 chrome 的 manifest.json 文件里:
- /Users/pangyue/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.thunder.chrome.host.json
- mac迅雷下載支持就是這樣干的
-
chrome.pageCapture 模塊,有個 saveAsMHTML 方法,可以為網頁保存快照在本地。但MHTML文件不能已在線的方式訪問,只能在本地文件系統下訪問。
MHTML is a standard format supported by most browsers. It encapsulates in a single file a page and all its resources (CSS files, images…).
Note that for security reasons a MHTML file can only be loaded from the file system and that it can only be loaded in the main frame.
- 獲取當前窗口ID
- 獲取當前標簽頁ID
- 本地存儲
- chrome.storage是針對插件全局的,你在background中保存的數據,在content-script也能獲取到;
- webRequest
請求攔截:
- Extension context invalidated. 報錯
- 重新安裝或者自動更新擴展程序時,現有內容腳本會失去與擴展程序其余部分的連接——即關閉端口,它們將無法使用runtime.sendMessage()——但內容腳本本身仍然可以繼續工作,因為它們已經被注入。
- 寫插件自動更新功能要注意該問題。
參考
- 官方文檔:https://developer.chrome.com/extensions
- 中文文檔:https://crxdoc-zh.appspot.com/extensions/api_index
- 中文文檔2:http://chrome.cenchy.com/
- 360瀏覽器擴展開發文檔:
- http://open.se.360.cn/open/extension_dev/overview.html
- http://open.chrome.360.cn/extension_dev/overview.html
- Mozilla:https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/What_are_WebExtensions
- 下載chrome插件crx文件離線安裝:https://crxdl.com/
- 國內插件市場:https://chromecj.com/tag
- 【來源:小茗同學】https://www.bookstack.cn/read/chrome-plugin-develop/spilt.10.8bdb1aac68bbdc44.md
- 【博客】Chrome插件(擴展)開發全攻略:https://www.cnblogs.com/liuxianan/p/chrome-plugin-develop.html
- 【博客系列文章】https://www.cnblogs.com/champagne/p/
- 一種開發 Chrome 擴展程序的新姿勢:
- 這篇文章提出了插件開發的痛點 – 不同運行環境之間的通訊問題。但可惜解決方案沒有vue版本,只有react版本。
- https://mp.weixin.qq.com/s?__biz=Mzg4MjE5OTI4Mw==&mid=2247490045&idx=1&sn=5141c0a6c6bc495f0733f620e18d3594&chksm=cf5b0661f82c8f7731f510475af28b37fcacdbf42cbc0282fe6f9482103463de1dd213ad5801&scene=132#wechat_redirect
總結
以上是生活随笔為你收集整理的Chrome 插件开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GetDisplayName 获取枚举的
- 下一篇: 实现栈的基本操作(c语言)