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?
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.