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?
CodePudding user response:
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.
One solution is to use run_at
key to start the content script before the tab starts loading:
"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.