Firefox网页扩展错误:无法建立连接。接收端不存在。

27

我正在尝试从一个后台脚本将一个变量发送到与HTML页面相关联的内容脚本。内容脚本使用从后台脚本收到的变量更新HTML内容。

问题是我遇到了这个错误信息:

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

背景脚本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"]}
);

error.html 的含义是:

<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>

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;

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"
  ]
}
5个回答

23

您会收到以下错误:

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

当您尝试与一个未监听消息的内容脚本的选项卡进行通信时,例如使用 tabs.sendMessage()tabs.connect(),就会出现这种错误。这还包括内容脚本不存在于标签页中的情况。

您无法将内容脚本注入到about:* URL中

对于您的问题,之所以出现此错误,是因为该标签页中没有注入任何内容脚本。在您尝试发送消息时,在main_frame webRequest.onErrorOccurred事件中,标签页的URL已经是about:neterror?[much more, including the URL where the error occurred]。您无法将内容脚本注入到about:* URL中。因此,该标签页中没有内容脚本监听您的消息。

具体而言,您在manifest.json content_scripts条目中使用了<all_urls>匹配模式<all_urls> 匹配:

特殊值"<all_urls>"匹配所有支持的协议下的URL:即"http","https","file","ftp","app"。

但是它不匹配about:* URL。

有关 Firefox 在main_frame中获取webRequest.onErrorOccurred事件时使用的URL的更多讨论,请参见 "Injecting into navigation error page gets: Error: No window matching {“matchesHost”:[“”]}"。


有没有其他方法可以实现自定义错误页面,以便我将从后台脚本获取的错误ID发送到我的HTML内容脚本?我可以使用自定义HTML更新选项卡内容。这个HTML包含一个内容脚本。一些功能确实有效(比如监听按钮点击),但我需要将错误数据发送到我的HTML中。我该怎么办? - user6875880
这就是我正在做的事情。如果您查看我的HTML,我有src="content-script.js"。所以,我需要从清单内容脚本中删除它?然后,我可以将错误代码从后台发送到HTML的脚本(使用browser.tabs.update(errorTab,{url: "data/error.html"});在错误选项卡中显示HTML吗? - user6875880
1
你肯定要从你的manifest.json content_scripts中移除它。但是,正如我提供的链接所述,你需要使用runtime.sendMessage()(用于在后台上下文中的目标)而不是tabs.sendMessage()(用于内容脚本的目标)。然而,鉴于在调用tabs.update()和HTML页面以及JavaScript实际加载和运行之间存在延迟,你可能需要使用其中一种方法将数据拉入HTML页面,而不是从后台页面推送数据。 - Makyen
您可以在storage.local中创建任意数量的键值对。但是,由于性能问题,不建议存储大量数据。 - Makyen
@johnktejik 你可以像处理其他异步错误一样捕获这个错误。具体的处理方式取决于你是使用 chrome.* 还是 browser.* 命名空间。 - Makyen
显示剩余7条评论

12

对于扩展程序开发人员:如果您重新加载扩展程序(作为开发循环的正常部分),它将切断与内容脚本的所有连接

您必须记得同时重新加载页面,以便内容脚本能够正确地重新监听。


2
我也遇到了同样的错误。
我的问题和解决方案不同,但我会把它添加在这里以便帮助大家。
在我的情况下,我的content.js脚本最初没有一个browser.runtime.onMessage.addListener()函数(FireFox)。
当我后来将此监听器添加到content.js脚本中时,我没有在FireFox的“about:debugging”页面中重新加载临时扩展程序,因此出现了上述错误。
在“about:debugging”选项卡中单击“重新加载”后,内容脚本接收到了消息。

1
我用如下方式解决了同样的任务:
我正在制作上下文菜单并遇到类似的问题。
browser.contextMenus.onClicked.addListener((info, tab) => {
       if (info.menuItemId === "mymenu") {
       // some code
       browser.tabs.sendMessage(tabs[0].id, {greeting: "Hi from background script"});
       }
        });

我遇到了错误:

无法建立连接。接收端不存在。

我添加了一个函数和一个监听器:

browser.contextMenus.onClicked.addListener((info, tab) => {
       if (info.menuItemId === "mymenu") {
       // some code
       browser.tabs.sendMessage(tabs[0].id, {greeting: "Hi from background script"});
       }
        });
   // -----function and Listener ------
   function connectToContent() {
      browser.tabs.query({ currentWindow: true, active: true
      }).then((tabs) => {
       browser.tabs.sendMessage(tabs[0].id, {greeting: "Activate Tab"});
       });
    }

    browser.tabs.onActivated.addListener(connectToContent);

现在它正在工作。 browser.tabs.onActivated.addListener 执行并保持连接。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接