我发布以下代码:
的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都从后台页面接收消息,但只有其中一个能够回应。这是正常行为吗?
提前感谢您的回答。
答案 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" });
});