Chrome浏览器扩展:sendMessage无法工作

4
我已经阅读了谷歌关于“消息传递”的文档多次,并且可能查看了10多个其他具有相同问题的问题,并已经尝试过大多数“解决方案”以及下面的内容的各种变化...这是黑魔法,对吗?无论如何,下面是它。
清单文件:
{
    "manifest_version" : 2,
    "name" : "Message Test",
    "version" : "1.0",

    "browser_action": { 
        "default_popup": "popup.html"
    },

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

    "content_scripts": [
        {
        "matches" : ["<all_urls>"],
        "js": ["message-test.js"]
        }
    ]    
}

我知道扩展程序不应该使用内联JS,但为了保留原始问题,我将其保留在此处。因为我仍然无法从后台页面发送消息,所以当我从弹出窗口切换到后台时,我从manifest.json中删除了适当的行。 popup.html 文件:
<html>
  <head>
    <script>
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello", theMessage: "Why isn\'t this working?"}, function(response) {
        console.log(response.farewell);
      });
    });
    </script>
  </head>
<body>
</body>
</html>

OR

background.js文件:

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello", theMessage: "Why isn\'t this working?"}, function(response) {
    console.log(response.farewell);
  });
});

message-test.js文件:

var Mymessage;
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    if (message.greeting == "hello"){
        Mymessage = message.theMessage;
        alert(Mymessage);
    }
    else{
        sendResponse({});
    }
});

我收到一个未定义的警告... 我还尝试在弹出窗口上按下按钮后并在指定网址上执行此操作,但这是稍后要处理的问题。可以在此处找到有关按钮和窗口的其他文件,只是background.js内容被包装在addEventListener ("click"...中: http://pastebin.com/KhqxLx5yhttp://pastebin.com/JaGcp6tj

all_urls 不是有效的语法。 - Zig Mandel
@ZigMandel 恰好就是这样。 - Xan
感谢您在这个问题上设置悬赏。截至2014年6月3日,我仍然没有收到有用的回复。对于那些知道这些东西如何工作的人来说,在从默认弹出窗口单击按钮后向内容脚本发送消息似乎并不太难... - user3334776
3个回答

3

你的代码存在几个问题。

Chrome 不允许扩展中使用内联脚本。你必须将 popup.html 分割为脚本和 HTML 两部分:

// popup.html
<html>
<body>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>

// popup.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    var tab = tabs[0];  // do not forget to declare "tab" variable
    chrome.tabs.sendMessage(tab.id, {
        greeting: "Can you hear me?"
    }, function(response){});
});

补充一下,如果你右键点击按钮并选择“检查弹出窗口”,就可以在弹出窗口的开发者控制台中捕获错误。 - Xan
不需要"activeTab",因为弹出窗口正在与现有的内容脚本进行通信,而不是尝试插入一个新的脚本。 - Rob W
所以我逐字尝试了一下,它仍然不起作用...完全相同的“manifest.json”文件,相同的“message-test.js”文件...我复制并粘贴了你的popup.html和popup.js。没有警报响起。 - user3334776
你们中有谁知道我还应该尝试什么吗? - user3334776
@user3334776 在您进行更改后,是否正确重新加载了您的扩展程序,并重新加载了测试新内容脚本应注入的页面? - Xan
你尝试过启用日志记录的方式运行Chrome吗?请参考这里 - http://www.chromium.org/for-testers/enable-logging - FuzzyAmi

2
仔细阅读这个答案可能会有所帮助。其中的每一点都适用于您的问题。
您的问题在于主要脚本执行的时间,以及内容脚本执行的时间。您需要确保在发送消息之前存在一个监听内容脚本,最坏的情况是通过编程方式注入它。
而要在弹出窗口中使其正常工作,请参照KAdot的答案

-1

这里是解决方案,使用后台脚本:

manifest.json

{
    "manifest_version" : 2,
    "name" : "Message Test",
    "version" : "1.0",

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

    "content_scripts": [
        {
        "matches" : ["<all_urls>"],
        "js": ["message-test.js"]
        }
    ]
}

message-test.js

var port = chrome.runtime.connect();
port.onMessage.addListener(function(message, sender, sendResponse) {
    if (message.greeting == "Can you hear me?"){
        alert("Test");
    }
    else{
        sendResponse({});
    }
});

popup.js

chrome.runtime.onConnect.addListener( function ( port ) {
port.postMessage({
        greeting: "Can you hear me?"
    });
});

一些解释:首先,我们从内容脚本连接到后台脚本,然后后台脚本向内容脚本发送消息。

更新

我根据@Xan的建议改进了答案。但是,思路是相同的,首先您应该让后台脚本知道内容脚本的存在。


仅使用开放端口进行敲门感觉不太妥当。 - Xan
@Xan 对不起,你知道和后台脚本沟通的其他方法吗? - dIsoVi
如果您不使用生成的端口,为什么要使用 chrome.runtime.connect / chrome.runtime.onConnect 呢? - Xan
我正在使用运行时连接来连接到后台脚本,直到该后台脚本对内容脚本一无所知。 - dIsoVi
@Xan,根据我们的讨论,我已经改进了答案。我只是想展示问题所在,使用提问者提供的代码。 - dIsoVi
显示剩余6条评论

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