无法将消息从上下文菜单发送到内容脚本

Unable to send message from context menu to content script

我想在用户选择上下文菜单项时向内容脚本发送消息。然后,内容脚本将根据消息根据需要格式化网页。

我无法这样做,但我已经能够将问题定位到负责发送消息的代码(在上下文菜单脚本中)或负责接收消息的代码(在内容脚本中)。

下面,我尝试展示一个试图重现问题的代码的简化版本:

manifest.json

{
    "manifest_version": 2,
    "name": "MCVE for SO",
    "version": "1",

    "description": "Demonstrate message passing from context menu to content script",

    "author": "Nityesh Agarwal",

    "permissions": [
        "tabs",
        "activeTab",
        "contextMenus"
    ],  

    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["markr.js"]
        }
    ],  

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

backgroundContextMenus.js:

chrome.runtime.onInstalled.addListener(function(){
    chrome.contextMenus.create({"title": "Testing",
                                "contexts": ["selection"],
                                "id": "testing"});
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
    console.log("testing..");
    console.log("Before sending the bold message");
    chrome.tabs.sendMessage(tab.id, {changeParameter: "bold"});
    console.log("After sending the bold message");
});

markr.js:

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse){
        console.log("Text toggled bold");
    }); 

选择上下文菜单项后,console 会显示以下消息:

backgroundContextMenus.js:8 testing..
backgroundContextMenus.js:9 Before sending the bold message
backgroundContextMenus.js:11 After sending the bold message

所以,正如您可能注意到的,没有日志说

Text toggled bold

这意味着 markr.js 文件中的代码没有被执行。因此,我怀疑负责发送消息的代码一定有问题:chrome.tabs.sendMessage(tabs[0].id, {changeParameter: "bold"});)

这是我尝试复制的另一个代码片段,但它给出了同样的问题 -


我无法弄清楚它究竟有什么问题。如果有人可以帮助我告诉我如何在上下文菜单和内容页面之间成功传递消息,那将会很有帮助。

根据 this answer 的提示,我修改了我的 backgroundContextMenus.js 如下:

function ensureSendMessage(tabId, message, callback){ 
  chrome.tabs.sendMessage(tabId, {ping: true}, function(response){ 
    if(response && response.pong) { // Content script ready
      chrome.tabs.sendMessage(tabId, message, callback);
    } else { // No listener on the other end
      console.log("Injecting script programmatically");
      chrome.tabs.executeScript(tabId, {file: "markr.js"}, function(){
        if(chrome.runtime.lastError) {
          console.error(chrome.runtime.lastError);
          throw Error("Unable to inject script into tab " + tabId);
        }
        // OK, now it's injected and ready
        console.log("Sending msg now");
        chrome.tabs.sendMessage(tabId, message, callback);
      });
    }
  });
}

chrome.runtime.onInstalled.addListener(function(){
    chrome.contextMenus.create({"title": "Testing",
                                "contexts": ["selection"],
                                "id": "testing"});
});

chrome.contextMenus.onClicked.addListener(function(info, tab){
    ensureSendMessage(tab.id, {greeting: "hello"});
});

然后我修改了markr.js如下:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
    if(request.ping){ 
        sendResponse({pong: true}); 
        return; 
    }   
    console.log("Text toggled bold");
}); 

现在控制台日志正是人们所期望的:

控制台日志:

markr.js:11 Text toggled bold

请记住,此日志是网页开发工具的控制台日志,而不是后台脚本的检查视图。