Is cross-origin postMessage broken in IE10?

I was mistaken when I originally posted this answer: it doesn't actually work in IE10. Apparently people have found this useful for other reasons so I'm leaving it up for posterity. Original answer below:


Worth noting: the link in that answer you linked to states that postMessage isn't cross origin for separate windows in IE8 and IE9 -- however, it was also written in 2009, before IE10 came around. So I wouldn't take that as an indication that it's fixed in IE10.

As for postMessage itself, http://caniuse.com/#feat=x-doc-messaging notably indicates that it's still broken in IE10, which seems to match up with your demo. The caniuse page links to this article, which contains a very relevant quote:

Internet Explorer 8+ partially supports cross-document messaging: it currently works with iframes, but not new windows. Internet Explorer 10, however, will support MessageChannel. Firefox currently supports cross-document messaging, but not MessageChannel.

So your best bet is probably to have a MessageChannel based codepath, and fallback to postMessage if that doesn't exist. It won't get you IE8/IE9 support, but at least it'll work with IE10.

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


Create a proxy page on the same host as launcher. Proxy page has an iframe with source set to remote page. Cross-origin postMessage will now work in IE10 like so:

  • Remote page uses window.parent.postMessage to pass data to proxy page. As this uses iframes, it's supported by IE10
  • Proxy page uses window.opener.postMessage to pass data back to launcher page. As this is on same domain - there are no cross-origin issues. It can also directly call global methods on the launcher page if you don't want to use postMessage - eg. window.opener.someMethod(data)

Sample (all URLs are fictitous)

Launcher page at 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>

Proxy page at 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>

Remote page at 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>