HTML5’s window.postMessage API

By  on  

I've create a MooTools plugin to wrap window.postMessage: PostMessager. Click here to download it!

HTML5 window.postMessage

One of the little known HTML5 APIs is the window.postMessage API.  window.postMessage allows for sending data messages between two windows/frames across domains.  Essentially window.postMessage acts as cross-domain AJAX without the server shims. Let's take a look at how window.postMessage works and how you can use it today in Firefox, IE8+, Opera, Safari, and Chrome.

Part One:  The Sender

The first part of the process is setting up a "source".  With the source, we will open a new window (or IFrame, if you'd prefer to), send the new window message (for the sake of our example, we'll do so every 6 seconds, and create an event listener for any response we receive from the destination window.

//create popup window
var domain = 'http://scriptandstyle.com';
var myPopup = window.open(domain + '/windowPostMessageListener.html','myWindow');

//periodical message sender
setInterval(function(){
	var message = 'Hello!  The time is: ' + (new Date().getTime());
	console.log('blog.local:  sending message:  ' + message);
	myPopup.postMessage(message,domain); //send the message and target URI
},6000);

//listen to holla back
window.addEventListener('message',function(event) {
	if(event.origin !== 'http://scriptandstyle.com') return;
	console.log('received response:  ',event.data);
},false);

I've used window.addEventListener which doesn't work with Internet Explorer (IE uses window.attachEvent). You'll want to use a function to normalize event assignment or use MooTools/jQuery/Dojo to do so.

Assuming the window opened properly, we send a message and specified URI match (protocol, hostname, and port, if present) that the destination window must currently be at (because the user may have changed the address of that subsequent window).  If the destination window has changed, the message will not be sent.

We've also created an event handler for receiving a message.  It's extremely important that you validate the event origin when receiving a message because the message handler accepts messages from any URI!  Once the origin is validated, you may handle the provided message in any way you'd like.

Here's what this looks like when using an IFrame:

//create popup window
var domain = 'http://scriptandstyle.com';
var iframe = document.getElementById('myIFrame').contentWindow;

//periodical message sender
setInterval(function(){
	var message = 'Hello!  The time is: ' + (new Date().getTime());
	console.log('blog.local:  sending message:  ' + message);
	iframe.postMessage(message,domain); //send the message and target URI
},6000);

Be sure to access the IFrame's contentWindow property -- not just the node itself.

Part Two:  The Destination

The second part of the process is getting the destination window ready.  The destination window features an event listener for the "message" event and should validate the message origin.  Again, message events are accepted from any location so it's extremely important that their origin is validated against a list of trusted origins.

//respond to events
window.addEventListener('message',function(event) {
	if(event.origin !== 'https://davidwalsh.name') return;
	console.log('message received:  ' + event.data,event);
	event.source.postMessage('holla back youngin!',event.origin);
},false);

The sample above sends a response back to the sender to confirm that the message was sent.  There are important event properties:

  • source - The source window/frame the message was sent from.
  • origin - The URI (protocol, domain, and port, if provided) match the message was sent from.
  • data - The actual message sent from the source.

All three of these components are essential to the messaging system and its validation.

Using window.postMessage

Like every other web technology, there's obvious danger that this technology could get used improperly if the source is not validated properly; it's up to you to make your application secure. window.postMessage is like the PHP of JavaScript technologies in that regard (oh, snap!).  window.postMessage is cool though, no?

Recent Features

  • By
    JavaScript Promise API

    While synchronous code is easier to follow and debug, async is generally better for performance and flexibility. Why "hold up the show" when you can trigger numerous requests at once and then handle them when each is ready?  Promises are becoming a big part of the JavaScript world...

  • By
    Chris Coyier’s Favorite CodePen Demos

    David asked me if I'd be up for a guest post picking out some of my favorite Pens from CodePen. A daunting task! There are so many! I managed to pick a few though that have blown me away over the past few months. If you...

Incredible Demos

  • By
    QuickBoxes for Dojo

    Adding to my mental portfolio is important to me. First came MooTools, then jQuery, and now Dojo. I speak often with Peter Higgins of Dojo fame and decided it was time to step into his world. I chose a simple but useful plugin...

  • By
    Scroll IFRAMEs on iOS

    For the longest time, developers were frustrated by elements with overflow not being scrollable within the page of iOS Safari.  For my blog it was particularly frustrating because I display my demos in sandboxed IFRAMEs on top of the article itself, so as to not affect my site's...

Discussion

  1. Makes me wish all browsers in the world were rocking full HTML5 support. A typical reason iframes are used is because the two parties have no control over each other so you can’t know for certain if the “sender” is going to support this or not. If you did, this should be used no question. cross-browser cross-domain iframe communication is one of the hackiest things I’ve ever worked with.

  2. DJ

    Nope… don’t see nuttin’ but a square box. Using latest Firefox on Win7 – just what are we supposed to be seeing?

    • Right… that’s the iFrame. Reading is hard, I guess.

  3. Nice writeup, David!

    Yes, postMessage *is* cool! :) + There are several libraries that help out with postMessage-based communication, either reducing boilerplate code or providing extra functionality: jsChannel http://goo.gl/3Ft4Y, easyXDM http://goo.gl/bX0xi and pmrpc http://goo.gl/R9pa (this one is mine – enables RPC and pubsub communication with windows/iframes and workers).

    p.s. the demo is showing a blank box for me also

  4. DJ, Ivan: You need to open your FireBug console to view the messages flying back and forth.

    • Pete K

      ok very weird, refreshed and it appears to work now!

  5. Pete K

    Opened firebug in FF 3.6, and saw the following error

    console is not defined
    console.log('davidwalsh.name: sending message: ' + message);
  6. Michael Tully

    Just had a loo ad this on the console, pretty sweet how they take “behind the scene’s” so to speak, I did notice as i was watching them speak to each other that an error arose when I clicked the “Message Event” Dropdown, I am using Safari Console, Heres what it said.
    Unsafe JavaScript attempt to access frame with URL http://davidwalsh.name/dw-content/window-post-message.php from frame with URL http://scriptandstyle.com/windowPostMessageListener.html. Domains, protocols and ports must match.
    Is this anything to worry about?

  7. Tom

    What if the client is using IE6 or IE7?

    • Pete K

      simple – if you cant do it for legacy browsers, then dont do it all.

  8. I’ve just done some additional tests and found that IE, 6 , 7, 8, 9 doesn’t allow window to window postMessage, only some will allow same window, iframe postMessage.

  9. Travis Chase

    Do you know if there is a Dojo wrapper for this function? Was looking for a Dojo way that wrapped postMessage to provide cross-browser support.

  10. Sebastian Lasse

    brilliant piece.
    @Travis Chase : would be cool to go to dojo. seems someone at least tried, but did not commit: http://www.instantcal.com/instantcal “Modified 05/01/09: added window.postMessage handling for InstantCal”

    However, wanted just mention that we should clearInterval when all data is ‘fetched’.

    It is fine for simple transports, but it is still the one, sitting on the back seat…
    youtube.com/watch?v=B5kHx0rGkec&feature=player_embedded

  11. Paul

    Does anyone know how to communicate between 2 iframes if one is on the local machine (c:\asdf.htm) and the other is on a domain ("http://dfdf.com") ?

    I can’t get postMessage to work from domain to local machine or vice vera.

    Or do you have a solution to run mp4 files on a local machine from a webpage that’s on http://asdfa.com ?

    Thanks
    Paul

  12. Ravikant Patel

    Thanks,
    It works for my issue related to send request to customer display unit.

  13. Thank you brother. I have been banging my head on the wall with the iframe’s security issues. This seems to be a great option to cross-communicate. I love HTML5!

  14. Great tutorial David, this was exactly what I was looking for! This technology opens the door for many cool new innovative things ;)

  15. Ciul

    Hi David,
    in MooTools I use:

    Element.NativeEvents.message = 2;
    

    So to add MooTools support of native message event. :D
    Thanks for the tuto.

  16. Gauri Padbidri

    How can we postMessage from the Main Window to a nested IFrame in an optimum way, that way we are NOT storing references of any IFrame sources as well ? Thanks !

    • Could you expound? I don’t understand what you mean.

  17. Kartik

    Please let me how to communicate between 2 windows if one is on the local machine (c:\Sample.htm) and the other is on a domain (“http://xyz.com”) ?

  18. nina

    hi. please let me know the steps in using this API. need help. Thanks :D

  19. anuelson

    Hi!
    can anyone tell whats the alternative code for postmessage for lower versions of Internet explorer.since IE6 does not support postMessage.tnx

  20. Beth

    Hi David, I have a question, if the sender is a HTTP call, can it make a connection to one on HTTPS?
    Thanks.

  21. Nageswara Rao

    Thank you sooooooooo much

  22. postMessage can accept an object/array (anything that can be JSON stringified). However, in my tests with IE8 (not sure about newer IEs) I find that a string can only be passed. For a shameless plug for Ext JS users, I created this for my own uses: https://github.com/mitchellsimoens/PostMessage

  23. Hi David, thanks for this. You’ve save my time and headache.

  24. brian

    Does this allow me to access params in the URL of the external window after a user grants access in an OAuth scenario? I can’t seem to get this to work.
    Thanks.

  25. Arnie Shore

    Say I want to use postMessage in an internal chat, in which the domain/pages uri differ only by port number, and say I know these ports.

    Since the description above suggests the receiver validate the origin, I assume the browser does not. And that I can then postMessage port by port.

    No?

  26. Mk

    Hi,

    Will there be any issue, if you send post message frequently to target system. Any change in performance or lag?

  27. Naveed Zahoor

    One other method I found useful is to save into localStorage and the read from it.

  28. mukesh

    I have two different site like site1 and site2
    i fire broadcast from site1 and get in site2
    *its working fine*

    But how to return site2 to site1 response
    because i want response from site2 to site1

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!