0

I have a script that injects a js file in each tab via

chrome.scripting.executeScript({, world: 'MAIN'})

I do that as i want to access variables of the loaded pages.

In this injected code i want to send a message to background via

chrome.runtime.sendMessage()

though in the page console i get the error:

Uncaught TypeError: Cannot read properties of undefined (reading 'sendMessage')

manifest.json (shrinked)


{
   "manifest_version": 3,
   "background": {
      "service_worker": "background.js",
      "type": "module"
   },
   "permissions": [
      "scripting"
   ]

}

background.js


chrome.scripting.executeScript({
   target: {tabId: tabId},
   files: [
      './js/asdf.js'
   ],
   world: 'MAIN'
}).then()

./js/asdf.js

console.log("asdfasdf"); # is printed
chrome.runtime.sendMessage({action: '...'}).then()

As soon as i do not run the script with world 'MAIN' i can access the method 'sendMessage'.

How can i send infos from a script injected into world 'MAIN' to the background? :)

mandano
  • 31
  • 4
  • No need for sendMessage, there's a much simpler method: use a function in executeScript: [example](https://stackoverflow.com/a/46870005). It can be an `async` function that returns a Promise. – wOxxOm Oct 30 '22 at 19:04
  • thx for your response, when i use the args attribute it seems i cannot use any files anymore - ```Uncaught (in promise) Error: 'args' may not be used with file injections.``` - though i have a few classes that i need to use :( - is there any other option? – mandano Oct 31 '22 at 16:32
  • `args` is not necessary. The important part is to end the executed code with an expression e.g. `foo()` at the end of your script and it will be transferred back into executeScript. – wOxxOm Oct 31 '22 at 18:32
  • thx again for your response, i think i lack knowlegde to understand your response - it would help to push data to the script and receive data from it? – mandano Nov 02 '22 at 16:09
  • i came across this [postMessage](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#host-page-communication) in [here](https://stackoverflow.com/questions/9515704/access-variables-and-functions-defined-in-page-context-using-a-content-script/9517879#comment94436100_19312198) - will try that out – mandano Nov 02 '22 at 16:15

1 Answers1

0

For my scenario the following worked:

content script (world: isolated)

window.addEventListener("load", async function () {
    //get state from background
    const state = await chrome.runtime.sendMessage({});


    ....
    //send state to page
    window.postMessage();
});

//receive response from page
window.addEventListener("message", (event) => {
    //send info to background
    chrome.runtime.sendMessage();
}, false);

background.js (inject code into page)

chrome.scripting.executeScript({
        target: {tabId: tabId},
        files: [
            'classes.js',
            '.main.js',
        ],
        world: 'MAIN',
    }).then();

classes.js

//receive info from content script   
window.addEventListener("message", (event) => {
   //do something based on received state 
}, false);

//post something back to content script
window.postMessage();

process:

  • get state from background by sendMessage in content script
  • based on state info content script sends postMessage to page
  • postMessage triggers process in page (injected code)
  • code does something and sends postMessage to content script
  • content script had listened for postMessage and forwards info to background by sendMessage
mandano
  • 31
  • 4