Window.postMessage

  • Revision slug: DOM/window.postMessage
  • Revision title: window.postMessage
  • Revision id: 68509
  • Created:
  • Creator: Waldo
  • Is current revision? No
  • Comment add minversion

Revision Content

{{template.DomRef()}} {{template.Fx_minversion_header(3)}}

Summary

window.postMessage is a method for safely enabling cross-origin communication. Normally, scripts on different pages are only allowed to access each other if and only if the pages which executed them are at locations with the same protocol (usually both http), port number (80 being the default for http), and host (modulo document.domain being set by both pages to the same value). window.postMessage provides a controlled mechanism to circumvent this restriction in a secure way.

window.postMessage, when called, constructs a MessageEvent with type message and dispatches it to the main document (i.e. window.document) in the window upon which it was called. The event has a data property which is set to the string value of the argument provided to window.postMessage, domain and uri properties which are set to the host name (never including a port number) and absolute URI of the main document in the window calling window.postMessage, and a source property which is the window from which window.postMessage is called. (All the other standard properties of events are, of course, also present.) The event then goes through the standard capturing, targeting, and bubbling phases at which point window.postMessage returns. The target window can listen for dispatched messages by calling:

document.addEventListener("message", receiveFunc, false);

If during the process of dispatch an exception is thrown, that exception terminates event handling in the usual manner. However, the exception is never propagated to the caller of window.postMessage, even when the calling window and the target window are same-origin.

Secure use of this method of communication relies upon:

  • pages which don't need it not registering event listeners for the type message
  • pages which do need it carefully vetting the sender using event.domain and possibly event.uri/event.source before using the message contained in event.data

In the latter case, not checking the values of the authentication properties before using the sent message constitutes a cross-site scripting hole.

Syntax

otherWindow.postMessage(message);

Parameters

  • otherWindow is a reference to another window; such a reference may be obtained, for example, using the contentWindow property of an iframe element, the return value of window.open, or by named or numeric index on window.frames.
  • message is string data to be sent to the other window

Example

/*
 * In window A's scripts, with A being on example.com
 */

var popup = window.open(...popup details...);

// ...when the popup has fully loaded, if not blocked by a popup blocker
popup.postMessage("hello there!");

function receiveMessage(event)
{
  // Do we trust the sender of this message?  (might be
  // different from what we originally opened, for example)
  if (event.domain != "example.org")
    return;

  // event.source is popup
  // event.uri is the absolute URI of the current main document in the popup
  // event.data is "hi there yourself!"
}
/*
 * In the popup's scripts, running on example.org
 */

function receiveMessage(event)
{
  // Do we trust the sender of this message?
  if (event.domain != "example.com")
    return;

  // event.source is the same as window.opener
  // event.uri is the absolute URI of the current main document in window A
  // event.data is "hello there!"
  event.source.postMessage("hi there yourself!");
}

document.addEventListener("message", receiveMessage, false);

Notes

Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message. Consequently, any event listener used to receive messages must first check the identity of the sender of the message, using the domain and possibly uri/source properties. This has already been mentioned once, but it cannot be understated: Failure to check the domain and possibly uri/source properties enables cross-site scripting attacks.

If in the process of handling the dispatched event an event handler throws an exception, that exception will terminate the dispatch process in the same way as happens with normal events (i.e. any other event listeners on the current node in dispatch are called, but dispatch proceeds to no other nodes). However, the exception will not be propagated to the caller of window.postMessage. In particular, the caller of window.postMessage will not see the exception even in the case where the target window has the same origin as the window calling window.postMessage.

The value of the domain property of the dispatched event is not affected by the current value of document.domain in the calling window.

window.postMessage is available to JavaScript running in chrome code (e.g. in extensions), but the source property of the dispatched event is always null as a security restriction. (The other properties have their expected values.)

Specification

window.postMessage is defined by the draft HTML5 specification.

See also

document.domain

Revision Source

