chrome.tabs.sendMessage callback function is not called. Why?
Asked Answered
M

1

5

I have the following method that is called from the background script of my Chrome Extension. The goal is to send a message to a specific tab and then call provided callback method with the result. The important part is that the callbackDone must be always called at some point in time. So it goes as such:

function sendToTab(nTabID, callbackDone)
{
    (function()
    {
        chrome.tabs.sendMessage(nTabID, {
            action: "update01"
        }, 
        function(response) 
        {
            if(chrome.runtime.lastError)
            {
                //Failed to send message to the page
                if(callbackDone)
                    callbackDone(nTabID, null); //Page never received the message
            }
            else
            {
                //Sent message OK
                if(response.result === true)
                {
                    if(callbackDone)
                        callbackDone(nTabID, true); //Success!
                }
                else
                {
                    if(callbackDone)
                        callbackDone(nTabID, false);    //Page returns failure
                }
            }
        });
    }());
}

Then from within the page that processes the message (can be an injected content script) I handle it as such:

chrome.runtime.onMessage.addListener(onMessageProc);

function onMessageProc(request, sender, sendResponse)
{
    if(request.action == "update01")
    {
        //Do processing .... that sets `bResult`

        sendResponse({result: bResult});
    }
}

The above approach works quite well, except... Say, there's a page, like Options page script, that does not process my update01 message and instead, it processes its own message as such:

chrome.runtime.onMessage.addListener(onMessageProc);

function onMessageProc(request, sender, sendResponse)
{
    if(request.action == "update02")   //Note different action ID
    {
        //Does some other actions...
    }
}

In this case when my first sendToTab method is called for this tab, my callbackDone is never called, i.e. chrome.tabs.sendMessage is invoked and it returns immediately but its callback function is never called.

So what am I missing here?

Mimesis answered 22/9, 2014 at 0:49 Comment(3)
I don't think that's all relevant code.Wouldbe
@Xan: What are you talking about?Mimesis
I thought it's important what's in your listeners. It is, but your code snippet is sufficient.Wouldbe
W
7

You are seeing expected behavior.

The documentation states, regarding the callback function:

If you specify the responseCallback parameter, it should be a function that looks like this:

function(any response) {...};

any response
The JSON response object sent by the handler of the message. If an error occurs while connecting to the specified tab, the callback will be called with no arguments and runtime.lastError will be set to the error message.

There are 3 possible results of sendMessage executing.

  1. There was a listener, and it called sendResponse.
    Then, the callback is called with the response as a parameter.

  2. There was a listener, and it terminated without calling sendResponse (synchronously or asynchronously).
    Then, the callback is not called at all.

  3. There was some sort of error sending the message.
    Then, the callback is called with no arguments and chrome.runtime.lastError set.

If you need your callback to execute in any circumstance, you'll need a "default" case in your listeners that calls sendResponse.

Wouldbe answered 22/9, 2014 at 9:15 Comment(4)
Thanks. Although it would really help if your 3 points were included in the documentation. Or at least it would eliminate bugs and confusion... How do you know all this?Mimesis
In this case, I just tested it. Then, cross-referenced with documentation, and the quote above can be interpreted like this.Wouldbe
@Mimesis You're not calling your sendResponse, and wondering why the response function is never called? Seems like expected behavior to me.Stave
@Stave I don't know. I would expect the callback to be called without arguments and with unset chrome.runtime.lastError. I suppose c00000fd did, too.Wouldbe

© 2022 - 2024 — McMap. All rights reserved.