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

jac*_*ack 6 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",
          "*://*/*"
   ]
}
Run Code Online (Sandbox Code Playgroud)

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);
    }

});
Run Code Online (Sandbox Code Playgroud)

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');
    }
});
Run Code Online (Sandbox Code Playgroud)

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

提前感谢您的回答.

wOx*_*xOm 13

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

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

    manifest.json,附加权限:

    "permissions": [
        "webNavigation"
    ],
    
    Run Code Online (Sandbox Code Playgroud)

    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) }
                );
            });
        });
    });
    
    Run Code Online (Sandbox Code Playgroud)
  • 解决方案2:重新编写后台脚本逻辑,以便内容脚本成为通信的主角,并让它在加载后发送消息.

    content.js

    chrome.runtime.sendMessage({text: "hey"}, function(response) {
        console.log("Response: ", response);
    });
    
    Run Code Online (Sandbox Code Playgroud)

    background.js

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