说明
使用 chrome.scripting
API 在不同上下文中执行脚本。
权限
scripting
可用性
清单
如需使用 chrome.scripting
API,请在清单中声明 "scripting"
权限,以及要将脚本注入的网页的主机权限。使用 "host_permissions"
键或 "activeTab"
权限(用于授予临时主机权限)。以下示例使用 activeTab 权限。
{
"name": "Scripting Extension",
"manifest_version": 3,
"permissions": ["scripting", "activeTab"],
...
}
概念和用法
您可以使用 chrome.scripting
API 将 JavaScript 和 CSS 注入网站。这与使用内容脚本执行的操作类似。不过,通过使用 chrome.scripting
命名空间,扩展程序可以在运行时做出决策。
注入目标
您可以使用 target
参数指定要向其注入 JavaScript 或 CSS 的目标。
唯一的必填字段是 tabId
。默认情况下,注入将在指定标签页的主框架中运行。
function getTabId() { ... }
chrome.scripting
.executeScript({
target : {tabId : getTabId()},
files : [ "script.js" ],
})
.then(() => console.log("script injected"));
若要在指定标签页的所有帧中运行,您可以将 allFrames
布尔值设置为 true
。
function getTabId() { ... }
chrome.scripting
.executeScript({
target : {tabId : getTabId(), allFrames : true},
files : [ "script.js" ],
})
.then(() => console.log("script injected in all frames"));
您还可以通过指定各个帧 ID 来注入标签页的特定帧。如需详细了解帧 ID,请参阅 chrome.webNavigation
API。
function getTabId() { ... }
chrome.scripting
.executeScript({
target : {tabId : getTabId(), frameIds : [ frameId1, frameId2 ]},
files : [ "script.js" ],
})
.then(() => console.log("script injected on target frames"));
注入的代码
扩展程序可以通过外部文件或运行时变量指定要注入的代码。
文件
文件指定为相对于扩展程序根目录的路径的字符串。以下代码会将文件 script.js
注入标签页的主框架。
function getTabId() { ... }
chrome.scripting
.executeScript({
target : {tabId : getTabId()},
files : [ "script.js" ],
})
.then(() => console.log("injected script file"));
运行时函数
使用 scripting.executeScript()
注入 JavaScript 时,可以指定要执行的函数而不是文件。此函数应该是可供当前扩展程序上下文使用的函数变量。
function getTabId() { ... }
function getTitle() { return document.title; }
chrome.scripting
.executeScript({
target : {tabId : getTabId()},
func : getTitle,
})
.then(() => console.log("injected a function"));
function getTabId() { ... }
function getUserColor() { ... }
function changeBackgroundColor() {
document.body.style.backgroundColor = getUserColor();
}
chrome.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;
}
chrome.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; }";
chrome.scripting
.insertCSS({
target : {tabId : getTabId()},
css : css,
})
.then(() => console.log("CSS injected"));
处理结果
执行 JavaScript 的结果会传递给扩展程序。每帧包含一个结果。主帧一定是所生成数组中的第一个索引;所有其他帧则以不确定的顺序排列。
function getTabId() { ... }
function getTitle() { return document.title; }
chrome.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;
}
chrome.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 chrome.scripting.getRegisteredContentScripts();
const scriptIds = scripts.map(script => script.id);
return chrome.scripting.unregisterContentScripts(scriptIds);
} catch (error) {
const message = [
"An unexpected error occurred while",
"unregistering dynamic content scripts.",
].join(" ");
throw new Error(message, {cause : error});
}
}
如需试用 chrome.scripting
API,请从 Chrome 扩展程序示例代码库中安装脚本示例。
类型
ContentScriptFilter
属性
-
ids
string[] 可选
如果指定,
getRegisteredContentScripts
将仅返回具有此列表中指定的 ID 的脚本。
CSSInjection
属性
-
css
字符串(可选)
包含要注入的 CSS 的字符串。必须指定
files
和css
中的一个。 -
文件
string[] 可选
要注入的 CSS 文件的路径(相对于扩展程序的根目录)。必须指定
files
和css
中的一个。 -
发迹地
StyleOrigin 可选
注入的样式来源。默认为
'AUTHOR'
。 -
用于指定要在其中插入 CSS 的目标的详细信息。
ExecutionWorld
用于执行脚本的 JavaScript 环境。
枚举
"ISOLATED"
指定隔离环境,即此扩展程序独有的执行环境。
"MAIN"
指定 DOM 的主域,即与托管网页的 JavaScript 共享的执行环境。
InjectionResult
属性
-
documentId
string
Chrome 106 及更高版本与注入关联的文档。
-
frameId
number
Chrome 90 及更高版本与注入关联的帧。
-
结果
任意(可选)
脚本执行的结果。
InjectionTarget
属性
RegisteredContentScript
属性
-
allFrames
布尔值 选填
如果指定为 true,该帧会注入到所有帧中,即使该帧不是标签页中最顶层的帧也是如此。系统会分别检查每个帧是否符合网址要求;如果不符合网址要求,帧将不会注入到子框架中。默认值为 false,表示仅匹配上层帧。
-
css
string[] 可选
要注入到匹配页面的 CSS 文件列表。这些元素会按照它们在此数组中出现的顺序进行注入,然后再为网页构建或显示任何 DOM。
-
excludeMatches
string[] 可选
不包括此内容脚本本应注入的网页。要详细了解这些字符串的语法,请参阅匹配模式。
-
id
string
在 API 调用中指定的内容脚本的 ID。不得以“_”开头,因为它会预留为生成的脚本 ID 的前缀。
-
js
string[] 可选
要注入到匹配页面的 JavaScript 文件的列表。这些变量会按照它们在此数组中出现的顺序进行注入。
-
matchOriginAsFallback
布尔值 选填
Chrome 119 及更高版本指明脚本是否可注入到网址包含不受支持的架构的帧中,具体来说就是:about:、data:、blob: 或 filesystem:。在这些情况下,系统会检查网址的来源,以确定是否应注入脚本。如果源是
null
(如 data: 网址一样),则使用的来源是创建当前帧的帧或启动到此帧的导航的帧。请注意,该框架可能不是父框架。 -
匹配
string[] 可选
指定要将此内容脚本注入哪些网页。要详细了解这些字符串的语法,请参阅匹配模式。必须为
registerContentScripts
指定。 -
persistAcrossSessions
布尔值 选填
指定此内容脚本是否将在以后的会话中持续存在。默认值为 true。
-
runAt
RunAt 可选
指定何时将 JavaScript 文件注入网页。首选值为
document_idle
。 -
全球
ExecutionWorld(可选)
Chrome 102 及更高版本用于运行脚本的 JavaScript“世界”。默认为
ISOLATED
。
ScriptInjection
属性
-
args
any[] 可选属性
Chrome 92 及更高版本要传递给所提供函数的参数。仅当指定了
func
参数时,此字段才有效。这些参数必须可进行 JSON 序列化。 -
文件
string[] 可选
要注入的 JS 或 CSS 文件的路径(相对于扩展程序的根目录)。必须指定
files
和func
中的一个。 -
injectImmediately
布尔值 选填
Chrome 102 及更高版本是否应尽快在目标中触发注入。请注意,这并不能保证注入一定会在网页加载之前发生,因为在脚本到达目标时,该网页可能已加载完毕。
-
用于指定要将脚本注入到的目标的详细信息。
-
全球
ExecutionWorld(可选)
Chrome 95 及更高版本用于运行脚本的 JavaScript“世界”。默认为
ISOLATED
。 -
func
void 可选属性
Chrome 92 及更高版本要注入的 JavaScript 函数。此函数将序列化,然后反序列化进行注入。这意味着,所有绑定的参数和执行上下文都将丢失。必须指定
files
和func
中的一个。func
函数如下所示:() => {...}
StyleOrigin
样式更改的来源。如需了解详情,请参阅样式源。
枚举
方法
executeScript()
chrome.scripting.executeScript(
injection: ScriptInjection,
callback?: function,
)
将脚本注入目标上下文。默认情况下,脚本将在 document_idle
运行,如果页面已加载,则立即运行。如果设置了 injectImmediately
属性,脚本将无需等待即可注入,即使页面尚未加载完毕也是如此。如果脚本的计算结果是一个 promise,则浏览器将等待该 promise 产生结果并返回结果值。
参数
-
要注入的脚本的详细信息。
-
callback
函数(可选)
callback
参数如下所示:(results: InjectionResult[]) => void
-
结果
-
返回
-
Promise<InjectionResult[]>
Chrome 90 及更高版本Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。
getRegisteredContentScripts()
chrome.scripting.getRegisteredContentScripts(
filter?: ContentScriptFilter,
callback?: function,
)
返回此扩展程序中与指定过滤器匹配的所有动态注册的内容脚本。
参数
-
filter
用于过滤扩展程序动态注册的脚本的对象。
-
callback
函数(可选)
callback
参数如下所示:(scripts: RegisteredContentScript[]) => void
返回
-
Promise<RegisteredContentScript[]>
Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。
insertCSS()
chrome.scripting.insertCSS(
injection: CSSInjection,
callback?: function,
)
向目标上下文中插入 CSS 样式表。如果指定了多个帧,系统会忽略不成功的注入。
参数
-
注入
要插入的样式的详细信息。
-
callback
函数(可选)
callback
参数如下所示:() => void
返回
-
Promise<void>
Chrome 90 及更高版本Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。
registerContentScripts()
chrome.scripting.registerContentScripts(
scripts: RegisteredContentScript[],
callback?: function,
)
用于为此扩展程序注册一个或多个内容脚本。
参数
-
包含要注册的脚本列表。如果在脚本解析/文件验证过程中出错,或者指定的 ID 已存在,则表示未注册任何脚本。
-
callback
函数(可选)
callback
参数如下所示:() => void
返回
-
Promise<void>
Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。
removeCSS()
chrome.scripting.removeCSS(
injection: CSSInjection,
callback?: function,
)
从目标上下文中移除此扩展程序之前插入的 CSS 样式表。
参数
-
注入
要移除的样式的详细信息。请注意,
css
、files
和origin
属性必须与通过insertCSS
插入的样式表完全匹配。尝试删除不存在的样式表的操作是空操作。 -
callback
函数(可选)
callback
参数如下所示:() => void
返回
-
Promise<void>
Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。
unregisterContentScripts()
chrome.scripting.unregisterContentScripts(
filter?: ContentScriptFilter,
callback?: function,
)
为此扩展程序取消注册内容脚本。
参数
-
filter
如果指定,则仅取消注册与过滤条件匹配的动态内容脚本。否则,该扩展程序的所有动态内容脚本都会被取消注册。
-
callback
函数(可选)
callback
参数如下所示:() => void
返回
-
Promise<void>
Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。
updateContentScripts()
chrome.scripting.updateContentScripts(
scripts: RegisteredContentScript[],
callback?: function,
)
更新此扩展程序的一个或多个内容脚本。
参数
-
包含要更新的脚本列表。仅当在此对象中指定了现有脚本的属性时,系统才会更新该属性。如果脚本解析/文件验证过程中出错,或者指定的 ID 与完全注册的脚本不对应,则系统不会更新任何脚本。
-
callback
函数(可选)
callback
参数如下所示:() => void
返回
-
Promise<void>
Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。