0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從瀏覽器原理解析Chrome常見插件的實(shí)現(xiàn)思路

OSC開源社區(qū) ? 來源:OSC開源社區(qū) ? 2023-12-08 14:25 ? 次閱讀

本文從瀏覽器架構(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)程的。

4d4db2e2-957c-11ee-8b88-92fbcf53809c.png

單進(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)

4d5922f8-957c-11ee-8b88-92fbcf53809c.png

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)槠渌撁娴哪_本運(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)又有了很多新的變化。

4d723590-957c-11ee-8b88-92fbcf53809c.png

近期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)存的占用。

4d765ad0-957c-11ee-8b88-92fbcf53809c.png

面向服務(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ù)后,向?yàn)g覽器發(fā)送確認(rèn)消息;

瀏覽器進(jìn)程接收到確認(rèn)消息后更新瀏覽器界面狀態(tài):安全、地址欄url、前進(jìn)后退的歷史狀態(tài)、更新web頁面;

打開插件發(fā)生了什么

插件的運(yùn)行相較于頁面會有簡化

我們打開瀏覽器,新增一個空白tab頁

4d8ef108-957c-11ee-8b88-92fbcf53809c.png

tab欄空白處右鍵,選擇任務(wù)管理器,打開任務(wù)管理器面板

4da50524-957c-11ee-8b88-92fbcf53809c.png

可以看到運(yùn)行了6個進(jìn)程,分別是瀏覽器進(jìn)程、GPU進(jìn)程、網(wǎng)絡(luò)進(jìn)程、存儲進(jìn)程、渲染進(jìn)程和擴(kuò)展進(jìn)程。

4dbcd4c4-957c-11ee-8b88-92fbcf53809c.png

擴(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慢慢取代。 時間線:

4dc48890-957c-11ee-8b88-92fbcf53809c.png

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中,需要用到的地方隨用隨取:

// 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

4df7a75c-957c-11ee-8b88-92fbcf53809c.png

山海關(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)亮了才是彩色的,灰色時無論左鍵還是右鍵單擊都是彈出選項。

4e21942c-957c-11ee-8b88-92fbcf53809c.png

右鍵菜單

通過開發(fā)Chrome插件可以自定義瀏覽器的右鍵菜單,主要是通過chrome.contextMenus API實(shí)現(xiàn),右鍵菜單可以出現(xiàn)在不同的上下文,比如普通頁面、選中的文字、圖片、鏈接,等等。

4e2bd306-957c-11ee-8b88-92fbcf53809c.png

掘金插件右鍵菜單

override(覆蓋特定頁面)

使用override可以將Chrome默認(rèn)的一些特定頁面替換掉,改為使用擴(kuò)展提供的頁面。 擴(kuò)展可以替代如下頁面:

歷史記錄:從工具菜單上點(diǎn)擊歷史記錄時訪問的頁面,或者從地址欄直接輸入chrome://history

新標(biāo)簽頁:當(dāng)創(chuàng)建新標(biāo)簽的時候訪問的頁面,或者從地址欄直接輸入chrome://newtab

書簽:瀏覽器的書簽,或者直接輸入 chrome://bookmarks

4e3bfe70-957c-11ee-8b88-92fbcf53809c.png

掘金插件替換了新標(biāo)簽頁

devtools(開發(fā)者工具)

Chrome允許插件在開發(fā)者工具(devtools)上開發(fā),主要表現(xiàn)在:

自定義一個和多個和Elements、Console、Sources等同級別的面板;

自定義側(cè)邊欄(sidebar),目前只能自定義Elements面板的側(cè)邊欄;

4e5228b2-957c-11ee-8b88-92fbcf53809c.png

React Developer Tools

option(選項頁)

插件的設(shè)置頁面,可以在右上角入口右鍵,有一個選項標(biāo)簽。

4ee38e6a-957c-11ee-8b88-92fbcf53809c.png

4eef110e-957c-11ee-8b88-92fbcf53809c.png

omnibox

omnibox是向用戶提供搜索建議的一種方式,可以在搜索欄輸入特定的標(biāo)識然后按Tab進(jìn)入搜索。

4efa6734-957c-11ee-8b88-92fbcf53809c.png

JSON Viewer插件

桌面通知

Chrome提供了一個chrome.notificationsAPI以便插件推送桌面通知,暫未找到chrome.notifications和HTML5自帶的Notification的顯著區(qū)別及優(yōu)勢。 在后臺JS中,無論是使用chrome.notifications還是Notification都不需要申請權(quán)限(HTML5方式需要申請權(quán)限),直接使用即可。

4f0aada6-957c-11ee-8b88-92fbcf53809c.png

核心介紹

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。 因?yàn)閏ontent-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)信息:

4f20e3aa-957c-11ee-8b88-92fbcf53809c.jpg

頁面注入小工具

插件的另一個常見用法就是往頁面注入一些工具代碼,比如去除頁面廣告工具。

4f30914c-957c-11ee-8b88-92fbcf53809c.jpg

