Cross-Window Messaging

Another new feature from the HTML 5 specification, that just landed for Firefox 3, is the cross-origin postMessage API.

This particular API adds a new method to every window (including the current window, popups, iframes, and frames) that allows you to send textual messages from your current window to any other – regardless of any cross-domain policies that might exist.

Specifically, you’re given a new window.postMessage(“string”) method that generates a message DOM event on the document of the receiving document. This event object contains the message as a property: event.data which the receiving document can use however they see fit.

Obviously communicating in a cross-domain fashion is prone to abuse so there’s additional information passed along that can be used to verify the integrity of the message. The full list of properties include:

  • .data – A string holding the message passed from the other window.
  • .domain – The domain name of the window that sent the message.
  • .uri – The full URI for the window that sent the message.
  • .source – A reference to the window object of the window that sent the message.

The last property is especially important as it allows for two-way communication to occur between these windows.

Simple Demo

I’ve constructed a simple demo that you can try (requires a nightly of Firefox 3) in which you can send a message – through an iframe – to another domain, having the results be received and rendered by it. Thus, this demos consists of two pages: One acting as the sender (on ejohn.org), one acting as the receiver (on dev.jquery.com).

This first page is the sender – it’s calling postMessage (sending the textual message) and also holds the iframe within which the receiving window is held.

<iframe src="http://dev.jquery.com/~john/message/" id="iframe"></iframe>
<form id="form">
  <input type="text" id="msg" value="Message to send"/>
  <input type="submit"/>
</form>
<script>
window.onload = function(){
        var win = document.getElementById("iframe").contentWindow;
        document.getElementById("form").onsubmit = function(e){
                win.postMessage( document.getElementById("msg").value );
                e.preventDefault();
        };
};
</script>

The follow page is the receiver – it has an event listener bound which watches for messages being passed to it and injects them in to the DOM.

<b>This iframe is located on dev.jquery.com</b>
<div id="test">Send me a message!</div>
<script>
document.addEventListener("message", function(e){
        document.getElementById("test").textContent =
                e.domain + " said: " + e.data;
}, false);
</script>

Security Concerns

Some care was taken in the construction of this API to prevent some basic forms of spoofing and security circumvention. In total, there’s a couple points to remember:

  1. If you’re expecting a message from a specific domain, set of domains, or even a specific url, please remember to verify the .domain or .uri properties as they come in, otherwise another page will be bound to spoof this event for malicious purposes.
  2. Just because a string is coming in, as a message, doesn’t mean that it’s completely safe. Note that in the example, above, I inject the string using .textContent, this is intentional. If I were to inject it using .innerHTML, and the message contained a script tag, it would execute immediately upon injection. This is a critical point: You’ll need to be sure to purify all your incoming messages before they are used and injected into the DOM (or sent to the server). This is the same that you would do on the server-side of your application, be sure to take the same precautions here, as well. Update: Ok, this isn’t so much of an issue anymore – it was in Firefox 2, but since only Firefox 3 supports this new feature, it’s perfectly ok – false alarm.

Security concerns aside, I think this feature has a ton of potential, especially in the way of developing scalable widget solutions (especially ones that continue to uphold security and cross-domain principles). I suspect that upon further adoption we’ll begin to see a number of resources (such as iGoogle and Netvibes) take advantage of this incredible power, allowing for more-complex widgets and browser-based applications.

Update: The following browsers support, or will support, postMessage:

  • Opera 9 supports document.postMessage() (although, the rest appears to be the same).
  • Firefox 3 beta 3 will have support for window.postMessage().
  • WebKit Nightlies currently supports window.postMessage() which will land in some future release of Safari.

Posted: February 10th, 2008


Subscribe for email updates

17 Comments (Show Comments)



Comments are closed.
Comments are automatically turned off two weeks after the original post. If you have a question concerning the content of this post, please feel free to contact me.


Secrets of the JavaScript Ninja

Secrets of the JS Ninja

Secret techniques of top JavaScript programmers. Published by Manning.

John Resig Twitter Updates

@jeresig / Mastodon

Infrequent, short, updates and links.