Problem: extension pages (popup, options, background page in MV2, etc.) are separate from the web page and they have their own DOM, document
, window
, and a chrome-extension://
URL.
- Note that service worker doesn't have any DOM/document/window at all.
- To inspect each context of the extension use its own devtools.
Solution: use a content script to access the web page or interact with its contents.
- Content scripts execute in the web page, not in the extension.
- Content scripts are isolated by default, see how to run code in page context (aka MAIN world).
- Don't load your content scripts in the extension page.
Method 1. Declarative
manifest.json:
"content_scripts": [{
"matches": ["*://*.example.com/*"],
"js": ["contentScript.js"]
}],
It will run once when the page loads. After that happens, use messaging .
Warning! It can't send DOM elements, Map, Set, ArrayBuffer, classes, functions, and so on. It can only send JSON-compatible simple objects and types so you'll need to manually extract the required data and pass it as a simple array or object.
Method 2. Programmatic
ManifestV3:
Use chrome.scripting.executeScript in the extension script (like the popup) to inject a content script/function into a tab on demand.
The result of this method is the last expression in the content script so it can be used to extract data. Data must be JSON-compatible, see the warning above.
Required permissions
in manifest.json:
"scripting"
- mandatory;
"activeTab"
- ideal scenario, suitable for a response to a user action (usually a click on the extension icon in the toolbar). Doesn't show any permission warning when installing the extension.
If ideal scenario is impossible add the allowed sites to host_permissions
in manifest.json:
ManifestV2 differences to the above: