Window.postMessage

  • Revision slug: DOM/window.postMessage
  • Revision title: window.postMessage
  • Revision id: 68527
  • Created:
  • Creator: Mgjbot
  • Is current revision? No
  • Comment robot Adding: [[ja:DOM:window.postMessage]] <<langbot>>

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, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.). The MessageEvent has the type message, a data property which is set to the string value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called. (Other standard properties of events are present with their expected values.)

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 object returned by window.open, or by named or numeric index on window.frames.
message
String data to be sent to the other window.
targetOrigin
Specifies what the origin of otherWindow must be for the event to be dispatched, either as the literal string "*" (indicating no preference) or as a URI. If at the time the event is scheduled to be dispatched the scheme, hostname, or port of otherWindow's document does not match that provided in targetOrigin, the event will not be dispatched; only if all three match will the event be dispatched. This mechanism provides control over where messages are sent; for example, if postMessage were used to transmit a password, it would be absolutely critical that this argument be a URI whose origin is the same as the intended receiver of the message containing the password, to prevent interception of the password by a malicious third party.

The dispatched event

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

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

function receiveMessage(event)
{
  if (event.origin !== "http://example.org:8080")
    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 at the time postMessage was called. 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 (implying port 443), http://example.net (implying port 80), and http://example.com:8080. Note that this origin is not guaranteed to be the current or future origin of that window, which might have been navigated to a different location since postMessage was called.
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 always verify the syntax of the received 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 <http://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 queue a message to be sent to the popup, assuming
// the window hasn't changed its location.
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.org")
    return;

  // event.source is popup
  // event.data is "hi there yourself!  the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
/*
 * In the popup's scripts, running on <http://example.org>:
 */

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

  // event.source is window.opener
  // event.data is "hello there!"

  // Assuming you've verified the origin of the received message (which
  // you must do in any case), a convenient idiom for replying to a
  // message is to call postMessage on event.source and provide
  // event.origin as the targetOrigin.
  event.source.postMessage("hi there yourself!  the secret response " +
                           "is: rheeeeet!",
                           event.origin);
}

window.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 cannot be understated: Failure to check the origin and possibly source properties enables cross-site scripting attacks.

As with any asynchrously-dispatched script (timeouts, user-generated events), it is not possible for the caller of postMessage to detect when an event handler listening for events sent by postMessage throws an exception.

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. This value will eventually be consistently 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: or data: URL is the origin of the script that loaded the URL.

{{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.) The targetOrigin argument for a message sent to a window located at a chrome: URL is currently misinterpreted such that the only value which will result in a message being sent is "*". Since this value is unsafe when the target window can be navigated elsewhere by a malicious site, it is recommended that postMessage not be used to communicate with chrome: pages for now; use a different method (such as a query string when the window is opened) to communicate with chrome windows. Lastly, posting a message to a page at a file: URL currently requires that the targetOrigin argument be "*". file:// cannot be used as a security restriction; this restriction may be modified in the future.

Specification

window.postMessage is defined by the draft HTML5 specification.

See also

document.domain

{{ wiki.languages( { "ja": "ja/DOM/window.postMessage" } ) }}

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, causes a <a href="en/MessageEvent">MessageEvent</a> to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if <code>window.postMessage</code> is called from an event handler, previously-set pending timeouts, etc.).  The <a href="en/MessageEvent">MessageEvent</a> has the type <code>message</code>, a <code>data</code> property which is set to the string value of the first argument provided to <code>window.postMessage</code>, an <code>origin</code> property corresponding to the origin of the main document in the window calling <code>window.postMessage</code> at the time <code>window.postMessage</code> was called, and a <code>source</code> property which is the window from which <code>window.postMessage</code> is called.  (Other standard properties of events are present with their expected values.)
</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 object returned by <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>
</dt><dd> Specifies what the origin of <code>otherWindow</code> must be for the event to be dispatched, either as the literal string <code>"*"</code> (indicating no preference) or as a URI.  If at the time the event is scheduled to be dispatched the scheme, hostname, or port of <code>otherWindow</code>'s document does not match that provided in <code>targetOrigin</code>, the event will not be dispatched; only if all three match will the event be dispatched.  This mechanism provides control over where messages are sent; for example, if <code>postMessage</code> were used to transmit a password, it would be absolutely critical that this argument be a URI whose origin is the same as the intended receiver of the message containing the password, to prevent interception of the password by a malicious third party.
</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">window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
{
  if (event.origin !== "<span class="plain">http://example.org:8080</span>")
    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 at the time <code>postMessage</code> was called.  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> (implying port <code>443</code>), <code><span class="plain">http://example.net</span></code> (implying port <code>80</code>), and <code><span class="plain">http://example.com:8080</span></code>.  Note that this origin is <i>not</i> guaranteed to be the current or future origin of that window, which might have been navigated to a different location since <code>postMessage</code> was called.
</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, you still should <b>always verify the syntax of the received message</b>.  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 &lt;<span class="plain">http://example.com:8080</span>&gt;:
 */

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 queue a message to be sent to the popup, assuming
// the window hasn't changed its location.
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.org</span>")
    return;

  // event.source is popup
  // event.data is "hi there yourself!  the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
</pre>
<pre class="eval">/*
 * In the popup's scripts, running on &lt;<span class="plain">http://example.org</span>&gt;:
 */

// Called sometime after postMessage is called
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 window.opener
  // event.data is "hello there!"

  // Assuming you've verified the origin of the received message (which
  // you must do in any case), a convenient idiom for replying to a
  // message is to call postMessage on event.source and provide
  // event.origin as the targetOrigin.
  event.source.postMessage("hi there yourself!  the secret response " +
                           "is: rheeeeet!",
                           event.origin);
}

window.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 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>As with any asynchrously-dispatched script (timeouts, user-generated events), it is not possible for the caller of <code>postMessage</code> to detect when an event handler listening for events sent by <code>postMessage</code> throws an exception.
</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.  This value will eventually be consistently 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> or <code>data:</code> URL is the origin of the script that loaded the URL.
</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.)  The <code>targetOrigin</code> argument for a message sent to a window located at a <code>chrome:</code> URL is currently misinterpreted such that the only value which will result in a message being sent is <code>"*"</code>.  Since this value is unsafe when the target window can be navigated elsewhere by a malicious site, it is recommended that <code>postMessage</code> not be used to communicate with <code>chrome:</code> pages for now; use a different method (such as a query string when the window is opened) to communicate with chrome windows.  Lastly, posting a message to a page at a <code>file:</code> URL currently requires that the <code>targetOrigin</code> argument be <code>"*"</code>.  <code>file://</code> cannot be used as a security restriction; this restriction may be modified in the future.
</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>
<div class="noinclude">
</div>
{{ wiki.languages( { "ja": "ja/DOM/window.postMessage" } ) }}
Revert to this revision