Sendmessage error:Error: Could not establish connection. Receiving end does not exist

Recently I had problem how to use sendMessage and I have successfully managed it that I could send and recieve messages on both ends. But I had to remake it a bit to use namespace and now I have this strange error.

I just upgraded from 48.0b6 to 48.0b7.
I have been using callback too.

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
SIDE NOTE: I constant problems with the Addon debugger that it does not show current content of file I am debugging and that it shows and prints incorrect errors because it does not see the current version of the file.

So the error,
sendmessage error:Error: Could not establish connection. Receiving end does not exist

probably happened when I added a callback.

When I removed it and HAD TO RESTART FIREFOX and Addon Debugger to see the current version. So the bellow code does not print error because it does not have the callback function:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

MyNamespace.sendCommandMessage = function(command, namespace){
  chrome.tabs.query(
    {
    active: true, 
    currentWindow: true // send it to the active window
    }, 
    function(tabs) {
      chrome.tabs.sendMessage(
        tabs[0].id,
        command/*,          // message
        {},                 // options optional object
        function(response) {
        if (chrome.runtime.lastError) {
          console.log("error:" + chrome.runtime.lastError);
          console.log(chrome.runtime.lastError);
        }
        else
          {
          console.log("message successfully sent");
          }
        
        } // optional function
        */
        )
      } // end of query() callback
  ); // end of query() call
}

This is used like this, when shif+ctrl+u is pressed:
MyNamespace.sendCommandMessage(command);

Now, the current code.

MyNamespace.sendCommandMessage = function(command){
  chrome.tabs.query(
    {
    active: true, 
    currentWindow: true // send it to the active window
    }, 
    function(tabs) {
      chrome.tabs.sendMessage(
        tabs[0].id,
        command,
       // {},                 // options optional object
        function(response) {
        if (chrome.runtime.lastError) {
          console.log("error:" + chrome.runtime.lastError);
          console.log(chrome.runtime.lastError);
        }
        else
          {
          console.log("message successfully sent");
          }
        
        } // optional function
        
        )
      } // end of query() callback
  ); // end of query() call

Prints the error above.

I tried to pass the empty object as options parameter and that cause the same problems.

So I need to ask you how this should be correctly done. Or what is the reason of the error. Do you also have the similar problems with the Addon Debugger? I still need to restart it because I don’t see the current version of the file. So I quite cannot rely on what the Addon Debugger shows!

I haven’t looked into this in detail, but this message means that there is no corresponding listener for that message. In some circumstances this may be expected but obviously most of the time it is an unexpected error. Make sure you are adding the content script and sending the messages from the same namespace. Content scripts are sandboxed so that you don’t stamp all over another addon. Or the content script may have crashed, it isn’t always obvious when this happens. This has changed recently, possibly in 48.0b7. This error is now received in some cases where previously the message just vanished silently.

The change I did is that I have moved a function which was the same for all three modules (content scripts) to the shared background.js. I have no idea if this is good practice.

options_easy.html:


html content
script src="…/background.js" /script
script src=“options_easy.js” /script
/body
/html

So I have included the background.js which includes the namespace definition. It also contains check function to check if there are data saved in storage. The second file .js is the individual module which contains the individual functions for that module.

The content script contains this:

chrome.runtime.onMessage.addListener(
function (m){
  console.log("Recieved message:");
  console.log(m);
  $('body, h1, h2, h3, h4, h5, div, p, ul, li').css({'background-color': 'black', 'color':'#f7fab0', 'font-family':'Arial Black', 'font-size': '20px', 'line-height': '35px', 'font-weight':'bold', 'font-size':'28px', 'padding-left':'0px', 'padding-right':'0px'});
  $('h1, h2, h3, h4, h5, div, p, ul, li, span, a').css({'background-image': 'none'});

}
);

Now I have re-checked if this works for mozilla site and it works if I do not use the callback. However the error would be there if I would use it.

When I want to use callback (response) It is not clear to me what should be the third parameter exactly. Should it be null, empty object or what? Can you gimme example? Do I need to create another listener or this one is enough?

I am sure with no response callback all works fine.

Can you tell yet me how to access the namespace defined in background.js from the injected content script?

chrome.runtime.onMessage.addListener(
function (m){
  console.log(MyNamespace);
}
);

This prints nothing.

Edit:

I got it, I just pass the namespace as message

The callback function must be the fourth parameter. The third parameter must be an object, any object, or just an empty one. If you pass a callback as the third parameter it won’t be called back. I don’t know if that will cause an error.

Remember that errors are only reported if the callback function is called, so if you pass it as the third parameter then no error will be reported even if there is an error.

Message callbacks are strange things. Best to use the word response to describe them. They are special functions that can only be called once and execute in the context of the sendMessage function itself, not in the context of the receiver.

Given that you are trying to share code between multiple content scripts, make sure that there is only one listener for each message, and only one sender.

Thanks.

You say third argument must be object, but I tried both empty object, null, and also {includeTlsChannelId:false} and nothing works for runtime.sendMessage.

For tabs.sendMessage there should be
optionsOptional
object.

frameId  Optional
    integer. Sends the message to a specific frame identified by frameId instead of all frames in the tab.

Which is useless for me when I have no frames on page. It should be optional. So I guess program should check type of the argument.

In the docs example for tabs.sendMessage I have found example how to use sendResponse - so it is in totally different manner than I expected from docs syntax:

// content-script.js

function handleMessage(request, sender, sendResponse) {
  console.log("message from the background script:");
  console.log(request.greeting);
  sendResponse({response: "hi from content script"});
}

chrome.runtime.onMessage.addListener(handleMessage);

But for me, it is not clear if may I use this in popup? As popup is not injected script.