内容脚本和背景页面之间的消息传递在chrome扩展是不工作,因为它应该是

messaging between content script and background page in a chrome extension is not working as it is supposed to be

本文关键字:工作 扩展 因为 chrome 背景 脚本 消息传递 之间      更新时间:2023-09-26

我把代码贴在下面:

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都收到来自后台页面的消息,但只有其中一个能够响应。这是正常的行为吗?

谢谢你的回答。

你只发送一个消息与直接回调,所以自然Chrome可以使用这个响应回调只是一次(这是一个一次性连接到一个实体,无论是页面或iframe)。

  • 解决方案1:显式地向每个iframe发送多个消息:

    清单。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!");
    });
    

Chrome扩展中内容脚本和背景页面之间的通信

内容脚本到背景页

发送信息到后台页面

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

从内容脚本接收信息

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

背景页到内容脚本

发送信息到内容脚本

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

从后台页面接收信息

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

您可以使用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就足够了,也许你可以使用框架在层次结构中的位置。