"接收端不存在"将消息传递给注入的内容脚本时

时间:2018-02-24 19:34:10

标签: javascript promise listener message firefox-webextensions

在Firefox的附加组件中,我试图将后台脚本中的代码注入选项卡,然后将消息传递给它。不幸的是,内容脚本似乎只在消息发送后才添加监听器,从而导致错误。我错过了什么?这是我的示例代码:

的manifest.json:

{
    "description": "Test background to content message passing",
    "manifest_version": 2,
    "name": "Background content message passing",
    "version": "0.1.0",
    "default_locale": "en",

    "applications": {
        "gecko": {
            "id": "bcm@example.com",
            "strict_min_version": "51.0"
        }
    },

    "permissions": [
        "contextMenus",
        "<all_urls>"
    ],

    "background": {
        "scripts": ["background.js"]
    }
}

background.js:

"use strict";

const {contextMenus, i18n, runtime, tabs} = browser;

contextMenus.onClicked.addListener(function(info, tab) {
    if (info.menuItemId == "bgd-cnt-msg") {
        tabs.executeScript(tab.id, {
            file: "/content.js",
        })
        .then(runtime.sendMessage({"result": 42}))
        .then(console.log("Debug: runtime message sent"))
        .catch(console.error.bind(console));
    }
});

contextMenus.create({
    id: "bgd-cnt-msg",
    title: "Test message passing",
    contexts: ["all"],
    documentUrlPatterns: ["<all_urls>"]
});

content.js

"use strict";

console.log("Debug: executing content script");

browser.runtime.onMessage.addListener(function (message) {
    console.log("Debug: received message %O", message);
});

console.log("Debug: added listener");

选择上下文菜单条目的结果是

Debug: runtime message sent                                  background.js:11:15
Debug: executing content script                                     content.js:3
Debug: added listener                                               content.js:9
Error: Could not establish connection. Receiving end does not exist.   undefined

即,在发送到选项卡的消息之后执行上下文脚本。如何在发送消息之前添加监听器?

根据@Thắng的建议,我将代码更改为使用tabs.sendMessage而不是runtime.sendMessage

contextMenus.onClicked.addListener(function(info, tab) {
    if (info.menuItemId == "bgd-cnt-msg") {
        tabs.executeScript(tab.id, {
            file: "/content.js",
        })
        .then(tabs.sendMessage(tab.id, {"result": 42}))
        .then(console.log("Debug: runtime message sent"))
        .catch(console.error.bind(console));
    }
});

现在提前报告错误:

Debug: runtime message sent                                  background.js:11:15
Error: Could not establish connection. Receiving end does not exist.   undefined
Debug: executing content script                                     content.js:3
Debug: added listener                                               content.js:9

感谢@Thắng,他提供了一个可行的解决方案,我修改了我的代码,不仅使用了tabs.sendMessage,还传递了回调函数:

contextMenus.onClicked.addListener(function(info, tab) {
    if (info.menuItemId == "bgd-cnt-msg") {
        tabs.executeScript(tab.id, {
            file: "/content.js",
        })
        .then(function () { tabs.sendMessage(tab.id, {"result": 42}) })
        .then(function () { console.log("Debug: runtime message sent") })
        .catch(console.error.bind(console));
    }
});

content.js

中添加其他修补程序
browser.runtime.onMessage.addListener(function (message) {
    console.log("Debug: result is " + message.result);
});

我现在得到了

Debug: executing content script                                     content.js:3
Debug: added listener                                               content.js:9
Debug: runtime message sent                                  background.js:11:15
Debug: result is 42                                                 content.js:6

1 个答案:

答案 0 :(得分:1)

在后台脚本中,您需要让它知道它应该将消息发送到哪个标签,因此请不要使用runtime.sendMessage

var sending = chrome.tabs.sendMessage(
  tabId,                   // integer
  message,                 // any
  options                  // optional object
)

在此处查看更多内容(适用于webExtensions但与Chrome兼容):https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/sendMessage

您的全功能扩展程序(您可能需要将所有browser.*更改为chrome.*): https://drive.google.com/file/d/1KGf8tCM1grhhiC9XcHOjsrbBsIZGff3e/view?usp=sharing