IFrame和IFrame之间的跨文档消息传递问题家长
Issues with Cross Document Messaging between IFrame & Parent
我有一个应用程序在一个"外国"页面(不同的域等)的iframe内运行。允许iframe &在父页面上,我在父页面上加载了一些脚本,并使用postMessage
进行一些跨文档消息传递。
大多数情况下,这种沟通是预期的,但有时我看到一些错误报告到我的错误跟踪工具,却不知道为什么会发生。
下面是一些示例代码: PluginOnParent.js
// ...
window.addEventListener('message', function(e) {
// Check message origin etc...
if (e.data.type === 'iFrameRequest') {
e.source.postMessage({
type: 'parentResponse',
responseData: someInterestingData
}, e.origin);
}
// ...
}, false);
// ...
AppInsideIFrame.js
// ...
var timeoutId;
try {
if (window.self === window.top) {
// We're not inside an IFrame, don't do anything...
return;
}
} catch (e) {
// Browsers can block access to window.top due to same origin policy.
// See http://stackoverflow.com/a/326076
// If this happens, we are inside an IFrame...
}
function messageHandler(e) {
if (e.data && (e.data.type === 'parentResponse')) {
window.clearTimeout(timeoutId);
window.removeEventListener('message', messageHandler);
// Do some stuff with the sent data
}
}
timeoutId = window.setTimeout(function() {
errorTracking.report('Communication with parent page failed');
window.removeEventListener('message', messageHandler);
}, 500);
window.addEventListener('message', messageHandler, false);
window.parent.postMessage({ type: 'iFrameRequest' }, '*');
// ...
当超时到达并报告错误时,这里会发生什么?
更多信息&我的想法:
- 我自己无法控制父页面
- 它似乎不是一个一般的"配置"问题(CORS等),因为错误发生在它大部分时间工作的同一页面 我们不支持IE <和其他"遗留"的浏览器版本,所以这些都不是问题在这里>
- 我的错误报告工具报告了许多不同的浏览器,其中包括最新版本的浏览器(FF 49, Android 5上的Chrome 43, Win和Android 6上的Chrome 53, Mobile Safari 10,…)
- 因此,这似乎不是一个与特定浏览器或版本相关的问题。
- 500毫秒的超时只是一些神奇的数字,我选择了我认为将是完全安全的…
问题似乎是在你的PluginOnParent.js,你在哪里发送你的响应。而不是使用"e.o origin"(在开发人员工具中检查后返回"null")—尝试使用文字"*",正如以下文档中关于postMessage用法的说明(在targetOrigin的描述中):
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage另外,作为奖励,我刚刚在两个不同的域测试了这个,它也有效。我将Parent.html放在一个域的web服务器上,并将iframe的src更改为另一个完全不同域的child.html,它们可以很好地通信。
Parent.html
<html>
<head>
<script type="text/javascript">
function parentInitialize() {
window.addEventListener('message', function (e) {
// Check message origin etc...
if (e.data.type === 'iFrameRequest') {
var obj = {
type: 'parentResponse',
responseData: 'some response'
};
e.source.postMessage(obj, '*');
}
// ...
})
}
</script>
</head>
<body style="background-color: rgb(72, 222, 218);" onload="javascript: parentInitialize();">
<iframe src="child.html" style="width: 500px; height:350px;"></iframe>
</body>
</html>
Child.html
<html>
<head>
<script type="text/javascript">
function childInitialize() {
// ...
var timeoutId;
try {
if (window.self === window.top) {
// We're not inside an IFrame, don't do anything...
return;
}
} catch (e) {
// Browsers can block access to window.top due to same origin policy.
// See http://stackoverflow.com/a/326076
// If this happens, we are inside an IFrame...
}
function messageHandler(e) {
if (e.data && (e.data.type === 'parentResponse')) {
window.clearTimeout(timeoutId);
window.removeEventListener('message', messageHandler);
// Do some stuff with the sent data
var obj = document.getElementById("status");
obj.value = e.data.responseData;
}
}
timeoutId = window.setTimeout(function () {
var obj = document.getElementById("status");
obj.value = 'Communication with parent page failed';
window.removeEventListener('message', messageHandler);
}, 500);
window.addEventListener('message', messageHandler, false);
window.parent.postMessage({ type: 'iFrameRequest' }, '*');
// ...
}
</script>
</head>
<body style="background-color: rgb(0, 148, 255);" onload="javascript: childInitialize();">
<textarea type="text" style="width:400px; height:250px;" id="status" />
</body>
</html>
希望有帮助!
大多数时候,这种交流都是按计划进行的,但有时我看到一些错误报告到我的错误跟踪工具,无法计算找出它们发生的原因。
当超时到达并报告错误时,这里会发生什么?
我自己无法控制父页面
不确定函数errorTracking.report
在调用时做什么,虽然没有出现与message
事件有关的实际错误?
500ms的超时时间只是我选择的一个神奇的数字本以为会完全安全的…
如果duration
设置在500
, setTimeout
可以在window
触发message
事件之前被调用。
timeoutId = window.setTimeout(function() {
errorTracking.report('Communication with parent page failed');
window.removeEventListener('message', messageHandler);
}, 500);
将setTimeout
的duration
调整为更长的持续时间。
或者用onerror
处理器或window.addEventListener
代替setTimeout
指出例如当脚本中出现语法错误时,从不同的来源,语法错误的细节不报告给防止信息泄漏(见bug 363897)。而是错误报告的只是"脚本错误"。中可以重写此行为有些浏览器使用了cross - origin属性服务器发送相应的
CORS
HTTP响应头。一个解决方法是隔离"脚本错误",并知道如何处理它错误细节只能在浏览器控制台中查看,而不能
// handle errors
onerror = function messageErrorHandlerAtAppInsideIFrame(e) {
console.error("Error at messageErrorIndex", e)
}
来处理在不同上下文或源之间通信期间的任何实际错误。
在iframe
的load
事件中使用postMessage
与父window
的message
处理程序通信。
http://plnkr.co/edit/M85MDHF1kPPwTE2E0UGt?p =预览
- 为什么我得到Chrome本机消息“;找不到指定的本机消息传递主机&”;
- 消息传递系统 jquery 发送jQuery514109241_1210239812938当我在消息中放入:))时
- 有没有一种简单的转换方法可以将chrome消息传递转换为safari消息传递语法
- 消息传递接收端
- 基本的谷歌chrome扩展消息传递不起作用
- Chrome 扩展消息传递体系结构
- 为什么我无法将此消息传递到选项卡中运行的所有帧
- Chrome扩展消息传递:未发送响应
- 为什么在定义回调/侦听器函数(异步消息传递,port.on)后没有立即设置全局变量
- Chrome 消息传递.未捕获错误:连接到扩展时出错
- 如何将 iframe 数据传递到父窗口
- 在 MQTT 客户端中“未捕获的引用错误:未定义消息传递”
- 用于 SMS 消息传递的 window.location.href - 平台兼容性
- 谷歌打包应用原生消息传递
- 消息传递在 Chrome 19 中断开
- 获取频道中的消息数,而无需在 Twilio IP 消息传递中检索它们
- PHP 和 Jquery 之间的消息传递
- 加载从跨文档消息传递中作为事件数据获得的 pdf
- 两个窗口或选项卡之间的跨文档消息传递,而不是iframe
- IFrame和IFrame之间的跨文档消息传递问题家长