我正在编写一个浏览器扩展程序,通过默认的消息传递接口完成大部分通信,例如chrome扩展帖子连接“postMessage”和safari,“tab.dispatchMessage”。
但是我有一些简单的消息,有助于识别顶部框架内的子框架元素,我不想将它们发送到后台脚本,我不想纯粹使用标准的window.postMessage方法。
问题是内框并不总是从顶部框架发送消息。 (当我向内框发送消息时,我几乎可以确定它已被加载)。
所以基本上我的问题是如何做到这一点,以及如何确保我的来自顶部框架的消息到达内部框架。
编辑:最小代码示例
// SCRIPT WHICH IS RUNNING IN INNER FRAME
// this is where the algorithm starts
var uuid = "unique generated id";
// STEP 4
// this is where the message send via frames[i].contentWindow.postMessage
// should be received, and this is where the problem is (it's not received sometimes, or to be more clear, not received on some pages)
window.addEventListener("message", function (event) {
var message = JSON.parse(event.data);
if (message.uuid === uuid) {
event.source.postMessage(event.data, "*");
}
});
// STEP 1
// send identifier to top frame letting it know that inner frame
// loaded and needs to be mapped
window.top.postMessage(JSON.stringify({uuid: uuid}), "*");
-
// SCRIPT WHICH IS RUNNING IN TOP FRAME
// this script is loaded before inner frame thus is able
// receive messages from inner frames all the time
var frames = document.getElementsByTagName("iframe");
var callMap = {}, frameMap = {};
// STEP 2
window.addEventListener("message", function (event) {
var message = JSON.parse(event.data);
// when inner frame send message with uuid but with ack
// it needs to be mapped, the sending inner frame uuid
// will be sent to all frames with additional (ack) id
if (message.uuid && !message.ack) {
callMap[message.uuid] = {};
for (var i = 0, len = frames.length; i < len; i++) {
var ack = "another unique id";
callMap[message.uuid][ack] = frames[i];
// STEP 3
frames[i].contentWindow.postMessage(JSON.stringify({
uuid: message.uuid, ack: ack
}), "*");
}
}
if (message.ack) {
frameMap[message.uuid] = callMap[message.uuid][message.ack];
delete callMap[message.uuid];
}
});