IE10中的跨源postMessage是否被破坏?

Bos*_*osh 90 html5 compatibility postmessage cross-browser internet-explorer-10

我正试图做一个简单的postMessage例子......

  • 在IE10中
  • 在窗口/标签之间(与iframe)
  • 跨越起源

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

但据我所知,postMessage当两个窗口共享一个原点时,窗口之间似乎只能在IE10中工作.(嗯,事实上 - 奇怪的是 - 行为稍微宽容一点:共享主机的两个不同的起源似乎也有效).

这是一个有记录的错误吗?有任何变通方法或其他建议吗?

(注意:这个问题触及了问题,但它的答案是关于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>
Run Code Online (Sandbox Code Playgroud)

推出了网页演示

<!DOCTYPE html>
<html>
  <script>
    window.opener.postMessage("Ahoy!", "*");
  </script>
</html>
Run Code Online (Sandbox Code Playgroud)

这适用于:http://jsbin.com/ahuzir/1 - 因为两个页面都托管在同一个源(jsbin.com).但是将第二页移到其他地方,它在IE10中失败了.

ShZ*_*ShZ 62

当我最初发布这个答案时,我错了:它在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.

所以你最好的选择可能是拥有一个MessageChannel基于代码的路径,postMessage如果不存在则回退到.它不会得到IE8/IE9的支持,但至少它可以与IE10一起使用.

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

  • 这个答案很烦人,因为它给了我们错误的希望.答案是:如果没有代理,它将无法工作,因为postMessage是_required_以使MessageChannel正常工作(至少在我见过的每个演示中).除非有人向我展示MessageChannel的演示,没有postMessage或postMessage('name','<domain>',[messageChannel.port2])工作跨域(我无法让它工作),我不会相信这没有代理框架工作. (9认同)
  • 你将如何创建一个基于`MessageChannel`的代码路径?您仍然需要运行`postMessage`来将通道的端口转到另一个窗口. (8认同)
  • MessageChannel不应该工作的原因与postMessage不相同.Microsoft需要修复跨进程编组.http://blogs.msdn.com/b/ieinternals/archive/2009/09/15/bugs-in-ie8-support-for-html5-postmessage-sessionstorage-and-localstorage.aspx (4认同)
  • 我不能为我的生活让postMessage使用最新版本的IE(11)和MessageChannel API来使用跨域弹出窗口.老实说,除了这个答案表明这个特定场景应该有效之外,我在InterWebs上找不到任何其他地方.任何人都可以指出一个证明它有效的例子吗?我永远感激不尽. (3认同)

Lyp*_*TEC 30

在与启动器相同的主机上创建代理页面.代理页面的iframe源设置为远程页面.跨域postMessage现在可以在IE10中工作,如下所示:

  • 远程页面用于window.parent.postMessage将数据传递到代理页面.因为它使用iframe,所以IE10支持它
  • 代理页面用于window.opener.postMessage将数据传递回启动器页面.由于这是在同一个域 - 没有跨源问题.如果你不想使用postMessage,它也可以直接调用启动器页面上的全局方法 - 例如.window.opener.someMethod(data)

示例(所有网址都是虚构的)

启动页面在 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>
Run Code Online (Sandbox Code Playgroud)

代理页面在 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>
Run Code Online (Sandbox Code Playgroud)

远程页面在 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>
Run Code Online (Sandbox Code Playgroud)

  • 是吧?...所有URL都是示例,并不意味着实际指向现有页面......从列出的源代码中,您可以确定需要做什么才能使其正常工作.. (8认同)

Bru*_*nec 24

在纠结的答案基础上,我在IE11 [和模拟IE10模式]中使用以下代码获得了成功:

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

然后我能够使用典型的postMessage堆栈进行通信,我在我的场景中使用了一个全局静态信使(虽然我不认为它有任何重要性,我也附加了我的信使类)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

无论我怎么努力,我都无法在IE9和IE8上运行

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

  • 我只是要说 - 如果其他人正在考虑这种解决方法,认为"没办法,那就不可能修复它" - 是的,它实际上修复了无法将postMessage发送到IE11中的window.opener.难以置信的. (6认同)