samrum / vite-plugin-web-extension

A vite plugin for generating cross browser platform, ES module based web extensions.
MIT License
325 stars 32 forks source link

Question: injection to MAIN environment #59

Open Bighamster opened 1 year ago

Bighamster commented 1 year ago

For the extension that I'm building, I'm trying to inject to the MAIN environment

chrome.scripting.registerContentScripts([
  {
    id: 'inpage',
    matches: ['http://*/*', 'https://*/*'],
    js: [
      'src/entries/content-scripts/inject.js'
    ],
    runAt: 'document_start',
    world: 'MAIN'
  },
]);

but generated code (async()=>{await import(chrome.runtime.getURL("assets/src/entries/content-scripts/inject.8e490e7d.js"))})();

raise an error chrome.runtime.getURL is not a function in console

I understand that neither the file (inject.8e490e7d.js) nor the method (chrome.runtime.getURL) exists in MAIN context, but how to inject correctly?

Bighamster commented 1 year ago

As a temporary solution I have to parse the manifest to find the right file name

  const manifest = browser.runtime.getManifest();
  const injectFile = manifest.web_accessible_resources.map(e => e.resources).flat().find(e => /\/inject\.[a-zA-Z0-9]+\.js$/.test(e));

  try {
    chrome.scripting.registerContentScripts([
      {
        id: 'inpage',
        matches: ['http://*/*', 'https://*/*'],
        js: [
          injectFile
        ],
        runAt: 'document_start',
        world: 'MAIN'
      },
    ]);
  } catch (err) {
    console.warn(`Dropped attempt to register inject content script. ${err}`);
  }
samrum commented 1 year ago

Couple of questions. To confirm, that temporary solution works without any issues? How are you defining the content script in your manifest? Is your original inject.js script importing other modules at all?

Bighamster commented 1 year ago

The answer to both questions is yes. Everything is working so far, but I haven't written anything complicated yet.

I moved inject.js to web_accessible_resources (from content_scripts) and ran registerContentScripts from background.js.

  web_accessible_resources: [{
    resources: [
      "src/entries/content-scripts/inject.js"
    ],
    matches: ["<all_urls>"],
    use_dynamic_url: true
  }],

inject.js for now it's very simple

import { EventEmitter } from 'events';

export default class WalletProvider extends EventEmitter {
  constructor() {
    super();
    this.selectedAddress = '0x0';
    this.networkVersion = '000';
    this.chainId = '0x0';
    this.setMaxListeners(100);
  }  
}

window.onemoreprovider = new Proxy(new WalletProvider(), {
  deleteProperty: () => true,
});
devhandler commented 9 months ago

@Bighamster if you use world: isolated, not main, would your original code work? i try to use registerContentScripts to register content scripts from background script (so no declaration in manifest.json), but the backgroud script keeps saying: Error: Could not load javascript 'content.js' for content script.

i'm also not sure the js path in registerContentScripts is relative to which one, the background folder in dev src, the dev root src, or actually in /dist even during development. js: [ 'src/entries/content-scripts/inject.js' ],

from the code generated by npm run dev, seems they are reference to dev src folders. (not sure what is the @vite folder, can't find it in node module folder) import "http://localhost:5173/@vite/client"; import "http://localhost:5173/src/entries/background/main.js";