本文從瀏覽器架構(gòu)演進(jìn)、插件運(yùn)行機(jī)制、插件基本介紹和一些常見的插件實(shí)現(xiàn)思路幾個方向聊聊Chrome插件。
瀏覽器架構(gòu)演進(jìn)
單進(jìn)程瀏覽器時代
單進(jìn)程瀏覽器是指瀏覽器的所有功能模塊都是運(yùn)行在同一個進(jìn)程里,這些模塊包含了網(wǎng)絡(luò)、插件、JavaScript 運(yùn)行環(huán)境、渲染引擎和頁面等。在 2007 年之前,市面上瀏覽器都是單進(jìn)程的。
單進(jìn)程瀏覽器的架構(gòu) 很多功能模塊運(yùn)行在一個進(jìn)程里,是導(dǎo)致單進(jìn)程瀏覽器不穩(wěn)定、不流暢和不安全的一個主要因素。
不穩(wěn)定:早期瀏覽器需要借助于插件來實(shí)現(xiàn)諸如 Web 視頻、Web 游戲等各種強(qiáng)大的功能,但是插件是最容易出問題的模塊,并且還運(yùn)行在瀏覽器進(jìn)程之中,所以一個插件的意外崩潰會引起整個瀏覽器的崩潰。除了插件之外,渲染引擎模塊也是不穩(wěn)定的,通常一些復(fù)雜的 JavaScript 代碼就有可能引起渲染引擎模塊的崩潰。和插件一樣,渲染引擎的崩潰也會導(dǎo)致整個瀏覽器的崩潰。
不流暢:所有頁面的渲染模塊、JavaScript 執(zhí)行環(huán)境以及插件都是運(yùn)行在同一個線程中的,這就意味著同一時刻只能有一個模塊可以執(zhí)行。如果一個腳本非常耗時,它就會獨(dú)占整個線程,這樣導(dǎo)致其他運(yùn)行在該線程中的頁面沒有機(jī)會去執(zhí)行任務(wù),導(dǎo)致整個瀏覽器失去響應(yīng),變卡頓。
不安全:當(dāng)你在頁面運(yùn)行一個插件時,插件可以操作系統(tǒng)資源,如果是個惡意插件,那么它就可以釋放病毒、竊取你的賬號密碼,引發(fā)安全性問題。
多進(jìn)程瀏覽器時代
早期架構(gòu)
2008 年 Chrome 發(fā)布時的進(jìn)程架構(gòu) 從圖中可以看出,早期的架構(gòu)已經(jīng)對瀏覽器的能力進(jìn)行了拆分,主要拆分為三類:瀏覽器進(jìn)程、插件進(jìn)程和渲染進(jìn)程。每個頁面是運(yùn)行在單獨(dú)的渲染進(jìn)程中的,同時頁面里的插件也是運(yùn)行在單獨(dú)的插件進(jìn)程之中,進(jìn)程之間是通過 IPC 機(jī)制進(jìn)行通信。 這就解決了單進(jìn)程時代瀏覽器的各種問題:
解決不穩(wěn)定:由于進(jìn)程是相互隔離的,所以當(dāng)一個頁面或者插件崩潰時,影響到的僅僅是當(dāng)前的頁面進(jìn)程或者插件進(jìn)程,并不會影響到瀏覽器和其他頁面。
解決不流暢:JavaScript運(yùn)行在渲染進(jìn)程中,所以即使JavaScript阻塞了渲染進(jìn)程,也只會影響當(dāng)前的渲染頁面,并不會影響瀏覽器和其他頁面,因為其他頁面的腳本運(yùn)行在它們自己的渲染進(jìn)程中。
解決不安全:Chrome把插件進(jìn)程和渲染進(jìn)程鎖在沙箱里面,沙箱里面的程序可以運(yùn)行,但是不能在硬盤上寫入任何數(shù)據(jù),也不能在敏感位置讀取任何數(shù)據(jù),這樣即使在渲染進(jìn)程或者插件進(jìn)程里面執(zhí)行了惡意程序,惡意程序也無法突破沙箱去獲取系統(tǒng)權(quán)限。
近期架構(gòu)
相較之前,近期的架構(gòu)又有了很多新的變化。
近期Chrome進(jìn)程架構(gòu) 從圖中可以看出,最新的 Chrome 瀏覽器包括:1 個瀏覽器主進(jìn)程、1 個 GPU 進(jìn)程、1 個網(wǎng)絡(luò)進(jìn)程、多個渲染進(jìn)程和多個插件進(jìn)程。
瀏覽器進(jìn)程:主要負(fù)責(zé)界面顯示、用戶交互、子進(jìn)程管理,同時提供存儲等功能??梢岳斫鉃g覽器進(jìn)程是一個統(tǒng)一的"調(diào)度大師"去調(diào)度其他進(jìn)程,比如我們在地址欄輸入url時,瀏覽器進(jìn)程首先會調(diào)用網(wǎng)絡(luò)進(jìn)程。
渲染進(jìn)程:核心任務(wù)是將HTML、CSS和JavaScript轉(zhuǎn)換為用戶可以交互的網(wǎng)頁,排版引擎Blink和JavaScript引擎V8都是運(yùn)行在該進(jìn)程中,默認(rèn)情況下,Chrome會為每個 Tab 標(biāo)簽創(chuàng)建一個渲染進(jìn)程。出于安全考慮,渲染進(jìn)程都是運(yùn)行在沙箱模式下。
GPU進(jìn)程:其實(shí),Chrome 剛開始發(fā)布的時候是沒有 GPU 進(jìn)程的。而 GPU 的使用初衷是為了實(shí)現(xiàn) 3D CSS 的效果,只是隨后網(wǎng)頁、Chrome 的 UI 界面都選擇采用 GPU 來繪制,這使得 GPU 成為瀏覽器普遍的需求。最后,Chrome 在其多進(jìn)程架構(gòu)上也引入了 GPU 進(jìn)程。
網(wǎng)絡(luò)進(jìn)程:主要負(fù)責(zé)頁面的網(wǎng)絡(luò)資源加載,之前是作為一個模塊運(yùn)行在瀏覽器進(jìn)程里面的,直至最近才獨(dú)立出來,成為一個單獨(dú)的進(jìn)程。
插件進(jìn)程:主要是負(fù)責(zé)插件的運(yùn)行,因插件易崩潰,所以需要通過插件進(jìn)程來隔離,以保證插件進(jìn)程崩潰不會對瀏覽器和頁面造成影響。
當(dāng)前架構(gòu)
目前Chrome瀏覽器的架構(gòu)正在發(fā)生一些改變,稱為面向服務(wù)的架構(gòu)(SOA),目的是將和瀏覽器本身(Chrome)相關(guān)的部分拆分為一個個不同的服務(wù),服務(wù)化之后,這些功能既可以放在不同的進(jìn)程里面運(yùn)行也可以合并為一個單獨(dú)的進(jìn)程運(yùn)行。 這樣做的主要原因是讓Chrome在不同性能的硬件上有不同的表現(xiàn)。當(dāng)Chrome運(yùn)行在一些性能比較好的硬件時,瀏覽器進(jìn)程相關(guān)的服務(wù)會被放在不同的進(jìn)程運(yùn)行以提高系統(tǒng)的穩(wěn)定性。相反如果硬件性能不好,這些服務(wù)就會被放在同一個進(jìn)程里面執(zhí)行來減少內(nèi)存的占用。
面向服務(wù)的架構(gòu)
插件運(yùn)行機(jī)制
在運(yùn)行機(jī)制前,我們先來回顧一下打開頁面會發(fā)生什么:
打開頁面發(fā)生了什么
用戶新增一個tab,此時系統(tǒng)瀏覽器進(jìn)程、渲染進(jìn)程、GPU 進(jìn)程、網(wǎng)絡(luò)進(jìn)程會被創(chuàng)建好;
用戶輸入url,瀏覽器進(jìn)程檢查url,組裝協(xié)議,構(gòu)成完整的url;
瀏覽器進(jìn)程通過進(jìn)程間通信(IPC)把url請求發(fā)送給網(wǎng)絡(luò)進(jìn)程;
網(wǎng)絡(luò)進(jìn)程接收到url請求后檢查本地緩存是否緩存了該請求資源,如果有則將該資源返回給瀏覽器進(jìn)程;
如果沒有,網(wǎng)絡(luò)進(jìn)程向web服務(wù)器發(fā)起http請求(網(wǎng)絡(luò)請求);
網(wǎng)絡(luò)進(jìn)程解析響應(yīng)流程;
檢查狀態(tài)碼,非200執(zhí)行狀態(tài)碼對應(yīng)的處理邏輯;
200響應(yīng)處理:檢查響應(yīng)類型Content-Type,如果是字節(jié)流類型,則將該請求提交給下載管理器,不再進(jìn)行后續(xù)的渲染,如果是html則通知瀏覽器進(jìn)程準(zhǔn)備渲染進(jìn)程進(jìn)行渲染;
準(zhǔn)備渲染進(jìn)程
瀏覽器進(jìn)程檢查當(dāng)前url是否和之前打開的渲染進(jìn)程根域名是否相同,如果相同,則復(fù)用原來的進(jìn)程,如果不同,則開啟新的渲染進(jìn)程;
傳輸數(shù)據(jù)、更新狀態(tài)
渲染進(jìn)程準(zhǔn)備好后,瀏覽器向渲染進(jìn)程發(fā)起“提交文檔”的消息,渲染進(jìn)程接收到消息和網(wǎng)絡(luò)進(jìn)程建立傳輸數(shù)據(jù)的“管道”;
渲染進(jìn)程接收完數(shù)據(jù)后,向瀏覽器發(fā)送確認(rèn)消息;
瀏覽器進(jìn)程接收到確認(rèn)消息后更新瀏覽器界面狀態(tài):安全、地址欄url、前進(jìn)后退的歷史狀態(tài)、更新web頁面;
打開插件發(fā)生了什么
插件的運(yùn)行相較于頁面會有簡化
我們打開瀏覽器,新增一個空白tab頁
tab欄空白處右鍵,選擇任務(wù)管理器,打開任務(wù)管理器面板
可以看到運(yùn)行了6個進(jìn)程,分別是瀏覽器進(jìn)程、GPU進(jìn)程、網(wǎng)絡(luò)進(jìn)程、存儲進(jìn)程、渲染進(jìn)程和擴(kuò)展進(jìn)程。
擴(kuò)展進(jìn)程中運(yùn)行Extension Page,主要包括backgrount.html和popup.html;
backgrount.html中沒有任何內(nèi)容,是通過background.js創(chuàng)建生成,當(dāng)瀏覽器打開時,會自動加載插件的background.js文件,它獨(dú)立于網(wǎng)頁并且一直運(yùn)行在后臺,它主要通過調(diào)用瀏覽器提供的API和瀏覽器進(jìn)行交互;
popup.html有內(nèi)容的,跟我們普通的web頁面一樣,由html、css、Javascript組成,它是按需加載的,需要用戶去點(diǎn)擊地址欄的按鈕去觸發(fā),才能彈出頁面;
渲染進(jìn)程主要運(yùn)行Web Page,當(dāng)打開頁面時,會將content_script.js加載并注入到該網(wǎng)頁的環(huán)境中,它和網(wǎng)頁中引入的Javascript一樣,可以操作該網(wǎng)頁的DOM Tree,改變頁面的展示效果;
GPU進(jìn)程主要為插件界面的渲染提供硬件能力支持;
網(wǎng)絡(luò)進(jìn)程主要處理插件中的外部資源請求,比如nexydy插件依賴到一些外部js;
存儲進(jìn)程為插件提供本地存儲能力,比如使用chrome.storage.local進(jìn)行持久化存儲;
瀏覽器進(jìn)程在這里更多起到橋梁作用,作為中轉(zhuǎn)可以實(shí)現(xiàn)Extension Page和content_script.js之間的消息通信。
插件基本介紹
版本發(fā)展
chrome插件存在三個版本,分別是Manifest V1、Manifest V2和Manifest V3。 其中MV1版本已經(jīng)被廢棄了,目前市面上存在MV2和MV3版本,以MV2為主流,在被MV3慢慢取代。 時間線:
Manifest V2新特性
https://developer.chrome.com/docs/extensions/mv2/manifestVersion/#manifest-v1-changes
設(shè)置了默認(rèn)的內(nèi)容安全策略`script-src 'self'; object-src 'self';`。有關(guān)內(nèi)容安全策略的詳細(xì)配置,可以參考MDN文檔;
默認(rèn)情況下,插件包內(nèi)的資源不再可供外部網(wǎng)站使用。需要通過清單web_accessible_resources屬性將其顯式列入白名單;
browser action API更改;
page action API更改;
chrome.extension代替chrome.self來指向插件本身;
chrome.extension.getTabContentses和chrome.extension.getExtensionTabs廢棄,使用extension.getViews替代;
Port.tab廢棄,使用runtime.Port替代;
Manifest V3新特性
Service worker替換Background Page;
網(wǎng)絡(luò)請求修改廢棄webRequest API使用新的declarativentrequest API來處理;
不再允許執(zhí)行遠(yuǎn)程托管的代碼,只能執(zhí)行擴(kuò)展包內(nèi)包含的JS;
Promises 已經(jīng)被添加到許多方法中,但仍支持回調(diào)作為替代方法;
Browser Action API和Page Action API被統(tǒng)一為單獨(dú)的Action API;
Web可訪問的資源,可以只對指定的站點(diǎn)和擴(kuò)展可用;
內(nèi)容安全策略(CSP),現(xiàn)在可以為單個對象中的不同執(zhí)行上下文指定單獨(dú)的CSP;
executeScript的變化,不能再執(zhí)行任意字符串,只能執(zhí)行腳本文件和函數(shù);
切換MV3會帶來的問題
由于background不再支持page頁面配置background.html,因此也無法調(diào)用window對象上的XMLHttpRequest來構(gòu)建ajax請求,也就是說我們不能像V2版本一樣,在background.html中使用XMLHttpRequest來發(fā)送請求了,而是需要使用fetch來獲取接口數(shù)據(jù);
由于service workers是短暫的,在不使用時會終止,這意味著它們在整個插件運(yùn)行期間會不斷的啟動、運(yùn)行和終止,也就是不穩(wěn)定的;因此我們可能需要對V2中background.js的代碼邏輯進(jìn)行一些改造,以往我們會習(xí)慣將一些數(shù)據(jù)直接存儲到全局變量,比如像下面這樣:
// V2 background.js let saveUserName = ""; // 其他頁面,比如content-script或者popup中存儲數(shù)據(jù) chrome.runtime.onMessage.addListener(({ type, name }) => { if (type === "set-name") { saveUserName = name; } }); // 點(diǎn)擊popup時展示數(shù)據(jù) chrome.action.onClicked.addListener((tab) => { // 這里saveUserName可能為空字符串 console.log(saveUserName, "saveUserName"); });
因此在V3中,需要對這種全局變量數(shù)據(jù)進(jìn)行改造,改造的方式也很簡單,就是將數(shù)據(jù)持久化保存到storage中,需要用到的地方隨用隨?。?/p>
// V3 service worker chrome.runtime.onMessage.addListener(({ type, name }) => { if (type === "set-name") { chrome.storage.local.set({ name }); } }); chrome.action.onClicked.addListener(async (tab) => { const { name } = await chrome.storage.local.get(["name"]); chrome.tabs.sendMessage(tab.id, { name }); });
由webRequest API切換至declarativentrequest API,很多代碼邏輯需要重構(gòu);
為什么切換MV3?
從Manifest V1到Manifest V2,可以看到Chrome想提高插件的隱私和安全,同時也優(yōu)化了不少API。 而Manifest V3除了安全性更完善外,還在性能上下了功夫。Manifest V3 的核心非常明確,就是限制擴(kuò)展對系統(tǒng)資源的使用。一直以來高資源占用都是 Chrome 為人詬病的痛點(diǎn),而且擴(kuò)展由于在后臺運(yùn)行,如果出現(xiàn)問題,更是難以定位和管理。 雖然增加了諸多限制,但Manifest V3還是有優(yōu)點(diǎn)的:
Service Worker 使擴(kuò)展不再能常駐后臺,讓擴(kuò)展所占用的資源可以被回收,降低了瀏覽器整體的開銷;
限制規(guī)則的數(shù)量,相當(dāng)于控制了單一擴(kuò)展在規(guī)則計算方面的資源使用上限;
這些變化可以讓 Chrome 變得更加流暢,對于用戶來說是好事。
展示形式
Chrome插件有以下常見的8中展現(xiàn)形式:
browserAction(瀏覽器右上角)
在瀏覽器右上角擴(kuò)展程序一欄顯示,包含一個圖標(biāo)、名稱和popup
山海關(guān)插件popup
pageAction(地址欄右側(cè))
pageAction指的是在當(dāng)某些特定頁面打開才顯示的圖標(biāo)。在早些版本的Chrome是將pageAction放在地址欄的最右邊,左鍵單擊彈出popup,右鍵單擊則彈出相關(guān)默認(rèn)的選項菜單。而新版的Chrome更改了這一策略,pageAction和普通的browserAction一樣也是放在瀏覽器右上角,只不過沒有點(diǎn)亮?xí)r是灰色的,點(diǎn)亮了才是彩色的,灰色時無論左鍵還是右鍵單擊都是彈出選項。
右鍵菜單
通過開發(fā)Chrome插件可以自定義瀏覽器的右鍵菜單,主要是通過chrome.contextMenus API實(shí)現(xiàn),右鍵菜單可以出現(xiàn)在不同的上下文,比如普通頁面、選中的文字、圖片、鏈接,等等。
掘金插件右鍵菜單
override(覆蓋特定頁面)
使用override可以將Chrome默認(rèn)的一些特定頁面替換掉,改為使用擴(kuò)展提供的頁面。 擴(kuò)展可以替代如下頁面:
歷史記錄:從工具菜單上點(diǎn)擊歷史記錄時訪問的頁面,或者從地址欄直接輸入chrome://history
新標(biāo)簽頁:當(dāng)創(chuàng)建新標(biāo)簽的時候訪問的頁面,或者從地址欄直接輸入chrome://newtab
書簽:瀏覽器的書簽,或者直接輸入 chrome://bookmarks
掘金插件替換了新標(biāo)簽頁
devtools(開發(fā)者工具)
Chrome允許插件在開發(fā)者工具(devtools)上開發(fā),主要表現(xiàn)在:
自定義一個和多個和Elements、Console、Sources等同級別的面板;
自定義側(cè)邊欄(sidebar),目前只能自定義Elements面板的側(cè)邊欄;
React Developer Tools
option(選項頁)
插件的設(shè)置頁面,可以在右上角入口右鍵,有一個選項標(biāo)簽。
omnibox
omnibox是向用戶提供搜索建議的一種方式,可以在搜索欄輸入特定的標(biāo)識然后按Tab進(jìn)入搜索。
JSON Viewer插件
桌面通知
Chrome提供了一個chrome.notificationsAPI以便插件推送桌面通知,暫未找到chrome.notifications和HTML5自帶的Notification的顯著區(qū)別及優(yōu)勢。 在后臺JS中,無論是使用chrome.notifications還是Notification都不需要申請權(quán)限(HTML5方式需要申請權(quán)限),直接使用即可。
核心介紹
manifest.json
這是一個Chrome插件最重要也是必不可少的文件,用來配置所有和插件相關(guān)的配置,必須放在根目錄。其中,manifest_version、name、version3個是必不可少的。 Manifest V2
{ // 清單文件的版本,這里先使用2演示 "manifest_version": 2, // 插件的名稱 "name": "...", // 插件的版本 "version": "1.0.0", // 插件描述 "description": "...", // 圖標(biāo),一般偷懶全部用一個尺寸的也沒問題 "icons": { "16": "img/icon.png", "48": "img/icon.png", "128": "img/icon.png" }, // 會一直常駐的后臺JS或后臺頁面 "background": { "scripts": ["js/background.js"] }, // 瀏覽器右上角圖標(biāo)設(shè)置,browser_action、page_action、app必須三選一 "browser_action": { "default_icon": "img/icon.png", "default_title": "...", "default_popup": "popup.html" }, // 當(dāng)某些特定頁面打開才顯示的圖標(biāo) "page_action": { "default_icon": "img/icon.png", "default_title": "...", "default_popup": "popup.html" }, // 需要直接注入頁面的JS "content_scripts": [{ "matches": [""], "js": ["js/content-script.js"], "css": ["css/custom.css"], // 代碼注入的時機(jī),document_start, document_end, document_idle,默認(rèn)document_idle "run_at": "document_start" }, ], // 權(quán)限申請 "permissions": [ "contextMenus", // 右鍵菜單 "tabs", // 標(biāo)簽 "notifications", // 通知 "webRequest", // web請求 "webRequestBlocking", "storage", // 插件本地存儲 "https://*/*" // 可以通過executeScript或者insertCSS訪問的網(wǎng)站 ], // 普通頁面能夠直接訪問的插件資源列表,如果不設(shè)置是無法直接訪問的 "web_accessible_resources": ["js/inject.js"], "homepage_url": "...", // 插件主頁 "chrome_url_overrides": { // 覆蓋瀏覽器默認(rèn)頁面 "newtab": "newtab.html" }, "options_ui": { // 插件選項頁 "page": "options.html", "chrome_style": true }, "omnibox": { "keyword" : "..." }, // 向地址欄注冊一個關(guān)鍵字以提供搜索建議,只能設(shè)置一個關(guān)鍵字 "default_locale": "zh_CN", // 默認(rèn)語言 "devtools_page": "devtools.html", // devtools頁面入口,注意只能指向一個HTML文件,不能是JS文件 "content_security_policy": "...", // 安全策略 "web_accessible_resources": [ // 可以加載的資源 RESOURCE_PATHS ] }
Manifest V3(僅展示與V2版本的不同點(diǎn))
{ "manifest_version": 3, "background": { "service_worker": js/background.js" }, "action": { //browser_action 和 page_action,統(tǒng)一為 Action "default_icon": "img/icon.png", "default_title": "這是一個示例Chrome插件", "default_popup": "popup.html" } "content_security_policy": { "extension_pages": "...", "sandbox": "..." }, "web_accessible_resources": [{ "resources": [RESOURCE_PATHS] }] }
content-scripts
是Chrome插件中向頁面注入腳本的一種形式(雖然名為script,其實(shí)還可以包括css的),借助content-scripts我們可以實(shí)現(xiàn)通過配置的方式輕松向指定頁面注入JS和CSS。 content-scripts和原始頁面共享DOM,但不共享JS。如要訪問頁面JS(例如某個JS變量),只能通過injected js來實(shí)現(xiàn)。content-scripts不能訪問絕大部分chrome API,除了下面這4種:
chrome.extension
chrome.i18n
chrome.runtime
chrome.storage
這些API絕大部分時候都夠用了,有需要調(diào)用其它API的話,可以通過通信讓background或service worker來幫忙調(diào)用
background
后臺是一個常駐的頁面,它的生命周期是插件中所有類型頁面中最長的,它隨著瀏覽器的打開而打開,隨著瀏覽器的關(guān)閉而關(guān)閉,所以通常把需要一直運(yùn)行的、啟動就運(yùn)行的、全局的代碼放在background里面。 background的權(quán)限非常高,幾乎可以調(diào)用所有的Chrome擴(kuò)展API(除了devtools),而且它可以無限制跨域,可以跨域訪問任何網(wǎng)站而無需要求對方設(shè)置CORS。 background的概念在MV3版本中變?yōu)榱藄ervice worker,區(qū)別在于生命周期變短了,service worker是短暫的基于事件的腳本,所以不適合用來保存全局變量。
popup
popup是點(diǎn)擊右上角圖標(biāo)時打開的一個小窗口網(wǎng)頁,焦點(diǎn)離開網(wǎng)頁就立即關(guān)閉,一般用來做一些臨時性的交互。權(quán)限級別和background差不多,就是生命周期比較短。
injected-script
chrome插件中其實(shí)沒有injected-script這一概念,這是開發(fā)者們在開發(fā)過程中衍生出來的一種概念,指的是通過DOM操作的方式向頁面注入的一種JS。 因為content-script無法訪問頁面中的JS,雖然可以操作DOM,但是DOM卻不能調(diào)用它,也就是無法在DOM中通過綁定事件的方式調(diào)用content-script中的代碼。但是在網(wǎng)頁中增加一個按鈕來調(diào)用插件的能力是一個比較常見的需求,所以誕生了injected-script。
插件通信機(jī)制
講通信機(jī)制之前,先回顧一下插件中存在的腳本類型。 Chrome插件的JS主要可以分為這5類:injected script、content-script、popup js、background js和devtools js。
權(quán)限對比
JS種類 | 可訪問的API | DOM訪問情況 | JS訪問情況 | 直接跨域 |
injected | 和普通JS無任何差別,不能訪問任何擴(kuò)展API | 可以訪問 | 可以訪問 | 不可以 |
content | 只能訪問 extension、runtime等部分API | 可以訪問 | 不可以 | 不可以 |
popup | 可訪問絕大部分API,除了devtools系列 | 不可直接訪問 | 不可以 | 可以 |
background | 可訪問絕大部分API,除了devtools系列 | 不可直接訪問 | 不可以 | 可以 |
devtools | 只能訪問 devtools、extension、runtime等部分API | 可以 | 可以 | 不可以 |
通過權(quán)限對比可以看到,每一種腳本在權(quán)限上都不相同,所以各種腳本間的相互通信就非常重要,這也是插件能夠?qū)崿F(xiàn)眾多功能的基礎(chǔ)。
通信概覽
injected | content | popup | background | |
injected | - | window.postMessage | - | - |
content | window.postMessage | - | chrome.runtime.sendMessage chrome.runtime.connect | chrome.runtime.sendMessage chrome.runtime.connect |
popup | - | chrome.tabs.sendMessage chrome.tabs.connect | - | chrome.extension. getBackgroundPage |
background | - | chrome.tabs.sendMessage chrome.tabs.connect | chrome.extension.getViews | - |
devtools | chrome.devtools. inspectedWindow.eval | - | chrome.runtime.sendMessage | chrome.runtime.sendMessage |
一些常見插件的實(shí)現(xiàn)思路
埋點(diǎn)日志檢測
一般業(yè)務(wù)中都會進(jìn)行一些埋點(diǎn)上報,埋點(diǎn)的本質(zhì)就是發(fā)送一些帶特定參數(shù)的請求,前端本地調(diào)試的時候想實(shí)時查看埋點(diǎn)信息通常需要去查看上報接口的入?yún)?,或者去對?yīng)的埋點(diǎn)平臺查看,這樣非常不方便。 基于這個,我們可以使用插件來幫助我們快速的可視化查看埋點(diǎn)信息:
頁面注入小工具
插件的另一個常見用法就是往頁面注入一些工具代碼,比如去除頁面廣告工具。
總結(jié)
隨著瀏覽器不斷的發(fā)展,Chrome逐漸把一些基礎(chǔ)服務(wù)獨(dú)立出來,類似于一個跨平臺的線上操作系統(tǒng)。
Chrome插件提供的能力很豐富,比如代碼注入、跨域請求、持久化方案、各種通信機(jī)制等,開發(fā)者可以發(fā)揮想象,組裝不同能力以適應(yīng)不同場景的需求,基本可以實(shí)現(xiàn)現(xiàn)代web所能支持的所有功能。
Chrome插件MV2版本將在24年1月全面廢棄,需要盡快遷移至MV3版本。
審核編輯:黃飛
-
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6801瀏覽量
123280 -
瀏覽器
+關(guān)注
關(guān)注
1文章
1022瀏覽量
35325 -
Chrome
+關(guān)注
關(guān)注
0文章
342瀏覽量
18014 -
javascript
+關(guān)注
關(guān)注
0文章
516瀏覽量
53850 -
進(jìn)程
+關(guān)注
關(guān)注
0文章
203瀏覽量
13960
原文標(biāo)題:從瀏覽器原理出發(fā)聊聊Chrome插件
文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論