Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Content script not receiving message from background script (Mv3)

I made this simple messaging example chrome extension, where a message is supposed to be sent from the background script to the content script. Unfortunately, it seems the content script doesn't receive the message.

Background script:

// background.js

function sendMessage(tabId, hostname) {
    console.log("Sending message to tabId: ", tabId)
    chrome.tabs.sendMessage(tabId, {hostname: hostname}, (resp) => {console.log("response: ", resp)});
}

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.url) {
        console.log(changeInfo.url)
        var hostname = new URL(changeInfo.url).hostname;
        sendMessage(tabId, hostname)

    }
});

Content script:

// content.js

console.log("injected");

function logMessage(message) {
    console.log("Message from background: ", message)
}

chrome.runtime.onMessage.addListener(
    (request, sender, sendResponse) => {
        logMessage(request.hostname)
    }
);

Manifest (v3):

// manifest.json

{
  "name": "Messaging test",
  "description": "",
  "version": "1.0",
  "manifest_version": 3,

  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["tabs"],
  "content_scripts": [
    {
      "matches": [
        "<all_urls>",
        "https://*/*",
        "http://*/*"
      ],
      "js": ["content.js"]
    }
  ]
}

I made sure to reload the extension and use a new tab for testing.

Here is the dev console output from the background script: dev console output of background script

And here is the dev console output from the content script (injected into google.com): dev console output of content script

So, the content script gets injected, but doesn't receive the message from the background script. I recall this working in manifest v2, so I'm not sure what's wrong. Any ideas?

like image 212
velox Avatar asked Sep 15 '25 19:09

velox


1 Answers

Content scripts run after DOMContentLoaded by default, but onUpdated event is triggered when the tab starts loading a URL, so when sendMessage is called there's no content script yet in this tab.

Solution: specify "run_at": "document_start" so the content script already runs when onUpdated reports changeInfo.url:

  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["content.js"],
    "run_at": "document_start"
  }],

Another solution would be to reverse the direction of communication and let the content script call sendMessage while the background script would return the data in onMessage, see messaging.

like image 82
wOxxOm Avatar answered Sep 17 '25 11:09

wOxxOm