# Content Scripts

By default, runs after page has loaded in an isolated world with seperate variables but accessing same DOM

Use messages to access most chrome APIS, but can accessjj:

* [i18n](https://developer.chrome.com/extensions/i18n)
* [storage](https://developer.chrome.com/extensions/storage)
* runtime:
  * [connect](https://developer.chrome.com/extensions/runtime#method-connect)
  * [getManifest](https://developer.chrome.com/extensions/runtime#method-getManifest)
  * [getURL](https://developer.chrome.com/extensions/runtime#method-getURL)
  * [id](https://developer.chrome.com/extensions/runtime#property-id)
  * [onConnect](https://developer.chrome.com/extensions/runtime#event-onConnect)
  * [onMessage](https://developer.chrome.com/extensions/runtime#event-onMessage)
  * [sendMessage](https://developer.chrome.com/extensions/runtime#method-sendMessage)
* [extension](https://developer.chrome.com/extensions/extension) ( [getURL](https://developer.chrome.com/extensions/extension#method-getURL) , [inIncognitoContext](https://developer.chrome.com/extensions/extension#property-inIncognitoContext) , [lastError](https://developer.chrome.com/extensions/extension#property-lastError) , [onRequest](https://developer.chrome.com/extensions/extension#event-onRequest) ,[sendRequest](https://developer.chrome.com/extensions/extension#method-sendRequest) )

## Settings

```javascript
  "content_scripts": [
    {
      "matches": ["http://*.nytimes.com/*"],
      "run_at": "document_idle",
      "js": ["contentScript.js"]
    }
  ],
```

### Run\_at

* `document_idle` ( **default**) - Guaranted to run after DOM is loaded so no needed to wait for window\.onload
* `document_start` - after css, but before any DOM or script is run
* `document_end` - immediately after DOM is complete, but before subresources like images and frames have loaded

There is fancy matching settings and white and black lists

## Orphaned Content Scripts

When you refresh/update the background script, the content scripts on past pages will still be there running code. But, they will not have access to localStorage or be able to message

The best way to check if valid is to try to access localStorage, but can also just ensure the content script only runs code on messages or storage changes

### Injecting Content Script into Active Tab if needed

```javascript
export async function getActiveTab() {
  const tabs = await browser.tabs.query({
    lastFocusedWindow: true,
    active: true
  });
  if (tabs.length === 0) {
    const message = "There is no active tab";
    debug(message);
    throw new Error(message);
  }

  return tabs[0];
}

export async function getValidActiveTab() {
  const activeTab = await getActiveTab();
  const tabId = activeTab.id;

  try {
    await browser.tabs.sendMessage(tabId, { type: C.test });
  } catch (_) {
    try {
      await browser.tabs.executeScript(tabId, {
        file: "build/content.js"
      });
      debug("Injected content script");
    } catch (_) {
      throw new Error(browser.runtime.lastError.message);
    }
  }

  return activeTab;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://openai.gitbook.io/code-cheatsheets/js/all/chrome_plugins/content.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
