7

I am developing an extension for both Chrome and Firefox, and I have come across a problem.

Basically, I am trying to get a content script to listen to messages using chrome.runtime.onMessage.addListener(...), however it doesn't seem to work.

I tested it by sending a message from the content script. The background script (ml.js) had a listener that worked fine, but the lsitener in the content script just didn't get the message.

You can view the code in this Gist (or below).

manifest.json:

{
    "manifest_version": 2,
    "name": "Messaging Extension",
    "version": "1.0.0",
    "background": {
        "scripts": ["ml.js"]
    },
    "content_scripts": [
        {
            "matches": ["*://*.google.co.uk/*"],
            "js": ["cs.js"],
            "run_at": "document_end"
        }
    ]
}

ml.js:

// When receive message...
chrome.runtime.onMessage.addListener(function(message) {
    if (message.key) {
        console.log('ML: First message received')
        // Send another message
        chrome.runtime.sendMessage({
            'foo': 'bar'
        })
    }
})

cs.js:

// Send message to ml.js
chrome.runtime.sendMessage({
    'key': 'value'
})
chrome.runtime.onMessage.addListener(function(message) {
    console.log('CS: Second message received')
})

When tested in Firefox (by loading the add-on at about:debugging and then visiting Google), cs.js sent the message, and ml.js logged the message to the console, however cs.js didn't log the message.

I'll appreciate some help, thanks!

Kaspar Lee
  • 5,446
  • 4
  • 31
  • 54
  • Are you expecting the content script to receive the message it sent? This does not happen. A message sent by a script is not received by the same script. – Makyen Oct 30 '16 at 12:21

1 Answers1

12

Using runtime.sendMessage() (messages to background scripts):

The runtime.sendMessage() (Chrome/Firefox) method is used to send messages to scripts that are running in the background context (background scripts, popup scripts, etc). Even when it is used to send messages from a script that is in the background context (e.g. to communicate between a popup script and a background script), it will be received by other currently listening background context scripts, but not the script that is sending it.

To quote the Google Chrome runtime.sendMessage() documentation (emphasis mine):

If sending to your extension, the runtime.onMessage event will be fired in every frame of your extension (except for the sender's frame)...

Sending a message to your content script (tabs.sendMessage())

If you are wanting to send a message from your background script to your content script you should be using tabs.sendMessage() (Chrome/Firefox). Alternately, you can use the connect() methods in runtime and tabs, which then provide you with a port (Chrome/Firefox).

References:

Community
  • 1
  • 1
Makyen
  • 31,849
  • 12
  • 86
  • 121
  • The sending of the message from the content script was just for demonstration purposes, but I see now that it was unclear (also I didn't know that you cannot receive a message you send from the same script). I have updated the question (and Gist) with new code demonstrating the same error. Thanks for the help though! – Kaspar Lee Oct 30 '16 at 13:03
  • Basically, even if the message is sent from `ml.js` using `runtime.sendMessage`, the content script will not receive it using `runtime.onMessage`. – Kaspar Lee Oct 30 '16 at 13:06
  • @Druzion, That is the expected behavior. `runtime.sendMessage()` is for sending messages to scripts in the background script context (e.g. background scripts popup scripts, etc.), not content scripts. If you want to send a message to your content script, you should use `tabs.sendMessage()`. Please see the documentation linked in the the "References" above. – Makyen Oct 30 '16 at 13:20
  • @Druzion, No problem. I'm glad I was able to help. In re-reading the Firefox `runtime.sendMessage()` documentation, I see that it could be a bit more clear. I've added it to my list of pages which I should update. – Makyen Oct 30 '16 at 13:33
  • Yes, I was reading `runtime.sendMessage` as the method to send messages *to* content scripts, instead of from them. – Kaspar Lee Oct 30 '16 at 13:38