内容脚本和chrome扩展中的后台页面之间的消息传递无法正常工作

时间:2015-09-25 07:49:57

标签: javascript google-chrome-extension

我发布以下代码:

的manifest.json

{
  "manifest_version": 2,

  "name": "Demo",
  "description": "all_frames test",
  "version": "1.0",

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

  "content_scripts": [{
        "matches":    ["*://*/*"],
        "js":         ["content.js"],
        "all_frames": true
    }],

  "permissions": [
          "tabs",
          "*://*/*"
   ]
}

background.js

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    var tabStatus = changeInfo.status;

    if (tabStatus == 'complete') {

        function return_msg_callback() {
            console.log('Got a msg from cs...')
        }

        chrome.tabs.sendMessage(tabId, {
            text: 'hey_cs'
        }, return_msg_callback);
    }

});

content.js

/* Listen for messages */
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
    /* If the received message has the expected format... */
    if (msg.text && (msg.text == 'hey_cs')) {
        console.log('Received a msg from bp...')
        sendResponse('hey_bp');
    }
});

然后,如果我转到包含多个跨源iFrame的网站,例如http://www.sport.es/,您会看到页面中的所有iFrame都从后台页面接收消息,但只有其中一个能够回应。这是正常行为吗?

提前感谢您的回答。

3 个答案:

答案 0 :(得分:10)

您只发送一封带有直接回调的邮件,因此Chrome自然只能使用此响应回调一次(它是与一个实体的一次性连接,无论是页面还是iframe)。

  • 解决方案1 ​​:明确向每个iframe发送多条消息:

    manifest.json,附加权限:

    "permissions": [
        "webNavigation"
    ],
    

    background.js

    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
        .............
        // before Chrome 49 it was chrome.webNavigation.getAllFrames(tabId, .....
        // starting with Chrome 49 tabId is passed inside an object
        chrome.webNavigation.getAllFrames({tabId: tabId}, function(details) {
            details.forEach(function(frame) {
                chrome.tabs.sendMessage(
                    tabId,
                    {text: 'hey_cs'},
                    {frameId: frame.frameId},
                    function(response) { console.log(response) }
                );
            });
        });
    });
    
  • 解决方案2 :重新设计后台脚本逻辑,以便内容脚本成为通信的主角,并在邮件加载后发送消息。

    content.js

    chrome.runtime.sendMessage({text: "hey"}, function(response) {
        console.log("Response: ", response);
    });
    

    background.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        console.log("Received %o from %o, frame", msg, sender.tab, sender.frameId);
        sendResponse("Gotcha!");
    });
    

答案 1 :(得分:3)

您可以使用executeScript代替消息传递。虽然很少使用回调的论点(而且我不认为很多人知道它是如何工作的),但它在这里是完美的:

chrome.tabs.executeScript(tabId, {file: "script.js"}, function(results) {
  // Whichever is returned by the last executed statement of script.js
  //   is considered a result.
  // "results" is an Array of all results - collected from all frames
})

例如,您可以确保最后执行的语句类似于

// script.js
/* ... */
result = { someFrameIdentifier: ..., data: ...};
// Note: you shouldn't do a "return" statement - it'll be an error,
//   since it's not a function call. It just needs to evaluate to what you want.

确保script.js能够在同一个上下文中执行多次。

对于帧标识符,您可以设计自己的算法。也许URL足够了,也许您可​​以使用frame's position in the hierarchy

答案 2 :(得分:1)

这是在chrome扩展[ Content 背景]中进行双向通信的一种清晰方法:

内部内容脚本:

将信息发送到后台:

chrome.extension.sendRequest({message: contentScriptMessage});

从后台接收信息:

chrome.runtime.onMessage.addListener(function(request, sender) {
  console.log(request.message);
});




内部背景脚本:

将信息发送到内容脚本:

chrome.extension.onRequest.addListener(function(request, sender) {
  console.log(request.message);
});

从内容脚本接收信息:

chrome.tabs.getSelected(null, function(tab) {
  chrome.tabs.sendMessage(tab.id, { message: "TEST" });
});
相关问题