chrome.scripting (original) (raw)

说明

使用 chrome.scripting API 在不同上下文中执行脚本。

权限

scripting

可用性

Chrome 88 及更高版本MV3 及更高版本

清单

如需使用 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({ ids: 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

属性

CSSInjection

属性

ExecutionWorld

脚本要在其中执行的 JavaScript 世界。

枚举

“ISOLATED”
指定隔离的世界,即此扩展程序独有的执行环境。

“MAIN”
指定 DOM 的主要世界,即与宿主网页的 JavaScript 共享的执行环境。

InjectionResult

属性

InjectionTarget

属性

RegisteredContentScript

属性

ScriptInjection

属性

StyleOrigin

样式更改的来源。如需了解详情,请参阅样式来源

枚举

方法

executeScript()

chrome.scripting.executeScript(
  injection: ScriptInjection,
): Promise<InjectionResult[]>

将脚本注入到目标上下文。默认情况下,脚本将在 document_idle 运行,如果网页已加载,则立即运行。如果设置了 injectImmediately 属性,即使网页尚未完成加载,脚本也会立即注入。如果脚本的评估结果为 promise,浏览器将等待 promise 确定,然后返回结果值。

返回

getRegisteredContentScripts()

chrome.scripting.getRegisteredContentScripts(
  filter?: ContentScriptFilter,
): Promise<RegisteredContentScript[]>

返回此扩展程序的所有与指定过滤条件匹配的动态注册的内容脚本。

返回

insertCSS()

chrome.scripting.insertCSS(
  injection: CSSInjection,
): Promise

将 CSS 样式表插入到目标上下文中。如果指定了多个帧,系统会忽略注入失败的情况。

返回

registerContentScripts()

chrome.scripting.registerContentScripts(
  scripts: RegisteredContentScript[],
): Promise

为相应扩展程序注册一个或多个内容脚本。

参数

返回

removeCSS()

chrome.scripting.removeCSS(
  injection: CSSInjection,
): Promise

从目标上下文中移除之前由相应扩展程序插入的 CSS 样式表。

参数

返回

unregisterContentScripts()

chrome.scripting.unregisterContentScripts(
  filter?: ContentScriptFilter,
): Promise

取消注册相应扩展程序的内容脚本。

参数

返回

updateContentScripts()

chrome.scripting.updateContentScripts(
  scripts: RegisteredContentScript[],
): Promise

更新相应扩展程序的一个或多个内容脚本。

参数

返回