9

I'm following the tutorial: https://alligator.io/web-components/composing-slots-named-slots/

I'm following the advice: How to append a HTML markup via Chrome Extension without leaking styles of the host page to the appended element?

For some reason getting an error:

window.customElements.define('my-info-box', MyInfoBox);

myScript.js:82 Uncaught TypeError: Cannot read property 'define' of null

Depending on whether I set breakpoint or not it behaves differently: https://en.wikipedia.org/wiki/Heisenbug

Do you happen to know?

I thought it could be timing issues so tried setTimeout as well as document.addEventListener('DOMContentLoaded', fireContentLoadedEvent); and doing the magic in the callback...




Video explanation: https://youtu.be/hpvRIlBtkEE

Extension code

  let shadowDomMarkup = 
  `
    <my-info-box>
      <span slot="top">I'm in the shadow DOM injected by extension</span>
    </my-info-box>
  `;

  $(shadowDomMarkup).prependTo("body");

  (function() {
    const template = document.createElement('template');

    template.innerHTML = `
      <style>
        :host {
          display: block;
          background: red;
          border: 10px dashed black;
        }
      </style>

      <div>
        <slot name="top"></slot>
      </div>
    `;

    class MyInfoBox extends HTMLElement {
      constructor() {
        super();

        this.attachShadow({ mode: 'open' });
        this.shadowRoot.appendChild(template.content.cloneNode(true));
      }
    }

    window.customElements.define('my-info-box', MyInfoBox);

  })();

Messy manifest (a lot of experimentation):

{
  "name": "Getting Started Example",
  "version": "1.0",
  "description": "Build an Extension!",
  "manifest_version": 2,
  "permissions": ["activeTab", "declarativeContent", "storage"],
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },

  "options_page": "options.html",
  "page_action": {
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["zepto.min.js", "angular.js", "angular-route.js", "myScript.js"],
      "css": ["styles.css"],
      "run_at": "document_start"
    }
  ],
  "web_accessible_resources": [
    "iframed.html"
  ],
  "content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
}
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
Mars Robertson
  • 12,673
  • 11
  • 68
  • 89
  • I don't think custom elements work in a content script. At least this doesn't seem a good idea as you may break a page that doesn't expect it. I think a better approach is to isolate everything inside an iframe that points to a html page in your extension (see [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources)), there are various tutorials and libraries that facilitate it. – wOxxOm Apr 15 '19 at 09:25
  • 2
    You'll need to use a polyfill. https://stackoverflow.com/q/42800035/4600982 – Supersharp Apr 15 '19 at 17:01
  • 4
    Possible duplicate of [Why can't you create Custom Elements in Chrome Extensions?](https://stackoverflow.com/questions/42800035/why-cant-you-create-custom-elements-in-chrome-extensions) – Intervalia Apr 15 '19 at 17:43
  • @wOxxOm Thanks! I'm happy to confirm it works! `var path = chrome.runtime.getURL("iframed.html"); var iframeMarkup = ""; $(iframeMarkup).prependTo("body");` Now I need to check how does it behave across various CSP... _(websites like Twitter, Google, Facebook, Github normally do not allow other scripts or iframes)_ – Mars Robertson Apr 15 '19 at 17:53
  • iframes that point into extension's web_accessible_resources should be normally exempt from page CSP unless there's a bug in the browser. – wOxxOm Apr 15 '19 at 18:09
  • **This is officially currently not possible in extensions; the devs want feedback on how to resolve namespace clashes.** https://bugs.chromium.org/p/chromium/issues/detail?id=390807 – i336_ Sep 22 '19 at 03:18
  • See also: https://stackoverflow.com/questions/30022350/registering-a-custom-element-from-a-chrome-extension – i336_ Sep 22 '19 at 03:35
  • It *is* possible and you don't need any polyfills. You just need to use the content script as a wrapper to inject a ` – dodov Feb 28 '23 at 08:10

0 Answers0