Window.postMessage

  • Revision slug: DOM/window.postMessage
  • Revision title: window.postMessage
  • Revision id: 68517
  • Created:
  • Creator: Waldo
  • Is current revision? No
  • Comment clarify data/javascript status

Revision Content

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

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 way which is secure when properly used.

Summary

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, an origin property corresponding to 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.

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 have the same origin.

Syntax

otherWindow.postMessage(message [, targetOrigin]);
otherWindow
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
String data to be sent to the other window.
targetOrigin (optional)
If present, causes the message to be sent only if otherWindow has the same origin as targetOrigin (and otherwise do nothing). targetOrigin should be a URI, but only the protocol, host, and port portions of the URI are used in determining same-origin-ness. You should provide this argument for any message containing sensitive data (such as passwords) to avoid issues if the location of otherWindow is different from what you expect it to be (for example, because a malicious site changed the location of the window to which you're sending the message). A syntax error is thrown if this argument is not a valid URI.

The dispatched event

otherWindow can listen for dispatched messages by executing the following JavaScript:

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

function receiverFunc(event)
{
  if (event.origin !== "...")
    return;

  // ...
}

The properties of the dispatched message are:

data
A string holding the message passed from the other window.
origin
The origin of the window that sent the message. This string is the concatenation of the protocol and "://", the host name if one exists, and ":" followed by a port number if a port is present and differs from the default port for the given protocol. Examples of typical origins are https://example.org, http://example.net, and http://example.com:8080.
source
A reference to the window object that sent the message; you can use this to establish two-way communication between two windows with different origins.

Security concerns

If you do not expect to receive messages from other sites, you should not add any event listeners for message events. This is a completely foolproof way to avoid security problems.

If you do expect to receive messages from other sites, always verify the sender's identity using the origin and possibly source properties. Any window (including, for example, http://evil.example.com) can send a message to any other window, and you have no guarantees that an unknown sender will not send malicious messages. Having verified identity, however, you still should verify the syntax of the sent message. Otherwise, a security hole in the site you trusted to send only trusted messages could then open a cross-site scripting hole in your site.

Example

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

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

// When the popup has fully loaded, if not blocked by a popup blocker:

// This does nothing, assuming the window hasn't changed its location
popup.postMessage("The user is 'bob' and the password is 'secret'",
                  "https://secure.example.net");

// This will successfully send a message to the popup
popup.postMessage("hello there!", "http://example.org");

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

  // event.source is popup
  // event.data is "hi there yourself!"
}
document.addEventListener("message", receiveMessage, false);
/*
 * In the popup's scripts, running on example.org
 */

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

  // event.source is the same as window.opener
  // 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 origin and possibly source properties. This has already been mentioned once, but it cannot be understated: Failure to check the origin and possibly 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 origin property of the dispatched event is not affected by the current value of document.domain in the calling window.

For IDN host names only, the value of the origin property is not consistently Unicode or punycode; for greatest compatibility check for both the IDN and punycode values when using this property if you expect messages from IDN sites. It is expected that eventually this value will consistently be IDN, but for now you should handle both IDN and punycode forms.

The value of the origin property when the sending window contains a javascript: URL is the origin of the script that loaded the URL. The origin for data: URLs is currently the origin of the script that loaded the URL, but this is likely to change in the future. For now, you should avoid using postMessage within pages generated from data: URLs.

