Hi Dai Gei Ho~ 我是Winnie ~
首先 大家中秋節快樂,在此篇文章中 我們要來介紹 Chrome Extension 中 的 Content Script ,雖然 前面已經有初步介紹過了,在今天文章內容中 預計會再針對其詳細內容及常見方法應用 進行補充。
如果大家有印象,Content Script 是 Extension 中唯一執行於 瀏覽器端 的 Context ,可以直接訪問 網頁中的資訊 且對DOM元素進行操作,同時又不會與頁面或其他Extension的內容腳本發生衝突。
截自:Google Chrome Extensions: Content Scripts and Isolated Worlds
雖然 Content Script 看似與網站的 JavaScript 共用,但其主要運行於 isolated worlds
,所以基本上兩個是完全隔離的。
因為isolated worlds
為一個私有Javascript執行環境,雖然它允許 Javascript 透過DOM取得view(視圖),但不能使用相關 window.xxx()
方法,所以兩者唯一共享的只有 HTML 中 DOM的View,不會互相產生程式碼衝突。
好像有點饒口,那讓我們以下程式範例為例:
這是一個 example.com
的頁面,當在頁面中點擊helloBtn
時,
原本頁面 會跳出 Good Morning ! Winnie
的 Alert :
// https://example.com
<html>
<button id="helloBtn">click me</button>
<script>
const greeting = "Good Morning ! ";
const button = document.getElementById("mybutton");
button.person_name = "Winnie";
button.addEventListener("click", () =>
alert(greeting + button.person_name + ".")
, false);
</script>
</html>
接著,當 Extension 將Content Script 注入example.com
的頁面
const greeting = "早上好, ";
const button = document.getElementById("mybutton");
button.person_name = "維尼";
button.addEventListener("click", () =>
alert(greeting + button.person_name + ".")
, false);
此時的結果會分別出現Good Morning ! Winnie
、早上好 !維尼
兩個Alert。 同時 我們宣告的 greeting、 button 變數在console中也沒出現重複宣告的錯誤。
Content Script 除了不能直接使用頁面中window.xxx
之外,因為安全性考量,在眾多 Chrome API 中使用也有所限制,目前可以直接使用的方法有:
chrome.i18n
storage
chrome.runtime :
connect、
getManifest、
getURL、
id、
onConnect、
onMessage、
sendMessage``關於 Chrome API 方法的使用,因為後續會有獨立文章進行說明,當全系列文章結束後會再添加對應連結,所以在這邊就先不進行說明了
關於 Content Script 注入方式有兩種, 分別是: Declaration Injection
與 Dynamic Injection
關於 Declaration Inject,想必看過前面的篇章中的範例的捧油們,應該很熟悉了。其主要方式就是在 Manifest.json 中提前定義好所要注入網站中執行的程式檔,其中可以包括 Javascript、css檔。
其中 match
欄位為指定此內容腳本將被注入到哪些頁面
,為必填欄位。
run_at
欄位為指定何時將Cotent Script程式 注入於頁面中
,分別有三個選項: document_idle
、 document_start
或 document_end
,
其中"document_idle"
為預設值,同時。
// manifest.json
"content_scripts": [
{
"matches": [
"https://ithelp.ithome.com.tw/users/20139636"
],
"js": [
"/content_script/content.js"
],
"css":[
"/style/content.css"
],
run_at: 'document_start
}
]
相較於前一個靜態注入 Content Scripts。
Dynamic Injection 的使用方式較為 被動, 同常注入Scripts時機為 當特定事件觸發時
假設 當 Background 背景事件 監聽到 使用者點擊了Notification的訊息事件時,想要讓 當前網頁即時跳出Extension 通知視窗時,就可以 Dynamic Injection 方式將Script 注入到當前頁面中,而提前就將通知視窗顯示出來。
使用方式如下:
首先,因為要注入Scripts,所以需請求權限,在 Manifest 的 Permission 中 聲明 scripting
// Manifest.json
{
"permissions": [ "scripting", activeTab, tab],
}
接著 透過chrome.scripting.executeScript
方法將 JavaScript 檔案 注入 到 指定的 TabId中。
關於 Tab API 及 相關監聽事件的用法,在後續Chrome 常見API方法篇 也會介紹到,同樣地後續會再補上連結...
//background.js
chrome.notifications.onClicked.addListener(
const tabId = getTabId();
chrome.scripting.executeScript(
{
target: {tabId: tabId},
files: ['script.js'],
},
() => { ... });
)
除了以檔案方式注入,也可以Functionc方式注入,同時如需要傳遞參數可以args
欄位以Array方式來宣告。
//background.js
function injectedFunction(msg, from) {
// 略..
console.log(msg, from)
}
chrome.notifications.onClicked.addListener(
const tabId = getTabId();
chrome.scripting.executeScript(
{
target: { tabId: tab.id },
matches: ["https://*.nytimes.com/*"],
function: injectedFunction
args:['中秋節快樂!', 'from Winnie']
},
() => { ... });
)
到了這邊,其實在官網文件中還有提供更多 Content Script 注入的方法細節可以使用,但因為內容真的太雜,所以就挑了幾個經常使用到的來進行介紹,如果有興趣的朋友可以再去文件尋寶尋寶
以上就是關於 Content Script 運作與常見應用的介紹,而在下一篇我們將 介紹 Extension中的 UI Popup
那今天文章先到這邊了,謝謝願意花時間看此篇文章的你,如果文章有錯誤的地方,再麻煩不吝嗇的給予指教,感謝!!
今日有感而發:
鐵人賽真的很神奇,讓我感覺每天都有被時間追著跑的感覺
雖然我現在 有點累、有點崩潰、甚至已經不知道後面再打什麼了
但卻沒有想要放棄...才發現原來我是M派啊我說麥當勞好吃的部分
今天想分享一首 -> 如常