この翻訳は不完全です。英語から この記事を翻訳 してください。

window.postMessage() は、 Window オブジェクト間で安全にクロスドメイン通信を可能にするためのメソッドです。例えば、ポップアップとそれを表示したページの間や、iframe とそれが埋め込まれたページの間での通信に使うことができます。

通常、異なった複数のページでのスクリプトはそれらが実行されたページが同じプロトコル、ポート番号、ホストである場合に限りお互いにアクセスすることが可能です ("同一オリジンポリシー" とも呼ばれます)。正しく使用した window.postMessage はこの制限を安全に回避するための制御された仕組みを提供します。

大まかには、ウィンドウが他のウィンドウへの参照を取得できる場合 ( targetWindow = window.opener など)、targetWindow.postMessage() を使って MessageEvent をそのウィンドウ上でディスパッチすることができます。受け取ったウィンドウでは必要に応じて自由にイベントを処理することができます。window.postMessage() に渡された引数 (“message”) はイベントオブジェクトを通して対象のウィンドウに公開されます

構文

targetWindow.postMessage(message, targetOrigin, [transfer]);
targetWindow
メッセージを受信するウィンドウへの参照。参照を取得する方法には以下のようなものがあります:
message
他のウィンドウに送られるデータ。データは the structured clone algorithm に従ってシリアル化されます。つまり、手動でシリアル化することなく様々なデータオブジェクトを渡すことができます。
targetOrigin
イベントをディスパッチする otherWindow のオリジンを "*" というリテラル文字列(制限しないことを示します)か URI のいずれかで指定します。もしイベントのディスパッチが予約される時点で、targetWindow のドキュメントのスキーマ、ホスト名、あるいはポートが  targetOrigin で指定されたものにマッチしない場合、そのイベントはディスパッチされません。3 つすべてがマッチした場合にだけイベントがディスパッチされます。この仕組みはメッセージがどこに送られるかを制御できるようにしています。例えば postMessage をパスワードを送るために利用する場合、悪意のある第三者によるパスワードの傍受を防ぐため、そのメッセージを受け取るべき受信者のオリジンと一致する URI をこの引数に指定しておくことが非常に重要になります。 送信先ウィンドウのドキュメントがどこに配置されるのかを知っている場合、* ではなく具体的な targetOrigin を指定してください。具体的なターゲットを指定しない場合、送信したデータは任意の悪意を持ったサイトに公開されることになります。
transfer Optional
メッセージと一緒に転送される Transferable オブジェクトのシーケンス。これらのオブジェクトの所有権は送信先に移動され、送信元では使えなくなります。

ディスパッチされるイベント

以下の JavaScript を実行することで、otherWindow に伝達されたメッセージを受け取ることができます。

otherWindow で以下の JavaScript を実行することで、ディスパッチされたメッセージを受け取ることができます。

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

function receiveMessage(event) {
  if (event.origin !== "http://example.org:8080")
    return;

  // ...
}

ディスパッチされたメッセージは以下のプロパティを持ちます。

data
他のウィンドウから渡されるメッセージを保持しているオブジェクト。
origin
postMessage が呼び出されたときにメッセージを送るウィンドウの origin。この文字列は、プロトコルと "://"、ホスト名(存在する場合)、そして、":" の後に続くポート番号(デフォルトポートと指定するポートが異なる場合)が連結されたものです。典型的な生成元の例は https://example.org (この場合のポートは 443)、http://example.net (この場合のポートは 80)、そして http://example.com:8080。この生成元はそのウィンドウの現在もしくは将来の生成元であることを保証していないことに注意してください。postMessage が呼び出されてから異なる場所に移動するかもしれません。
source
メッセージを送った window オブジェクトへの参照。これを使うことで異なった生成元である二つのウィンドウ間で双方向の通信を確立することができます。

セキュリティに関すること

他のサイトからメッセージを受け取りたくない場合、message イベントのための一切のイベントリスナーを追加するべきではありません。これはセキュリティ的な問題を避けるための完全にフールプルーフな方法です。

他のサイトからメッセージを受け取りたい場合、origin あるいは source プロパティを用いて常に送信者の識別情報を確かめてください。任意のウィンドウ(例えば、http://evil.example.com も含む)は任意の他のウィンドウにメッセージを送ることができ、見知らぬ送信者が悪意あるメッセージを送らない保証はありません。識別情報を確かめても、常に受け取ったメッセージの構文を確かめるべきです。さもなければ、信頼されたメッセージだけを送ることが信頼されているサイトにおけるセキュリティホールがクロスサイトスクリプティングセキュリティホールをあなたのサイトに開けることになり得ます。

/*
 * <http://example.com:8080> にある、window A のスクリプト:
 */

var popup = window.open(...ポップアップの詳細...);

// ポップアップブロッカーでブロックされず、ポップアップが完全にロードされたとき

// ウィンドウがその場所を変更していない場合、これは何もしません。
popup.postMessage("ユーザー名は 'bob' 、パスワードは 'secret' です",
                  "https://secure.example.net");

// ウィンドウがその場所を変更していない場合、
//これはポップアップに送るメッセージのキューに追加します。
popup.postMessage("hello there!", "http://example.org");

function receiveMessage(event) {
  // このメッセージの送信者は信頼している者か?(例えば、最初開いたものと違
  // うかもしれません)。
  if (event.origin !== "http://example.org")
    return;

  // event.source は popup
  // event.data は "hi there yourself!  the secret response is: rheeeeet!"
}

window.addEventListener("message", receiveMessage, false);
/*
 * <http://example.org> で実行される popup のスクリプト:
 */

// postMessage が呼び出された後に呼び出されます。
function receiveMessage(event) {
  // このメッセージの送信者は信頼している者か?
  if (event.origin !== "http://example.com:8080") {
    return;
  }

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

  // 受け取ったメッセージのオリジンを確かめたい場合(どんな場合でもそうするべ
  // きです)、メッセージに返答するための便利なイディオムは event.source 上
  // の postMessage を呼び出し、targetOrigin に event.origin を指定すること
  // です。
  event.source.postMessage(
    "hi there yourself!  the secret response " +
    "is: rheeeeet!",
    event.origin
  );
}

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

注記

任意のウィンドウが、いつでも、ウィンドウの文書の場所にかかわらず、メッセージを送るために、任意の他のウィンドウ上でこのメソッドにアクセスするかもしれません。従って、任意のイベントリスナーはメッセージを受け取る際に、origin あるいは source プロパティを用いて、まず最初にメッセージの送信者の識別情報をチェックしなければなりません。これを軽視することはできません。なぜなら、origin あるいは source プロパティのチェックの失敗はクロスサイトスクリプティング攻撃を可能にするからです。

非同期で伝達されるスクリプト(タイムアウト、ユーザーが生成したイベント)のために postMessage の呼び出し元の判別が不可能であるとき、postMessage によって送られるイベントを待ち受けているイベントハンドラは例外を投げます。

伝達されるイベントの origin プロパティは呼び出すウィンドウの document.domain の現在の値に影響されません。

IDN ホスト名に限った話ですが、origin プロパティの値は一貫して Unicode もしくは Punycode ではありません。ですから、IDN サイトからのメッセージを期待する場合にこのプロパティを用いるときは、最も素晴らしい互換性チェックにするために、IDN と Punycode の値の両方をチェックしてください。この値は最終的には 一貫して IDN になるはずですが、現在は IDN と Punycode 両方の形式を扱うべきです。

javascript:data: を含む送信ウィンドウの origin プロパティの値は URL を読み込んだスクリプトの生成元になります。

window.postMessage を拡張機能で使う

window.postMessage は chrome コードで実行される JavaScript で利用可能です(例:拡張内および特権コード)。しかし、伝達されるイベントの source プロパティはセキュリティ上の制限から常に null です(他のプロパティは期待された値です)。

It is not possible for content or web context scripts to specify a targetOrigin to communicate directly with an extension (either the background script or a content script).  Web or content scripts can use window.postMessage with a targetOrigin of "*" to broadcast to every listener, but this is discouraged, since an extension cannot be certain the origin of such messages, and other listeners (including those you do not control) can listen in.

Content scripts should use runtime.sendMessage to communicate with the background script.  Web context scripts can use custom events to communicate with content scripts (with randomly generated event names, if needed, to prevent snooping from the guest page).

最後に、file: URL のページへのメッセージを送るには targetOrigin 引数を "*" にする必要があります。file:// はセキュリティ上の制限のために用いることはできません、この制限は将来修正されるかもしれません。

仕様

Specification Status Comment
HTML Living Standard
postMessage() の定義
現行の標準  

ブラウザー実装状況

 

Update compatibility data on GitHub
デスクトップモバイル
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeEdge MobileAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung Internet
postMessageChrome 完全対応 1Edge 完全対応 12Firefox 完全対応 8
補足
完全対応 8
補足
補足 Supports sending File and FileList objects between windows. This is only allowed if the recipient's principal is contained within the sender's principal for security reasons.
完全対応 6
補足
補足 The message parameter is serialized using the structured clone algorithm. This means you can pass a broad variety of data objects safely to the destination window without having to serialize them yourself.
未対応 ? — 6
補足
補足 The message parameter must be a string.
IE 完全対応 10
補足
完全対応 10
補足
補足 IE10 had an important limitation: see this article for details.
未対応 8 — 10
補足
補足 Support only for <frame> and <iframe>.
Opera 完全対応 9.5Safari 完全対応 4WebView Android 完全対応 ありChrome Android 完全対応 ありEdge Mobile 完全対応 ありFirefox Android 完全対応 8
補足
完全対応 8
補足
補足 Supports sending File and FileList objects between windows. This is only allowed if the recipient's principal is contained within the sender's principal for security reasons.
完全対応 6
補足
補足 The message parameter is serialized using the structured clone algorithm. This means you can pass a broad variety of data objects safely to the destination window without having to serialize them yourself.
未対応 ? — 6
補足
補足 The message parameter must be a string.
Opera Android 完全対応 ありSafari iOS 完全対応 あり
補足
完全対応 あり
補足
補足 For security reasons, to work properly on Safari, construct using document.getElementById('your-frame').contentWindow.
Samsung Internet Android 完全対応 あり
transfer argumentChrome ? Edge 完全対応 ありFirefox 完全対応 20IE 完全対応 ありOpera ? Safari ? WebView Android ? Chrome Android ? Edge Mobile ? Firefox Android 完全対応 20Opera Android ? Safari iOS ? Samsung Internet Android ?

凡例

完全対応  
完全対応
実装状況不明  
実装状況不明
実装ノートを参照してください。
実装ノートを参照してください。

 

関連情報

ドキュメントのタグと貢献者

最終更新者: unarist,