在IE10中,交叉源postMessage被破坏了吗?

我试图做一个微不足道的postMessage示例工作…

  • 在IE10中
  • 在窗口/选项卡之间(与iframes)
  • 在起源之间

删除这些条件中的任何一个,并且事情工作正常:-)

但据我所知,当两个窗口共享一个原点时,窗口间postMessage只能在IE10中工作。 (事实上​​,也是奇怪的是,这种行为比这个稍微宽松一些:共享一个主机的两个不同的起源似乎也起作用)。

这是一个logging的错误? 任何解决方法或其他build议?

(注: 这个问题涉及的问题,但其答案是关于IE8和IE9 – 不是10)


更多细节+例子…

启动页面演示

 <!DOCTYPE html> <html> <script> window.addEventListener("message", function(e){ console.log("Received message: ", e); }, false); </script> <button onclick="window.open('http://jsbin.com/ameguj/1');"> Open new window </button> </html> 

推出页面演示

 <!DOCTYPE html> <html> <script> window.opener.postMessage("Ahoy!", "*"); </script> </html> 

这工作在: http ://jsbin.com/ahuzir/1 – 因为这两个页面被托pipe在相同的来源(jsbin.com)。 但移动第二页在其他地方,并在IE10失败。

当我最初发布这个答案时,我错了:它实际上并没有在IE10中工作。 显然人们发现这有用的其他原因,所以我留给后代。 下面的原始答案:


值得注意的是:你链接到的那个链接指出, postMessage并不是IE8和IE9中独立窗口的交叉源,不过它也是在2009年IE10出现之前写的。 所以我不会认为这是在IE10中固定的。

至于postMessage本身, http://caniuse.com/#feat=x-doc-messaging明显地表明,它仍然在IE10中,这似乎与您的演示相匹配。; caniuse页面链接到这篇文章 ,其中包含一个非常相关的报价:

Internet Explorer 8+部分支持跨文档消息:它目前与iframe一起使用,但不是新窗口。 但是,Internet Explorer 10将支持MessageChannel。 Firefox目前支持跨文档消息,但不支持MessageChannel。

所以你最好的select是可能有一个基于MessageChannel的代码path,如果不存在,则回退到postMessage 。 它不会得到你的IE8 / IE9的支持,但至less它会与IE10的工作。

MessageChannel文档: http : //msdn.microsoft.com/en-us/library/windows/apps/hh441303.aspx

在启动器的同一个主机上创build一个代理页面。 代理页面的源代码设置为远程页面的iframe 。 在IE10中,跨源postMessage现在可以工作:

  • 远程页面使用window.parent.postMessage将数据传递给代理页面。 由于这使用iframe,它受IE10支持
  • 代理页面使用window.opener.postMessage将数据传递回启动页面。 由于这是在相同的领域 – 没有交叉来源的问题。 它也可以直接调用启动页面上的全局方法,如果你不想使用postMessage – 例如。 window.opener.someMethod(data)

示例(所有url都是虚构的)

启动页面http://example.com/launcher.htm

 <!DOCTYPE html> <html> <head> <title>Test launcher page</title> <link rel="stylesheet" href="/css/style.css" /> </head> <body> <script> function log(msg) { if (!msg) return; var logger = document.getElementById('logger'); logger.value += msg + '\r\n'; } function toJson(obj) { return JSON.stringify(obj, null, 2); } function openProxy() { var url = 'proxy.htm'; window.open(url, 'wdwProxy', 'location=no'); log('Open proxy: ' + url); } window.addEventListener('message', function(e) { log('Received message: ' + toJson(e.data)); }, false); </script> <button onclick="openProxy();">Open remote</button> <br/> <textarea cols="150" rows="20" id="logger"></textarea> </body> </html> 

代理页面http://example.com/proxy.htm

 <!DOCTYPE html> <html> <head> <title>Proxy page</title> <link rel="stylesheet" href="/css/style.css" /> </head> <body> <script> function toJson(obj) { return JSON.stringify(obj, null, 2); } window.addEventListener('message', function(e) { console.log('Received message: ' + toJson(e.data)); window.opener.postMessage(e.data, '*'); window.close(self); }, false); </script> <iframe src="http://example.net/remote.htm" frameborder="0" height="300" width="500" marginheight="0" marginwidth="0" scrolling="auto"></iframe> </body> </html> 

远程页面在http://example.net/remote.htm

 <!DOCTYPE html> <html> <head> <title>Remote page</title> <link rel="stylesheet" href="/css/style.css" /> </head> <body> <script> function remoteSubmit() { var data = { message: document.getElementById('msg').value }; window.parent.postMessage(data, '*'); } </script> <h2>Remote page</h2> <input type="text" id="msg" placeholder="Type a message" /><button onclick="remoteSubmit();">Close</button> </body> </html> 

