Web Messagingとは
対応ブラウザ
※Windows 7上で動作確認を行っています。
※ブラウザの設定より、異なる挙動をする場合があります。
※ブラウザにWeb Messaging自体が実装されている場合に「○」としています。個々のメソッドや属性などについては未実装である場合があります。
解説
コードによるほかのウィンドウ、タブ、フレームへのアクセスは、通常、セキュリティ上の理由から、同一オリジンのドキュメントの間だけに制限されています。
ここでいうオリジン(origin 生成元)というのは、ドキュメントのURLのうち、スキーム、ドメイン、ポートを合わせた部分のことです。
以下のようなURLならhttp://example.com:8080の部分がオリジンで、a.htmlとb.htmlはオリジンが同一であるということになります。
http:// | www.example.com | :8080 | /path/to/the/file/ | a.html |
http:// | www.example.com | :8080 | /path/to/ | b.html |
スキーム | ドメイン | ポート | パス |
オリジン | パス |
しかし、オリジンは異なっているものの、信用できる特定のドキュメントと、一定のメッセージのやり取りを行う必要があるという場合も存在します。
この問題を解決するために、Web Messagingには、クロスドキュメントメッセージングとチャネルメッセージングの二つのAPIが用意されています。
クロスドキュメントメッセージングは、この異なるオリジンの間での通信を安全に行うことを目的としたAPIで、そのために、メッセージの送受信を専用のメソッドとイベントだけに限定し、送受信時に相手先のオリジンを確認できるようになっています。
クロスドキュメントメッセージングは、基本的には「window.postMessage(message, targetOrigin)」メソッドとwindowのmessageイベントのセットで利用します。
送信元のドキュメントで、送信先のドキュメントのwindowオブジェクトの「postMessage(message, targetOrigin)」メソッドを呼び出すと、送信先ドキュメントで、windowオブジェクトのmessageイベントが発生してデータが受信されます。
以下は送信と受信のシンプルな例です。
http://abc.example.com/a.html のコード
// 「iframe」はhttps://efg.example.org/b.htmlを
// 表示しているiframe要素への参照
iframe.contentWindow.postMessage('送信メッセージ','https://efg.example.org');
https://efg.example.org/b.html のコード
// messageイベントをハンドリングする
window.onmessage = function(event){
// 送信元のオリジンを確認
if(event.origin == 'http://abc.example.com'){
// 送信されたデータの取出し
console.log(event.data);
}
}
これに対し、チャネルメッセージングは、データの送受信をwindow単位で行うのではなく、任意の個数の生成が可能な、MessageChannelオブジェクトを使用して行います。チャネルメッセージングを使うと、同時に複数の通信チャンネルを使った通信を行うことができます。
MessageChannelオブジェクトには属性port1と属性port2が存在し、実体はMessagePortオブジェクトになっています。このport1とport2が、MessageChannelを一つの通信チャンネルとした場合の、両端の通信端末に相当します。
以下の例では、同一のウィンドウの中のコードで通信チャンネルを生成し、チャンネルの一方の端(port2)からもう一方の端(port1)へメッセージを送っています。
また、一つのMessageChannelのport1とport2のどちらか一方のMessagePortオブジェクトを、クロスドキュメントメッセージングを利用してオリジンの異なるウィンドウに送信すれば、ウィンドウをまたいで存在するport1とport2の間で通信することで、異なるオリジンの間での通信を実現することができます。
// チャンネルを生成
var channel = new MessageChannel();
// このチャンネルの端末1を開始する
channel.port1.start();
// このチャンネルの端末2を開始する
channel.port2.start();
// 端末1の受信ハンドラを定義する
port1.onmessage = function(event){
console.log(event.data);
}
// 端末2からメッセージを端末1に送信する
port2.postMessage('送信データ');
関連項目
(関連する項目はありません)