<p>
{{template.DomRef()}}
{{template.Fx_minversion_header(3)}}
</p>
<h3 name="Summary"> Summary </h3>
<p><code>window.postMessage</code> is a method for safely enabling cross-origin communication.  Normally, scripts on different pages are only allowed to access each other if and only if the pages which executed them are at locations with the same protocol (usually both <code>http</code>), port number (<code>80</code> being the default for <code>http</code>), and host (modulo <a href="en/DOM/document.domain">document.domain</a> being set by both pages to the same value).  <code>window.postMessage</code> provides a controlled mechanism to circumvent this restriction in a secure way.
</p><p><code>window.postMessage</code>, when called, constructs a <a href="en/MessageEvent">MessageEvent</a> with type <code>message</code> and dispatches it to the main document (i.e. <code>window.document</code>) in the window upon which it was called.  The event has a <code>data</code> property which is set to the string value of the argument provided to <code>window.postMessage</code>, <code>domain</code> and <code>uri</code> properties which are set to the host name (never including a port number) and absolute URI of the main document in the window calling <code>window.postMessage</code>, and a <code>source</code> property which is the window from which <code>window.postMessage</code> is called.  (All the other standard properties of events are, of course, also present.)  The event then goes through the standard capturing, targeting, and bubbling phases at which point <code>window.postMessage</code> returns.  The target window can listen for dispatched messages by calling:
</p>
<pre class="eval">document.addEventListener("message", receiveFunc, false);
</pre>
<p>If during the process of dispatch an exception is thrown, that exception terminates event handling in the usual manner.  However, the exception is <i>never</i> propagated to the caller of <code>window.postMessage</code>, even when the calling window and the target window are same-origin.
</p><p>Secure use of this method of communication relies upon:
</p>
<ul><li> pages which don't need it not registering event listeners for the type <code>message</code>
</li><li> pages which do need it carefully vetting the sender using <code>event.domain</code> and possibly <code>event.uri</code>/<code>event.source</code> before using the message contained in <code>event.data</code>
</li></ul>
<p>In the latter case, <b>not checking the values of the authentication properties before using the sent message constitutes a cross-site scripting hole</b>.
</p>
<h3 name="Syntax"> Syntax </h3>
<pre class="eval">otherWindow.postMessage(message);
</pre>
<h3 name="Parameters"> Parameters </h3>
<ul><li> <code>otherWindow</code> is a reference to another window; such a reference may be obtained, for example, using the <code>contentWindow</code> property of an <code>iframe</code> element, the return value of <a href="en/DOM/window.open">window.open</a>, or by named or numeric index on <a href="en/DOM/window.frames">window.frames</a>.
</li><li> <code>message</code> is string data to be sent to the other window
</li></ul>
<h3 name="Example"> Example </h3>
<pre class="eval">/*
 * In window A's scripts, with A being on example.com
 */

var popup = window.open(...popup details...);

// ...when the popup has fully loaded, if not blocked by a popup blocker
popup.postMessage("hello there!");

function receiveMessage(event)
{
  // Do we trust the sender of this message?  (might be
  // different from what we originally opened, for example)
  if (event.domain != "example.org")
    return;

  // event.source is popup
  // event.uri is the absolute URI of the current main document in the popup
  // event.data is "hi there yourself!"
}
</pre>
<pre class="eval">/*
 * In the popup's scripts, running on example.org
 */

function receiveMessage(event)
{
  // Do we trust the sender of this message?
  if (event.domain != "example.com")
    return;

  // event.source is the same as window.opener
  // event.uri is the absolute URI of the current main document in window A
  // event.data is "hello there!"
  event.source.postMessage("hi there yourself!");
}

document.addEventListener("message", receiveMessage, false);
</pre>
<h3 name="Notes"> Notes </h3>
<p>Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message.  Consequently, any event listener used to receive messages <b>must</b> first check the identity of the sender of the message, using the <code>domain</code> and possibly <code>uri</code>/<code>source</code> properties.  This has already been mentioned once, but it cannot be understated: <b>Failure to check the <code>domain</code> and possibly <code>uri</code>/<code>source</code> properties enables cross-site scripting attacks.</b>
</p><p>If in the process of handling the dispatched event an event handler throws an exception, that exception will terminate the dispatch process in the same way as happens with normal events (i.e. any other event listeners on the current node in dispatch are called, but dispatch proceeds to no other nodes).  However, <i>the exception will not be propagated to the caller of <code>window.postMessage</code></i>.  In particular, the caller of <code>window.postMessage</code> will not see the exception even in the case where the target window has the same origin as the window calling <code>window.postMessage</code>.
</p><p>The value of the <code>domain</code> property of the dispatched event is not affected by the current value of <code>document.domain</code> in the calling window.
</p><p><code>window.postMessage</code> is available to JavaScript running in chrome code (e.g. in extensions), but the <code>source</code> property of the dispatched event is always <code>null</code> as a security restriction.  (The other properties have their expected values.)
</p>
<h3 name="Specification"> Specification </h3>
<p><code>window.postMessage</code> is defined by the <a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html#crossDocumentMessages">draft HTML5 specification</a>.
</p>
<h3 name="See_also"> See also </h3>
<p><a href="en/DOM/document.domain">document.domain</a>
</p>
Revert to this revision