build立在纠结的答案上,我使用下面的代码片段在IE11 [和模拟IE10模式]中取得了成功:

 var submitWindow = window.open("/", "processingWindow"); submitWindow.location.href = 'about:blank'; submitWindow.location.href = 'remotePage to comunicate with'; 

然后,我可以使用典型的postMessage堆栈进行通信,我在我的场景中使用了一个全局静态信使(尽pipe我不认为它有任何意义,我也附加了我的信使类)

 var messagingProvider = { _initialized: false, _currentHandler: null, _init: function () { var self = this; this._initialized = true; var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; var eventer = window[eventMethod]; var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message"; eventer(messageEvent, function (e) { var callback = self._currentHandler; if (callback != null) { var key = e.message ? "message" : "data"; var data = e[key]; callback(data); } }, false); }, post: function (target, message) { target.postMessage(message, '*'); }, setListener: function (callback) { if (!this._initialized) { this._init(); } this._currentHandler = callback; } } 

不pipe我多么努力,我都无法在IE9和IE8上运行

我的configuration在哪里工作:
IE版本:11.0.10240.16590,更新版本:11.0.25(KB3100773)

基于LyphTEC和Akrikos的解答,另一个解决方法是在一个空白的popup窗口中创build一个<iframe> ,这样就避免了单独的代理页面的需要,因为空白的popup框的起源与它的开启者相同。

启动页面http://example.com/launcher.htm

 <html> <head> <title>postMessage launcher</title> <script> function openWnd() { var w = window.open("", "theWnd", "resizeable,status,width=400,height=300"), i = w.document.createElement("iframe"); i.src = "http://example.net/remote.htm"; w.document.body.appendChild(i); w.addEventListener("message", function (e) { console.log("message from " + e.origin + ": " + e.data); // Send a message back to the source e.source.postMessage("reply", e.origin); }); } </script> </head> <body> <h2>postMessage launcher</h2> <p><a href="javascript:openWnd();">click me</a></p> </body> </html> 

远程页面在http://example.net/remote.htm

 <html> <head> <title>postMessage remote</title> <script> window.addEventListener("message", function (e) { alert("message from " + e.origin + ": " + e.data); }); // Send a message to the parent window every 5 seconds setInterval(function () { window.parent.postMessage("hello", "*"); }, 5000); </script> </head> <body> <h2>postMessage remote</h2> </body> </html> 

我不确定这是多么脆弱,但是它在IE 11和Firefox 40.0.3中工作。

现在,(2014-09-02),您最好的select是使用代理框架在msdn博客文章中详细解决此问题的解决方法: https : //blogs.msdn.microsoft.com/ieinternals/2009 / 09/15 / HTML5的实现的问题,在-IE8及更高版本/

这里是工作的例子: http : //www.debugtheweb.com/test/xdm/origin/

你需要在你的页面上设置一个与popup窗口相同来源的代理框架。 使用window.opener.frames[0]将信息从popup窗口发送到代理框架。 然后使用从代理框架到主页面的postMessage。

此解决scheme涉及将该网站添加到Internet Explore的可信站点,而不是在本地Intranet站点。 我在Windows 10 / IE 11.0.10240.16384,Windows 10 / Microsoft Edge 20.10240.16384.0和Windows 7 SP1 / IE 10.0.9200.17148中testing了这个解决scheme。 该页面不能包含在Intranet区域中

因此,打开Internet Explorerconfiguration(工具> Internet选项>安全>可信站点>站点),并添加页面,在这里我使用*来匹配所有的子域名。 确保页面在本地Intranet站点(工具> Internet选项>安全>本地Intranet>站点>高级)中列出。 重新启动浏览器并再次testing。

在Internet Explorer中添加到受信任的站点

Windows 10 / Microsoft Edge中,您将在控制面板> Internet选项中find该configuration。

UPDATE

如果这不起作用,您可以尝试重置工具> Internet选项>高级设置>重置Internet Explorer设置中的所有设置 ,然后重置: 请谨慎使用它 ! 那么你将需要重新启动你的系统。 之后,将网站添加到可信站点。

请参阅您的页面在“文件”>“属性”中的区域,或者使用右键单击。

在Internet Explorer中的页面属性

UPDATE

我在一个企业内部网,有时它工作,有时它不(自动configuration?我甚至开始责怪公司代理)。 最后我用这个解决schemehttps://stackoverflow.com/a/36630058/2692914 。

MessageChannel不适用于IE9-11之间的窗口/选项卡,因为它依赖postMessage,在这种情况下它仍然是破碎的。 “最佳”的解决方法是通过window.opener(即window.opener.somefunction(“somedata”))调用一个函数。

在这里更详细的解决方法