Cross-Document Messaging with postMessage

JavaScript can be used to communicate between documents when using iframes, as discussed at Iframes and Cross-Document Communication. However, if the documents are not on the same domain, the Same Origin Policy prevents access to most objects and properties and will trigger access denied errors when JavaScript attempts communication.

Cross-Document Messaging with postMessage is designed to provide a safe means of communication between documents on different domains while still offering protection from cross-site scripting attacks. This method can be used with iframes as well as between windows when the window.open method is used by one to open another.

Current browsers fully support the postMessage method.[1] Internet Explorer starting with version 8 also provides partial support for postMessage, although not supporting its use with window.open.

How to Use postMessage

There are two basic components to cross-document messaging: the postMessage method invocation, and the onmessage event handler set up in the receiving document to respond to incoming messages.

To send a message from one document to another, begin by obtaining a reference to the window you want to send a message to. If sending a message to a document in an iframe, first get a reference to the iframe and then its contentWindow property as shown below. If sending a message from the iframed document to the containing document, the parent keyword provides a reference. (See example.)

If sending a message to a window opened using the window.open method, a reference is returned from the method. If sending a message from a window opened using the window.open method, the opener property of the window provides that reference.

postMessage Arguments

The postMessage method takes two arguments:[2] the message to be sent (data), and the domain to which you wish to send it (formally referred to as the target origin):

// get reference to window inside the iframe
var wn = document.getElementById('ifrm').contentWindow;
// postMessage arguments: data to send, target origin
wn.postMessage('Hello to iframe from parent!', 'http://www.example.com');

The postMessage method supports data types including strings, numbers, arrays, and objects. However, some older browsers only support passing strings in postMessage. The JSON.stringify method can be used to convert more complex data types to strings if you wish to support older browsers, as most of our examples demonstrate.

The target origin argument includes the protocol, host, and optionally, the port of the document to receive the message. Target origin can also be specified using an "*" (any origin) or "/" (the same origin as the document sending the message).[3] If the origin of the target window doesn't match the specified origin, the message is not sent.

The Message Event

When a message is sent using postMessage, a message event is fired on the destination window. In order to process the event, you need a message event handler. You can use addEventListener to assign a handler to the message event, including attachEvent for Internet Explorer 8 if you like, or you can assign a function to the onmessage property of the window object. [4]

// Assign handler to message event
if ( window.addEventListener ) {
    window.addEventListener('message', handleMessage, false);
} else if ( window.attachEvent ) { // ie8
    window.attachEvent('onmessage', handleMessage);
}

An event object is passed to the message event handler. The message event includes the following properties:

data
the message being sent
origin
the origin of the document that sent the message (protocol, hostname, and possibly port)
source
a reference to the window object from which the message came

The following message event handler function demonstrates how these properties can be used:

// message event handler (e is event object) 
function handleMessage(e) {
    // Reference to element for data display
    var el = document.getElementById('display');
    // Check origin
    if ( e.origin === 'http://www.example.com' ) {
        // Retrieve data sent in postMessage
        el.innerHTML = e.data;
        // Send reply to source of message
        e.source.postMessage('Message received', e.origin);
    }
}

Security Considerations

The postMessage specification recommends the following steps to ensure the safety of the process when using cross-document messaging:

  • Check the origin attribute to ensure that messages are only accepted from domains that you expect to receive messages from.
  • If you don't check the origin attribute and instead accept messages from any origin, keep in mind the potential risk for denial-of-service attacks. Controlling the number of messages accepted per minute could offer protection in this case.
  • Check the data received to be sure it is the type of data you are expecting.
  • Don't use the wildcard target origin ("*") when sending messages that contain confidential information.

postMessage Examples

Examples demonstrate using postMessage to:

  • Send form data to a hidden iframe on another domain.
  • Set the height of an iframe to display all of its content when its document is on another domain.
  • Obtain information from and interact with objects and properties in documents on another domain.

  1. See Can I Use for details on browser support for the postMessage method. ^
  2. An optional transfer argument can be included as described at HTML5 Web Messaging. ^
  3. Older browsers, such as Internet Explorer 8 and 9, don't support '/' as target origin. ^
  4. The JavaScript Event Handling Tutorial describes some drawbacks when assigning an event handler to a property such as onmessage. It also covers the differences in the event model for Internet Explorer 8 and how to address them. ^