總結(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版本。

審核編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6822

    瀏覽量

    123331
  • 瀏覽器
    +關(guān)注

    關(guān)注

    1

    文章

    1025

    瀏覽量

    35353
  • Chrome
    +關(guān)注

    關(guān)注

    0

    文章

    344

    瀏覽量

    18032
  • javascript
    +關(guān)注

    關(guān)注

    0

    文章

    516

    瀏覽量

    53864
  • 進(jìn)程
    +關(guān)注

    關(guān)注

    0

    文章

    203

    瀏覽量

    13961

原文標(biāo)題:從瀏覽器原理出發(fā)聊聊Chrome插件

文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Chrome 15正式版瀏覽器登場

    `Google今天發(fā)布了Chrome 15正式版,Windows、Linux、Mac三大平臺以及Chrome Frame瀏覽器內(nèi)嵌框架用戶均可更新至最新的Chrome 15.0.874
    發(fā)表于 10-26 18:49

    樹莓派安裝chrome瀏覽器的問題

    如題,在安裝chrome瀏覽器的時候,出現(xiàn)如下圖問題。怎么破?
    發(fā)表于 09-11 11:07

    安裝了chrome瀏覽器,但還是很卡

    在論壇看到了發(fā)燒友大神說的關(guān)于瀏覽器的問題,我也就安裝了chrome瀏覽器,但是還是卡爆了。CPU爆棚的說。。。
    發(fā)表于 09-12 16:44

    Chrome瀏覽器將在ARM內(nèi)核運(yùn)行,Google Andr

    Chrome瀏覽器將在ARM內(nèi)核運(yùn)行,Google Android如虎添翼 Google將為其新發(fā)布的x86瀏覽器開發(fā)一個適用于ARM處理的內(nèi)核,Google創(chuàng)始人之一Sergey
    發(fā)表于 09-05 10:57 ?1385次閱讀

    視頻監(jiān)控系統(tǒng)跨瀏覽器插件的研究與實(shí)現(xiàn)

    針對目前視頻監(jiān)控系統(tǒng)的瀏覽器插件與非IE內(nèi)核的瀏覽器不兼容的問題,本文采用基于FireBreath開發(fā)框架開發(fā)跨瀏覽器插件系統(tǒng)的方法,使
    發(fā)表于 12-18 16:03 ?5次下載

    四大瀏覽器續(xù)航對決,結(jié)果Chrome瀏覽器完勝

    近日,YouTube頻道UP主Linus Tech Tips進(jìn)行了一次四大瀏覽器續(xù)航對決,結(jié)果Chrome瀏覽器完勝。
    發(fā)表于 06-27 10:16 ?1400次閱讀

    Chrome成為瀏覽器市場的霸主 微軟Edge慘淡收場

    瀏覽器競爭的賽道上,微軟Edge算是徹底輸了。微軟為與Chrome競爭重新啟動Edge瀏覽器,但結(jié)果確實(shí)不如人意。如今Chrome已徹底統(tǒng)治瀏覽器
    發(fā)表于 02-03 10:23 ?868次閱讀

    谷歌瀏覽器 Chrome 發(fā)布 Linux 版本即將跟進(jìn)

    今 天谷歌瀏覽器Google Chrome正式對用戶提供下載,不過現(xiàn)在只發(fā)布了 Windows 版本,Linux MAC 版本也將會在近期發(fā)布。谷歌瀏覽器 Chrome
    發(fā)表于 04-02 14:38 ?543次閱讀

    Chrome瀏覽器隱私設(shè)置重新設(shè)計后有什么不同

    Chromium小組重新設(shè)計了Chrome瀏覽器的“隱私設(shè)置”或Chrome 80中的“隱私和安全設(shè)置”卡。
    的頭像 發(fā)表于 11-16 09:37 ?2302次閱讀

    五大Chrome神級插件,讓Chrome瀏覽器更加好用十倍

    Chrome谷歌瀏覽器是很多人心目中的NO.1,雖然它很好用,但難免還是有些功能顧及不到。這時候,就需要插件來幫忙。今天介紹5個Chrome神級插件
    的頭像 發(fā)表于 09-17 14:05 ?3202次閱讀

    Chrome瀏覽器“吃”太多內(nèi)存怎么辦?

    我們知道Chrome是非常出色的瀏覽器,無論性能還是功能的角度來看,都是如此。
    的頭像 發(fā)表于 11-27 09:19 ?2989次閱讀

    Chrome瀏覽器插件v1.9.0發(fā)布 使用了最簡單的JavaScript代碼解析

    Chrome 瀏覽器插件以往的文章獲取方式,也跟著專區(qū)內(nèi)容在進(jìn)步。因此,本次的版本更新帶來的主要功能亦即是:支持專區(qū)文章展示。細(xì)節(jié)效果圖如下: OSCHINA Chrome
    的頭像 發(fā)表于 01-08 11:39 ?2030次閱讀
    <b class='flag-5'>Chrome</b><b class='flag-5'>瀏覽器</b><b class='flag-5'>插件</b>v1.9.0發(fā)布 使用了最簡單的JavaScript代碼<b class='flag-5'>解析</b>

    暴力猴瀏覽器插件

    暴力猴瀏覽器插件
    發(fā)表于 05-29 11:20 ?6次下載

    瀏覽器支持javascript怎么設(shè)置

    和JavaScript之間的關(guān)系。瀏覽器是一個軟件應(yīng)用程序,用于解析和渲染網(wǎng)頁。它可以是桌面應(yīng)用程序(例如Chrome,F(xiàn)irefox和Safari)或移動應(yīng)用程序(例如Safari和Chro
    的頭像 發(fā)表于 11-26 11:22 ?1443次閱讀

    寫一個Chrome瀏覽器插件

    一、什么是瀏覽器插件 瀏覽器插件是依附于瀏覽器,用來拓展網(wǎng)頁能力的程序。插件具有監(jiān)聽
    的頭像 發(fā)表于 11-18 17:12 ?338次閱讀
    寫一個<b class='flag-5'>Chrome</b><b class='flag-5'>瀏覽器</b><b class='flag-5'>插件</b>