为什么我的 Chrome 扩展内容脚本的运行时没有任何 onMessage 仅连接和发送消息

Why does the runtime of my Chrome extension content script not have any onMessage only connect and send message

我为此苦苦挣扎了好几天,我的扩展程序的内容脚本似乎缺少权限之类的,我搜索了 API 文档但一无所获。

如果我使用以下代码从内容页面发送消息,而不是向内容页面发送消息,则消息传递有效:

来自后台页面:

var messageCallback = function (e) {
    var nodeMessage = JSON.parse(e.data);

    switch (nodeMessage.ExecutionType) {
        case 0:
            chrome.tabs.create({ url: nodeMessage.Url }, function (tab) {

                //injects injected.js NOT messages.js
                injectCode(tab.id);

                chrome.tabs.sendMessage(tab.id,nodeMessage);
            });
        break;
//some other switch cases...

来自内容脚本:

chrome.runtime.onMessage.addListener(function (message) {
    console.log('Message received');

    var event = new CustomEvent("foo_receive", {
        detail: message,
        bubbles: true
    });

    console.log('Event sent');
    document.dispatchEvent(event);
});

我的清单如下所示:

{
  "manifest_version": 2,

  "name": "extesnion_name",
  "short_name": "thing",
  "description": "long sentence",
  "version": "1.0.0",
  "icons": { "16": "icon16.png",
             "48": "icon48.png",
             "128": "icon128.png" },
  "permissions": ["background", "tabs", "<all_urls>" ],
  "background": {
    "scripts": ["background.js"],
    "persistent": true
  },
  "content_scripts":[
      {
         "matches": ["<all_urls>"],
         "js": ["messages.js"],
      }
  ],
  "web_accessible_resources": ["injected.js"]
}

chrome控制台显示如下:

内容脚本:

和背景页面:

如果 chrome.runtime.onMessage 未定义,您会在控制台中看到一条错误消息,告诉您当 运行 内容脚本时。

真正发生的是,您在控制台中看到的是 chrome.runtime 的受限版本,因为您访问的是网页上下文而不是内容脚本上下文。请参阅 this answer 从控制台访问内容脚本上下文。

你没有给我们看,但我猜你的后台脚本有

function injectCode(tabId) {
    chrome.tabs.executeScript(tabId,{"file":"contentScript.js"});
}

问题是这个函数是异步的。浏览器不会等待它完成,而是继续使用后台脚本,将消息发送到不存在的内容脚本。然后 injectCode 完成,但为时已晚。

Here 是一个很好的参考。简短的回答是你需要使用 callback 选项,这样你最终会得到

chrome.tabs.executeScript(tabId,{"file":"contentScript.js"},function() {
    chrome.tabs.sendMessage(tabId,nodeMessage);
});

但现在您需要重做 injectCode 函数来跟踪 nodeMessage