說明
使用 chrome.scripting API 在不同情境中執行指令碼。
權限
scripting可用性
資訊清單
如要使用 browser.scripting API,請在資訊清單中宣告 "scripting" 權限,以及要插入指令碼的網頁主機權限。使用 "host_permissions" 鍵或 "activeTab" 權限,授予暫時的主機權限。以下範例使用 activeTab 權限。
{
"name": "Scripting Extension",
"manifest_version": 3,
"permissions": ["scripting", "activeTab"],
...
}
概念和用途
您可以使用 browser.scripting API 將 JavaScript 和 CSS 插入網站。這與內容指令碼的功能類似。不過,透過 browser.scripting 命名空間,擴充功能可以在執行階段做出決策。
插入目標
您可以使用 target 參數,指定要插入 JavaScript 或 CSS 的目標。
唯一的必填欄位是 tabId。根據預設,系統會在指定分頁的主頁框中執行插入作業。
function getTabId() { ... }
browser.scripting
.executeScript({
target : {tabId : getTabId()},
files : [ "script.js" ],
})
.then(() => console.log("script injected"));
如要在指定分頁的所有頁框中執行,請將 allFrames 布林值設為 true。
function getTabId() { ... }
browser.scripting
.executeScript({
target : {tabId : getTabId(), allFrames : true},
files : [ "script.js" ],
})
.then(() => console.log("script injected in all frames"));
您也可以指定個別頁框 ID,將指令碼插入分頁的特定頁框。如要進一步瞭解影格 ID,請參閱 browser.webNavigation API。
function getTabId() { ... }
browser.scripting
.executeScript({
target : {tabId : getTabId(), frameIds : [ frameId1, frameId2 ]},
files : [ "script.js" ],
})
.then(() => console.log("script injected on target frames"));
插入的程式碼
擴充功能可以透過外部檔案或執行階段變數,指定要插入的程式碼。
檔案
檔案會指定為與擴充功能根目錄相關的路徑字串。下列程式碼會將 script.js 檔案插入分頁的主頁框。
function getTabId() { ... }
browser.scripting
.executeScript({
target : {tabId : getTabId()},
files : [ "script.js" ],
})
.then(() => console.log("injected script file"));
執行階段函式
使用 scripting.executeScript() 插入 JavaScript 時,您可以指定要執行的函式,而非檔案。這個函式應為目前擴充功能內容可用的函式變數。
function getTabId() { ... }
function getTitle() { return document.title; }
browser.scripting
.executeScript({
target : {tabId : getTabId()},
func : getTitle,
})
.then(() => console.log("injected a function"));
function getTabId() { ... }
function getUserColor() { ... }
function changeBackgroundColor() {
document.body.style.backgroundColor = getUserColor();
}
browser.scripting
.executeScript({
target : {tabId : getTabId()},
func : changeBackgroundColor,
})
.then(() => console.log("injected a function"));
如要解決這個問題,請使用 args 屬性:
function getTabId() { ... }
function getUserColor() { ... }
function changeBackgroundColor(backgroundColor) {
document.body.style.backgroundColor = backgroundColor;
}
browser.scripting
.executeScript({
target : {tabId : getTabId()},
func : changeBackgroundColor,
args : [ getUserColor() ],
})
.then(() => console.log("injected a function"));
執行階段字串
如果在網頁中插入 CSS,也可以指定要在 css 屬性中使用的字串。這個選項僅適用於 scripting.insertCSS(),您無法使用 scripting.executeScript() 執行字串。
function getTabId() { ... }
const css = "body { background-color: red; }";
browser.scripting
.insertCSS({
target : {tabId : getTabId()},
css : css,
})
.then(() => console.log("CSS injected"));
處理結果
JavaScript 的執行結果會傳遞至擴充功能。每個影格都包含單一結果。主頁框保證是結果陣列中的第一個索引;所有其他頁框則以非確定性順序排列。
function getTabId() { ... }
function getTitle() { return document.title; }
browser.scripting
.executeScript({
target : {tabId : getTabId(), allFrames : true},
func : getTitle,
})
.then(injectionResults => {
for (const {frameId, result} of injectionResults) {
console.log(`Frame ${frameId} result:`, result);
}
});
scripting.insertCSS() 不會傳回任何結果。
Promise
如果指令碼執行結果的值是 Promise,Chrome 會等待 Promise 解決並傳回結果值。
function getTabId() { ... }
async function addIframe() {
const iframe = document.createElement("iframe");
const loadComplete =
new Promise(resolve => iframe.addEventListener("load", resolve));
iframe.src = "https://example.com";
document.body.appendChild(iframe);
await loadComplete;
return iframe.contentWindow.document.title;
}
browser.scripting
.executeScript({
target : {tabId : getTabId(), allFrames : true},
func : addIframe,
})
.then(injectionResults => {
for (const frameResult of injectionResults) {
const {frameId, result} = frameResult;
console.log(`Frame ${frameId} result:`, result);
}
});
範例
取消註冊所有動態內容指令碼
下列程式碼片段包含一個函式,可取消註冊擴充功能先前註冊的所有動態內容指令碼。
async function unregisterAllDynamicContentScripts() {
try {
const scripts = await browser.scripting.getRegisteredContentScripts();
const scriptIds = scripts.map(script => script.id);
return browser.scripting.unregisterContentScripts({ ids: scriptIds });
} catch (error) {
const message = [
"An unexpected error occurred while",
"unregistering dynamic content scripts.",
].join(" ");
throw new Error(message, {cause : error});
}
}
如要試用 browser.scripting API,請從 Chrome 擴充功能範例存放區安裝指令碼範例。
類型
ContentScriptFilter
屬性
-
ids
string[] 選填
如果指定,
getRegisteredContentScripts只會傳回 ID 在這份清單中的指令碼。
CSSInjection
屬性
-
CSS
字串 選填
包含要插入 CSS 的字串。必須指定
files或css其中之一。 -
檔案
string[] 選填
要插入的 CSS 檔案路徑 (相對於擴充功能的根目錄)。必須指定
files或css其中之一。 -
origin
StyleOrigin 選用
插入的樣式來源。預設值為
'AUTHOR'。 -
指定要插入 CSS 的目標詳細資料。
ExecutionWorld
指令碼執行的 JavaScript 環境。
列舉
「ISOLATED」
指定隔離環境,也就是這個擴充功能專屬的執行環境。
"MAIN"
指定 DOM 的主要環境,也就是與主機網頁 JavaScript 共用的執行環境。
InjectionResult
屬性
-
documentId
字串
Chrome 106 以上版本 Chrome 148 起為 browser.*與插入作業相關聯的文件。
-
frameId
數字
Chrome 90 以上版本 瀏覽器 (自 Chrome 148 起)與插入相關聯的框架。
-
結果
任意 選填
指令碼執行結果。
InjectionTarget
屬性
RegisteredContentScript
屬性
-
allFrames
布林值 選填
如果指定為 true,則會插入所有頁框,即使該頁框不是分頁中最上層的頁框也一樣。系統會獨立檢查每個框架是否符合網址規定,如果不符合,就不會插入子框架。預設值為 false,表示只會比對頂層頁框。
-
CSS
string[] 選填
要插入有相符圖像的網頁的 CSS 檔案清單。系統會按照這些指令碼在這個陣列中出現的順序,在網頁建構或顯示任何 DOM 之前,將指令碼插入網頁。
-
excludeMatches
string[] 選填
排除原本會插入這個內容指令碼的網頁。如要進一步瞭解這些字串的語法,請參閱「比對模式」。
-
id
字串
在 API 呼叫中指定的內容指令碼 ID。開頭不得為「_」,因為這是產生的指令碼 ID 預留前置字元。
-
js
string[] 選填
要插入有相符圖像的網頁的 JavaScript 檔案清單。系統會按照這些指令碼在陣列中的顯示順序,依序插入指令碼。
-
matchOriginAsFallback
布林值 選填
Chrome 119 以上版本 Chrome 148 以上版本的 browser.*指出指令碼是否可插入網址含有不支援配置的頁框,具體來說是 about:、data:、blob: 或 filesystem:。在這種情況下,系統會檢查網址來源,判斷是否應插入指令碼。如果來源是
null(例如 data: 網址),則使用的來源是建立目前頁框的頁框,或是啟動導覽至這個頁框的頁框。請注意,這可能不是父項頁框。 -
完全相符
string[] 選填
指定要將這個內容指令碼插入哪些網頁。如要進一步瞭解這些字串的語法,請參閱「比對模式」。必須為
registerContentScripts指定。 -
persistAcrossSessions
布林值 選填
指定這個內容指令碼是否會保留到日後的工作階段。預設值為 true。
-
runAt
RunAt 選填
指定將 JavaScript 檔案插入網頁的時間。建議使用預設值
document_idle。 -
世界Chrome 102+ 瀏覽器。* 自 Chrome 148 起
執行指令碼的 JavaScript「世界」。預設值為
ISOLATED。
ScriptInjection
屬性
-
args
any[] 選填
Chrome 92 以上版本 瀏覽器。*自 Chrome 148 起要傳遞至指定函式的引數。只有在指定
func參數時,這個值才有效。這些引數必須可序列化為 JSON。 -
檔案
string[] 選填
要插入的 JS 或 CSS 檔案路徑,相對於擴充功能的根目錄。必須明確指定
files或func。 -
injectImmediately
布林值 選填
Chrome 102+ 瀏覽器。* 自 Chrome 148 起是否應盡快在目標中觸發注入。請注意,這不保證指令碼會在載入網頁前插入,因為指令碼到達目標時,網頁可能已經載入。
-
指定要插入指令碼的目標詳細資料。
-
世界Chrome 95 以上版本 Chrome 148 以上版本的瀏覽器*
執行指令碼的 JavaScript「世界」。預設值為
ISOLATED。 -
func
void 選填
Chrome 92 以上版本 瀏覽器。*自 Chrome 148 起要插入的 JavaScript 函式。這個函式會先序列化,然後反序列化以便插入。這表示所有繫結參數和執行內容都會遺失。必須明確指定
files或func。func函式如下所示:() => {...}
StyleOrigin
樣式變更的來源。詳情請參閱樣式來源。
列舉
"AUTHOR"
"USER"
方法
executeScript()
browser.scripting.executeScript(
injection: ScriptInjection,
): Promise<InjectionResult[]>
將指令碼插入目標結構定義。根據預設,系統會在 document_idle 執行指令碼,如果網頁已載入,則會立即執行。如果設定 injectImmediately 屬性,即使網頁尚未載入完成,指令碼也會直接插入,不會等待。如果指令碼評估為 Promise,瀏覽器會等待 Promise 解決並傳回結果值。
參數
-
注射避孕針
要插入的指令碼詳細資料。
傳回
-
Promise<InjectionResult[]>
Chrome 90 以上版本 瀏覽器 (自 Chrome 148 起)傳回 Promise,在插入完成時解析。產生的陣列包含每個成功插入的頁框的執行結果。
getRegisteredContentScripts()
browser.scripting.getRegisteredContentScripts(
filter?: ContentScriptFilter,
): Promise<RegisteredContentScript[]>
傳回這項擴充功能中,符合指定篩選條件的所有動態註冊內容指令碼。
參數
-
篩選器
用於篩選擴充功能動態註冊指令碼的物件。
傳回
-
Promise<RegisteredContentScript[]>
insertCSS()
browser.scripting.insertCSS(
injection: CSSInjection,
): Promise<void>
將 CSS 樣式表插入目標情境。如果指定多個頁框,系統會忽略插入失敗的頁框。
參數
-
注射避孕針
要插入的樣式詳細資料。
傳回
-
承諾<void>
Chrome 90 以上版本 瀏覽器 (自 Chrome 148 起)傳回 Promise,在插入完成時解析。
registerContentScripts()
browser.scripting.registerContentScripts(
scripts: RegisteredContentScript[],
): Promise<void>
為這個擴充功能註冊一或多個內容指令碼。
參數
-
指令碼
包含要註冊的指令碼清單。如果指令碼剖析/檔案驗證期間發生錯誤,或指定的 ID 已存在,則不會註冊任何指令碼。
傳回
-
承諾<void>
傳回 Promise,在指令碼完整註冊後解析,或在發生錯誤時拒絕。
removeCSS()
browser.scripting.removeCSS(
injection: CSSInjection,
): Promise<void>
從目標情境中移除這個擴充功能先前插入的 CSS 樣式表。
參數
-
注射避孕針
要移除的樣式詳細資料。請注意,
css、files和origin屬性必須與透過insertCSS插入的樣式表完全相符。嘗試移除不存在的樣式表不會有任何作用。
傳回
-
承諾<void>
傳回 Promise,在移除完成時解析。
unregisterContentScripts()
browser.scripting.unregisterContentScripts(
filter?: ContentScriptFilter,
): Promise<void>
取消註冊這項擴充功能的內容指令碼。
參數
-
篩選器
如果指定,則只會取消註冊符合篩選條件的動態內容指令碼。否則,系統會取消註冊擴充功能的所有動態內容指令碼。
傳回
-
承諾<void>
傳回 Promise,在指令碼取消註冊後解析,或在發生錯誤時拒絕。
updateContentScripts()
browser.scripting.updateContentScripts(
scripts: RegisteredContentScript[],
): Promise<void>
更新這個擴充功能的一或多個內容指令碼。
參數
-
指令碼
包含要更新的指令碼清單。只有在這個物件中指定的屬性,才會在現有指令碼中更新。如果指令碼剖析/檔案驗證期間發生錯誤,或指定的 ID 未對應至完整註冊的指令碼,則不會更新任何指令碼。
傳回
-
承諾<void>
傳回 Promise,在指令碼更新後解析,或在發生錯誤時拒絕。