从扩展程序背景或弹出窗口发送消息到内容脚本无法正常工作。

116

我知道这个问题已经以不同方式反复被问过了,但我尝试查看了所有答案(希望没有错过任何人),但是它们都不能解决我的问题。

这是我的扩展程序的代码:

清单:

{
"name": "test",
"version": "1.1",
"background": 
{ 
    "scripts": ["contextMenus.js"]
},

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

"content_scripts" : [
    {
        "matches" : [ "http://*/*" ],
        "js": ["jquery-1.8.3.js", "jquery-ui.js"],
        "css": [ "jquery-ui.css" ],
        "js": ["openDialog.js"]
    }
],

"manifest_version": 2
}

contextMenus.js

function onClickHandler(info, tab) {
    if (info.menuItemId == "line1"){

      alert("You have selected: " + info.selectionText);

      chrome.extension.sendMessage({action:'open_dialog_box'}, function(){});

      alert("Req sent?");

    }
}

chrome.contextMenus.onClicked.addListener(onClickHandler);

chrome.runtime.onInstalled.addListener(function() {

  chrome.contextMenus.create({"id": "line1", "type": "normal", "title": "I'm line 1",     "contexts":["selection"]});

});

openDialog.js

chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {

  if (msg.action == 'open_dialog_box') {
    alert("Message recieved!");
  }
});

背景页的两个警报正常工作,而 content_script 的一个警报没有工作。

控制台日志信息:端口错误:无法建立连接。接收端不存在。

我的错误在哪里?


你应该使用chrome.tabs.sendMessage()来向内容脚本发送消息,而不是chrome.extension.sendMessage() - apsillers
6个回答

192
在您的背景页面中,您应该调用:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
    chrome.tabs.sendMessage(tabs[0].id, {action: "open_dialog_box"}, function(response) {});  
});

当前你使用的是chrome.extension.sendMessage,建议改为chrome.tabs.sendMessage

chrome.tabs版本用于向内容脚本发送消息,而chrome.extension函数用于向所有其他扩展组件发送消息。


8
谢谢。除了chrome.tabs.sendMessage必须指定发送到哪个标签页(http://developer.chrome.com/extensions/messaging.html),你的答案是正确的。因此解决方法是将其更改为:`chrome.tabs.query({active: true}, function(tabs){ chrome.tabs.sendMessage(tab.id, {action: "open_dialog_box"}, function(response) { }); });`。 - Subway
18
要在 content-script.js 中收到什么内容? - Kushal Jain
7
@KushalJain 我刚弄清楚了。在你的内容脚本JS文件中,你需要添加一个事件监听器,像这样:chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { /*在此处编写代码*/ });message是包含 { action: "open_dialog_box" } 或者其他你发送的信息的参数。sender是一个包含你Chrome扩展程序ID的对象。sendResponse是包含 function(response) {} 或者任何你传递进来的函数的参数,用于在消息被处理后调用该函数。 - jsea
11
这个解决方案对我没用。我完全按照文档操作,从 https://developer.chrome.com/extensions/messaging 复制了所有代码。这是一个非常简单的例子,但我仍然做不对。出现错误提示:“无法建立连接。接收端不存在。”你有什么想法吗? - umsateesh
3
我会吻你,@apsillers,我对天发誓。 - Mel Macaluso
显示剩余10条评论

25

@apsillers是正确的。 另外不要忘记在您的内容脚本侦听器中返回true,否则它可能会关闭得太早。

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    console.log(message)
    return true
});

这对我解决了问题 - 我一开始没有得到任何响应,但添加 return true 后它开始工作了。 - rupertonline
2
我发誓,在 Stack Overflow 上,最简单的答案通常是正确的。我无法相信这就是解决问题的方法,但它确实有效。感谢分享! - jstafford

5
提供的解决方案存在问题,它们会引发其他错误(导致我的 Google Chrome 崩溃)。
@apsillers 的解决方案可行,但回调会引发错误!
正确的写法应该是:
// Background.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
chrome.tabs.sendMessage(tabs[0].id, {action: "open_dialog_box"});  
});

现在使用@Ronan Ca提供的Content scripts,该方案基于@apsillers的解决方案。由于我们已从背景脚本中删除了回调,因此不建议返回。
// ContentScripts.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log(message)
// return true <- this and the callback in background.js are what caused a crash in extensions page of my Google chrome
});

如果我尝试使用回调函数打开后台控制台,它就无法打开。(这是一个非常严重的崩溃)


4

以下是一个将消息发送给内容脚本文件的后台脚本示例。

background.js

chrome.tabs.sendMessage(tabs[0].id,"your message"); 

content-script/content.js

chrome.runtime.onMessage.addListener(function (response, sendResponse) {
          console.log(response);
});

4
这是在清单V3中对我有效的方法。从后台脚本向内容脚本发送消息。
  chrome.tabs.sendMessage(sender.tab.id,"your message")

1
我的使用情况需要从网页向后台脚本发送消息。我使用了chrome.runtime.onMessageExternal来捕获此消息。
在此侦听器中,我基本上将消息转发到我的内容脚本,以便它可以执行其任务,但我无法弄清楚为什么我的内容脚本onMessage侦听器无法捕获该消息。
结果发现,在从网页发送消息之前等待1秒钟(我基本上是在加载时进行的),我能够看到消息到达我的内容脚本。

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