chrome.scripting (original) (raw)

Description

Use the chrome.scripting API to execute script in different contexts.

Permissions

scripting

Availability

Manifest

To use the chrome.scripting API, declare the "scripting" permission in the manifest plus the host permissions for the pages to inject scripts into. Use the "host_permissions" key or the "activeTab" permission, which grants temporary host permissions. The following example uses the activeTab permission.

{
  "name": "Scripting Extension",
  "manifest_version": 3,
  "permissions": ["scripting", "activeTab"],
  ...
}

Concepts and usage

You can use the chrome.scripting API to inject JavaScript and CSS into websites. This is similar to what you can do with content scripts. But by using the chrome.scripting namespace, extensions can make decisions at runtime.

Injection targets

You can use the target parameter to specify a target to inject JavaScript or CSS into.

The only required field is tabId. By default, an injection will run in the main frame of the specified tab.

function getTabId() { ... }

chrome.scripting
    .executeScript({
      target : {tabId : getTabId()},
      files : [ "script.js" ],
    })
    .then(() => console.log("script injected"));

To run in all frames of the specified tab, you can set the allFrames boolean to true.

function getTabId() { ... }

chrome.scripting
    .executeScript({
      target : {tabId : getTabId(), allFrames : true},
      files : [ "script.js" ],
    })
    .then(() => console.log("script injected in all frames"));

You can also inject into specific frames of a tab by specifying individual frame IDs. For more information on frame IDs, see the chrome.webNavigationAPI.

function getTabId() { ... }

chrome.scripting
    .executeScript({
      target : {tabId : getTabId(), frameIds : [ frameId1, frameId2 ]},
      files : [ "script.js" ],
    })
    .then(() => console.log("script injected on target frames"));

Injected code

Extensions can specify the code to be injected either via an external file or a runtime variable.

Files

Files are specified as strings that are paths relative to the extension's root directory. The following code will inject the file script.js into the main frame of the tab.

function getTabId() { ... }

chrome.scripting
    .executeScript({
      target : {tabId : getTabId()},
      files : [ "script.js" ],
    })
    .then(() => console.log("injected script file"));

Runtime functions

When injecting JavaScript with scripting.executeScript(), you can specify a function to be executed instead of a file. This function should be a function variable available to the current extension context.

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"));

You can work around this by using the args property:

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"));

Runtime strings

If injecting CSS within a page, you can also specify a string to be used in thecss property. This option is only available for scripting.insertCSS(); you can't execute a string using scripting.executeScript().

function getTabId() { ... }
const css = "body { background-color: red; }";

chrome.scripting
    .insertCSS({
      target : {tabId : getTabId()},
      css : css,
    })
    .then(() => console.log("CSS injected"));

Handle the results

The results of executing JavaScript are passed to the extension. A single result is included per-frame. The main frame is guaranteed to be the first index in the resulting array; all other frames are in a non-deterministic order.

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() does not return any results.

Promises

If the resulting value of the script execution is a promise, Chrome will wait for the promise to settle and return the resulting value.

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);
      }
    });

Examples

Unregister all dynamic content scripts

The following snippet contains a function that unregisters all dynamic content scripts the extension has previously registered.

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});
  }
}

To try the chrome.scripting API, install the scripting sample from the Chrome extension samplesrepository.

Types

ContentScriptFilter

Properties

CSSInjection

Properties

ExecutionWorld

The JavaScript world for a script to execute within.

Enum

"ISOLATED"
Specifies the isolated world, which is the execution environment unique to this extension.

"MAIN"
Specifies the main world of the DOM, which is the execution environment shared with the host page's JavaScript.

InjectionResult

Properties

InjectionTarget

Properties

RegisteredContentScript

Properties

ScriptInjection

Properties

StyleOrigin

The origin for a style change. See style origins for more info.

Enum

Methods

executeScript()

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

Injects a script into a target context. By default, the script will be run at document_idle, or immediately if the page has already loaded. If the injectImmediately property is set, the script will inject without waiting, even if the page has not finished loading. If the script evaluates to a promise, the browser will wait for the promise to settle and return the resulting value.

Parameters

Returns

getRegisteredContentScripts()

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

Returns all dynamically registered content scripts for this extension that match the given filter.

Parameters

Returns

insertCSS()

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

Inserts a CSS stylesheet into a target context. If multiple frames are specified, unsuccessful injections are ignored.

Parameters

Returns

registerContentScripts()

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

Registers one or more content scripts for this extension.

Parameters

Returns

removeCSS()

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

Removes a CSS stylesheet that was previously inserted by this extension from a target context.

Parameters

Returns

unregisterContentScripts()

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

Unregisters content scripts for this extension.

Parameters

Returns

updateContentScripts()

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

Updates one or more content scripts for this extension.

Parameters

Returns