{{wiki.template('Non-standard_inline')}} window.postMessage is available to JavaScript running in chrome code (e.g. in extensions and privileged code), 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.Gecko_minversion_header(1.9)}}
{{template.Fx_minversion_header(3)}}
</p><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 way which is secure when properly used.
</p>
<h3 name="Summary"> Summary </h3>
<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>, an <code>origin</code> property corresponding to 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.
</p><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 have the same origin.
</p>
<h3 name="Syntax"> Syntax </h3>
<pre class="eval">otherWindow.postMessage(message [, targetOrigin]);
</pre>
<dl><dt> <code>otherWindow</code>
</dt><dd> 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>.
</dd><dt> <code>message</code>
</dt><dd> String data to be sent to the other window.
</dd><dt> <code>targetOrigin</code> (optional)
</dt><dd> If present, causes the message to be sent <i>only</i> if <code>otherWindow</code> has the same origin as <code>targetOrigin</code> (and otherwise do nothing).  <code>targetOrigin</code> should be a URI, but only the protocol, host, and port portions of the URI are used in determining same-origin-ness.  You should provide this argument for any message containing sensitive data (such as passwords) to avoid issues if the location of <code>otherWindow</code> is different from what you expect it to be (for example, because a malicious site changed the location of the window to which you're sending the message).  A syntax error is thrown if this argument is not a valid URI.
</dd></dl>
<h3 name="The_dispatched_event"> The dispatched event </h3>
<p><code>otherWindow</code> can listen for dispatched messages by executing the following JavaScript:
</p>
<pre class="eval">document.addEventListener("message", receiveFunc, false);

function receiverFunc(event)
{
  if (event.origin !== "...")
    return;

  // ...
}
</pre>
<p>The properties of the dispatched message are:
</p>
<dl><dt> <code>data</code>
</dt><dd> A string holding the message passed from the other window.
</dd><dt> <code>origin</code>
</dt><dd> The <a href="en/Origin">origin</a> of the window that sent the message.  This string is the concatenation of the protocol and "://", the host name if one exists, and ":" followed by a port number if a port is present and differs from the default port for the given protocol.  Examples of typical origins are <code><span class="plain">https://example.org</span></code>, <code><span class="plain">http://example.net</span></code>, and <code><span class="plain">http://example.com:8080</span></code>.
</dd><dt> <code>source</code>
</dt><dd> A reference to the <code><a href="en/DOM/window">window</a></code> object that sent the message; you can use this to establish two-way communication between two windows with different origins.
</dd></dl>
<h3 name="Security_concerns"> Security concerns </h3>
<p>If you do not expect to receive messages from other sites, you <i>should not</i> add any event listeners for <code>message</code> events.  This is a completely foolproof way to avoid security problems.
</p><p>If you do expect to receive messages from other sites, <b>always verify the sender's identity</b> using the <code>origin</code> and possibly <code>source</code> properties.  Any window (including, for example, <code><span class="plain">http://evil.example.com</span></code>) can send a message to any other window, and you have no guarantees that an unknown sender will not send malicious messages.  Having verified identity, however, <i>you still should verify the syntax of the sent message</i>.  Otherwise, a security hole in the site you trusted to send only trusted messages could then open a cross-site scripting hole in your site.
</p>
<h3 name="Example"> Example </h3>
<pre class="eval">/*
 * In window A's scripts, with A being on example.com:8080
 */

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

// When the popup has fully loaded, if not blocked by a popup blocker:

// This does nothing, assuming the window hasn't changed its location
popup.postMessage("The user is 'bob' and the password is 'secret'",
                  "<span class="plain">https://secure.example.net</span>");

// This will successfully send a message to the popup
popup.postMessage("hello there!", "<span class="plain">http://example.org</span>");

function receiveMessage(event)
{
  // Do we trust the sender of this message?  (might be
  // different from what we originally opened, for example)
  if (event.origin != "<span class="plain">http://example.com:8080</span>")
    return;

  // event.source is popup
  // event.data is "hi there yourself!"
}
document.addEventListener("message", receiveMessage, false);
</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.origin != "<span class="plain">http://example.com:8080</span>")
    return;

  // event.source is the same as window.opener
  // 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>origin</code> and possibly <code>source</code> properties.  This has already been mentioned once, but it cannot be understated: <b>Failure to check the <code>origin</code> and possibly <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>origin</code> property of the dispatched event is not affected by the current value of <code>document.domain</code> in the calling window.
</p><p>For IDN host names only, the value of the <code>origin</code> property is not consistently Unicode or punycode; for greatest compatibility check for both the IDN and punycode values when using this property if you expect messages from IDN sites.  It is expected that eventually this value will consistently be IDN, but for now you should handle both IDN and punycode forms.
</p><p>The value of the <code>origin</code> property when the sending window contains a <code>javascript:</code> URL is the origin of the script that loaded the URL.  The origin for <code>data:</code> URLs is currently the origin of the script that loaded the URL, but this is likely to change in the future.  For now, you should avoid using <code>postMessage</code> within pages generated from <code>data:</code> URLs.
</p><p>{{wiki.template('Non-standard_inline')}} <code>window.postMessage</code> is available to JavaScript running in chrome code (e.g. in extensions and privileged code), 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