Firefox webextension Error: Could not establish connection. Receiving end does not exist

user6875880 picture user6875880 · Jun 21, 2017 · Viewed 14.4k times · Source

I am trying to send a variable from a background script to a content script that is associated with an HTML page. The content script updates the HTML content with the variable received from the background script.

The problem is that I am getting this error message:

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

The background script main.js:

var target = "<all_urls>";
function logError(responseDetails) {
  errorTab = responseDetails.tabId;
  console.log("Error tab: "+errorTab);

  errorURL = responseDetails.url;
  console.log("Error URL: "+errorURL);

  //send errorURL variable to content script
  var sending = browser.tabs.sendMessage(errorTab, {url: errorURL})
    .then(response => {
      console.log("Message from the content script:");
      console.log(response.response);
    }).catch(onError);

  //direct to HTML page
  browser.tabs.update(errorTab,{url: "data/error.html"});
}//end function

browser.webRequest.onErrorOccurred.addListener(
  logError,
  {urls: [target],
  types: ["main_frame"]}
);

The error.html is:

<html>
<head>
  <meta charset="UTF-8">
</head>
<body>
  The error received is <span id="error-id"></span>
  <script src="content-script.js"></script>
</body>
</html>

The content-script.js:

//listen to errorURL from the background script.
browser.runtime.onMessage.addListener(request => {
  console.log("Message from the background script:");
  console.log(request.url);
  return Promise.resolve({response: "url received"});
}); //end onMessage.addListener

//update the HTML <span> tag with the error
document.getElementById("error-id").innerHTML = request.url;

The manifest.json:

{
  "manifest_version": 2,
  "name": "test",
  "version": "1.0",
  "background": {
    "scripts": ["main.js"]
  },

  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["webextension/data/content-script.js"]
    }
  ],

  "permissions": [
    "<all_urls>",
    "activeTab",
    "tabs",
    "storage",
    "webRequest"
  ]
}

Answer

Makyen picture Makyen · Jun 21, 2017

You get the error:

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

when you attempt to communicate (e.g. tabs.sendMessage(), tabs.connect()) to a tab where a content script is not listening for messages. This includes times when a content script does not exist in the tab.

You can not inject content scripts into about:* URLs

For your issue, you are getting this error because no content script is injected in the tab. By the time you are trying to send the message, in a main_frame webRequest.onErrorOccurred event, the URL for the tab is already about:neterror?[much more, including the URL where the error occurred]. You can not inject content scripts into about:* URLs. Thus, there is no content script in the tab listening for your message.

Specifically, you have used the <all_urls> match pattern in your manifest.json content_scripts entry. <all_urls> matches:

The special value "<all_urls>" matches all URLs under any of the supported schemes: that is, "http", "https", "file", "ftp", "app".

It does not match about:* URLs.

For a bit more discussion of the URL used when Firefox gets a webRequest.onErrorOccurred event in a main_frame, see "Injecting into navigation error page gets: Error: No window matching {“matchesHost”:[“”]}"