scripting.executeScript()

将脚本注入目标上下文。默认情况下脚本将在 document_idle 时运行。

备注: 此方法在 Chrome 和 Firefox 101 的 Manifest V3 或更高版本中可用。在 Safari 和 Firefox 102+ 中,此方法也在 Manifest V2 中可用。

使用此 API 必须拥有 "scripting" 权限以及目标 URL 的权限,权限可以是明确的主机权限或使用 activeTab 权限。需要注意,部分特殊页面(包括阅读模式、查看源代码和 PDF 查看器页面)不支持该权限。

在 Firefox 和 Safari 中,缺少部分主机权限也会导致执行成功(这一部分的结果会包含在兑现的 Promise 中)。在 Chrome 中,缺少任意一个权限都会导致执行被阻止(参见 Issue 1325114)。

注入的脚本被称为内容脚本

这是一个返回 Promise 的异步函数。

语法

js
let results = await browser.scripting.executeScript(
  details             // 对象
)

参数

details

描述注入脚本的对象,包含以下属性:

args 可选

传递到函数中的参数数组,仅在指定了 func 参数时有效。参数必须是可 JSON 序列化的。

files 可选

stringarray。要注入的 JavaScript 文件相对于扩展的根目录的路径的数组。必须指定 filesfunc 其中之一。

func 可选

function。要注入的 JavaScript 函数。该函数将被序列化、反序列化以注入,因此任何绑定在函数上的参数和函数的执行上下文都将被丢失。必须指定 filesfunc 其中之一。

injectImmediately 可选

boolean。注入目标是否尽早触发注入(但不一定在页面加载之前)。

target

scripting.InjectionTarget。指定脚本注入目标的详细信息。

world 可选

scripting.ExecutionWorld。脚本执行的环境。

返回值

Promise,将以 InjectionResult 对象数组兑现,表示在每个注入框架中注入脚本的结果。

如果注入失败(例如注入目标无效)则该 Promise 将被拒绝。当脚本执行开始时,无论成功与否(resulterror),脚本的结果将包含在结果中。

每个 InjectionResult 对象具有以下属性:

frameId

number。与注入相关联的框架 ID。

result 可选

any。脚本执行的结果。

error 可选

any。如果发生错误,包含脚本抛出或拒绝的值。通常这是一个带有消息(message)属性的错误对象,但它可以是任何值(包括原始值和 undefined)。

Chrome 尚不支持 error 属性(参见 Issue 1271527: Propagate errors from scripting.executeScript to InjectionResult)。作为替代,可以通过将要执行的代码包装在 try-catch 语句中来捕获运行时错误。未捕获的错误也会报告到目标标签页的控制台。

脚本的结果是最后一条执行的语句,类似于在 Web 控制台中执行脚本时看到的结果(不包括任何 console.log() 输出)。例如,考虑这样的脚本:

js
let foo = "my result";
foo;

在该示例中,结果数组中将包含一个元素:字符串 "my result"

在 Firefox 中脚本的结果必须是一个可结构化克隆的值,而在 Chrome 中必须是一个可 JSON 序列化的值。Chrome 不兼容情况一文中的数据克隆算法部分更详细地讨论了这种差异。

示例

以下示例在活动标签页中执行一行代码:

js
browser.action.onClicked.addListener(async (tab) => {
  try {
    await browser.scripting.executeScript({
      target: {
        tabId: tab.id,
      },
      func: () => {
        document.body.style.border = "5px solid green";
      },
    });
  } catch (err) {
    console.error(`无法执行脚本:${err}`);
  }
});

以下示例执行一个名为 "content-script.js" 的脚本文件(随扩展一起打包)。脚本在活动标签页中(包括子框架和主文档)执行:

js
browser.action.onClicked.addListener(async (tab) => {
  try {
    await browser.scripting.executeScript({
      target: {
        tabId: tab.id,
        allFrames: true,
      },
      files: ["content-script.js"],
    });
  } catch (err) {
    console.error(`无法执行脚本:${err}`);
  }
});

浏览器兼容性

备注: 此 API 基于 Chromium 的 chrome.scripting API。