postMessage still broken on IE11?

Is it broken? Well, sort of.

I tried various ideas and couldn’t get the code in your jsFiddle to work. Looking at this MSDN Blog post, we find that postMessage only works between IFrames in older versions of IE, which has yet to be fixed for IE 11.

That article links to a demo of the problem. There are a couple of workarounds that involve calling scripts on the window.opener. However, as that blog states (emphasis mine):

Unfortunately, this workaround often isn’t possible, because same-origin-policy dictates that the popup window and the window.opener page must be from the same origin in order to call each other’s script functions.

So it looks like the only way to do this is something like this, where the child is hosted in an IFrame in the parent. I have created a similar demo here, based on the code in yours. It’s pretty simple, but posts a message to the contentWindow of the IFrame, which in turn responds.

I see the recommendation to use MessageChannel instead, but I also wonder if using Web Workers might be worth investigating, though their use would of course depend on the nature of your task. There is also the answer to this question, where the IFrame approach was used, but a jQuery UI dialog was used to display it – I would imagine you could do the same thing with modals in Bootstrap if you prefer that.


For reference:

HTML

<iframe id="iframe" src="http://jsbin.com/iLapokOS/7/"></iframe>
<div id="log"></div>
<button id="post-message-button">Post message to window</button>

Parent script

var wnd;

$(document).ready(function() {
    $('#log').append('listening...');

    wnd = $('#iframe')[0].contentWindow;

    window.addEventListener('message', function(e){
      $('#log').append('<br/>Received message: ' + JSON.stringify(e.data));
    }, false);

    $('#post-message-button').click(function() {
        if(!wnd){
            return;
        }
        $('#log').append('<br/>sending...');
        wnd.postMessage('Hello?', 'http://jsbin.com');
    });
});

Child HTML and JS

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
  <script>
    $(document).ready(function() {

      window.addEventListener("message", function(e){
        $('body').append('<br/>Origin: ' + e.origin);        
        $('body').append("<br/>Received message: " + JSON.stringify(e.data));

        e.source.postMessage('Hello yourself', e.origin);
      }, false);
    });
  </script>


</body>
</html>

Update 16/01: The really bad part is that it does break even if the message is send from the same domain, but after being redirected by another domain.

Hilariously, this “security feature” can be used in reverse to bypass the crossdomain restriction entirely.

In parent window at example.com:

<script>
  window.open("http://example.com/dummy_redirect");
  window.addEventListener('message', function(ev) {console.log(ev.data)})
</script>

On example.com server:

GET /dummy_redirect 302 http://jsfiddle.net/b6yfbunw/

A popup will open to your domain, redirect to jsfiddle, and the postMessage call will work in IE. You can even navigate to any domain after that and continue to make postMessage calls to the parent window.

Leave a Comment