Search code examples
google-chromegoogle-chrome-extension

Accessing `window`/DOM/HTML of the webpage from the extension


I'm writing a Chrome extension and trying to overlay a <div> over the current webpage as soon as a button is clicked in the popup.html file.

When I access the document.body.insertBefore method from within popup.html it overlays the <div> on the popup, rather than the current webpage.

Do I have to use messaging between background.html and popup.html in order to access the web page's DOM? I would like to do everything in popup.html, and to use jQuery too, if possible.


Solution

  • Your code doesn't run in the context of the web page, but in an extension context (popup, options, background script/page, etc.), which similarly to a separate browser tab has its own DOM, document, window, and a chrome-extension:// URL.

    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.
    • To inspect each context of the extension use its own devtools.

    Method 1. Declarative

    manifest.json:

    "content_scripts": [{
      "matches": ["*://*.example.com/*"],
      "js": ["contentScript.js"]
    }],
    

    It will run automatically when the page loads. After that happens, use messaging .

    ⚠️ Messaging in Chrome doesn't support 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.

    ⚠️ You'll need to re-inject content scripts after reloading/installing the extension.

    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:

      • "*://*.example.com/" plus any other sites you want.

      • "<all_urls>" or "*://*/" these will put your extension in a super slow review queue in the Chrome Web Store because of broad host permissions.

    • ManifestV2 differences to the above:

      • Use chrome.tabs.executeScript instead of chrome.scripting.executeScript.
      • Specify sites or "activeTab" in "permissions", no need for "scripting".