Web Messaging について
■ Web Messaging について
Web Messaging は、HTML5 世代の機能です。
http://www.w3.org/TR/webmessaging/
ブラウザから2つの Web ページを開き、相互にメッセージ通信を行う事ができます。
これはネットを経由する通信ではなく、クライアント内だけのやり取りです。
■生成元(オリジン)について
生成元(オリジン)とは、自身のリソースが格納されている場所です。
「プロトコル、ドメイン、ポート番号」の3つを合わせたものです。
■同一生成元ポリシー (Same-Origin Policy) について
クロスサイトスクリプトを行う事はできません。
例えば、「http://my.example.com」をブラウザで開くとします。
「http://my.example.com」のスクリプトは、動的に「http://other.example.com」を開けますが、このコンテンツ内にアクセスする事はできません。
■クロスサイトメッセージングを行う
クロスサイト間で連携するには、Web Messaging の機能を使用します。
異なるオリジン下のコンテンツ同士で、相互にオブジェクトを送受信する事ができます。
■ブラウザが Web Messaging をサポートしているか調べる
window.postMessage が真であるか比較します。
■Internet Explorer での対応について
Internet Explorer 7 以前では、対応していません。
バージョンによっては、一部の機能が未対応です。
こちらで解説しています。
基本的なメッセージングについて
■メッセージを受信する
■メッセージを受信するイベント
メッセージを受信するには、onmessage イベントを使用します。
デフォルトの状態で、最大のセキュリティリスクが発生する事に注意して下さい。
メッセージの受信側に制限はありません。すべてのメッセージを受け入れます。
登録したコールバック関数の引数から、MessageEvent オブジェクトが得られます。
■ MessageEvent について
MessageEvent オブジェクトには、以下のプロパティがあります。
プロパティ名 | 型 | 説明 |
data | * | 送信者から送られたデータを取得する。 |
origin | String | 送信者のオリジンを取得する。 |
source | WindowProxy | 送信者の Window オブジェクトを取得する。 |
ports | Array | 配列を取得する。中身は MessagePort オブジェクト。 |
lastEventId | String | Last-Event-ID リクエストヘッダの値を取得する?(Server-Sent Events 用) |
■セキュリティについて (origin プロパティ)
送信者の生成元(オリジン)を取得するには、origin プロパティを使用します。
オリジンを取得して、信頼できる送信者であるか調べます。
不特定の送信者だった場合、拒絶するようにします。
■使用例
メッセージを受信する(この例では、http://sub.example.com のみ信頼し、それ以外を拒絶している)
// Web Messaging に対応している
if(window.postMessage){
// ------------------------------------------------------------
// 信頼するオリジン
// ------------------------------------------------------------
var origin_allow = "http://sub.example.com";
// ------------------------------------------------------------
// メッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 出力テスト(送信者から送られたデータ)
console.log(e.data);
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
// イベントリスナーに対応している
if(window.addEventListener){
// メッセージ受信時に実行されるイベント
window.addEventListener("message" , WindowMessageHandler);
// アタッチイベントに対応している
}else if(window.attachEvent){
// メッセージ受信時に実行されるイベント
window.attachEvent("onmessage" , WindowMessageHandler);
}
}
■メッセージを送信する
■相手の Window オブジェクトを取得する
■メッセージを送信する
メッセージを送信するには、postMessage() メソッドを使用します。
相手の Window オブジェクトを使って呼び出します。
Window.postMessage( 送信データ , "相手のオリジン" , [譲渡データ] ) :Void
第01引数 | * | 送信データを指定する。 |
第02引数 | String | 送信を許可する相手のオリジンを指定する。 |
第03引数(略可) | Array | Transferable なオブジェクトを配列に格納して指定する。MessagePort などが該当。 |
戻り値 | Void | なし。 |
■第01引数 (送信データ)
送信したいデータを指定します。
オブジェクトを指定した場合、複製されます。
Internet Explorer 9 以前では、文字列型に変換されます。
オブジェクトを指定したい場合は、JSON を使って変換します。
■第02引数 (相手のオリジン)
送信を許可する、相手のオリジンを指定します。
実際に送信に成功するのは、ここで指定したオリジンのみです。
相手ウィンドウには、同じページが表示され続けているとは限りません。
ユーザー操作によって、想定外の未知のページに変化している可能性があります。
以下の記号の指定も可能です。
指定文字列 | 説明 |
"/" | 自身と同一のオリジンである場合のみ、送信を許可する。(IE8 では未対応) |
"*" | すべてのサイトに対して、送信を許可する。(最大のセキュリティリスク) |
■第03引数 (譲渡データ)
ここで指定したオブジェクトは、所有権が相手に譲渡されます。
自身からは、アクセス不可能になり、再利用もできません。
■大容量のデータを譲渡する
一部のブラウザでは、 ArrayBuffer オブジェクトなどの譲渡が可能です。
大容量のデータを、複製せずに、相手に渡したい場合に便利です。
譲渡するデータは、第01引数と第03引数の両方に含める必要があります。
第01引数にのみ指定した場合、データは複製されます。
■メッセージを返信する
■相手の Window オブジェクトを取得する (source プロパティ)
送信者の Window オブジェクトを取得するには、source プロパティを使用します。
■メッセージを返信する
相手の Window オブジェクトを使って、postMessage() メソッドを呼び出します。
メッセージを返信する(この例では、http://sub.example.com のみ信頼し、それ以外を拒絶している)
// Web Messaging に対応している
if(window.postMessage){
// ------------------------------------------------------------
// 信頼するオリジン
// ------------------------------------------------------------
var origin_allow = "http://sub.example.com";
// ------------------------------------------------------------
// メッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// 相手の Window オブジェクトを取得する
// ------------------------------------------------------------
var window_target = e.source;
// ------------------------------------------------------------
// 返信用オブジェクト
// ------------------------------------------------------------
var receive_obj = {
message:"返信テスト",
param:{}
};
// ------------------------------------------------------------
// 返信する
// ------------------------------------------------------------
window_target.postMessage ( JSON.stringify(receive_obj) , origin_allow );
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
if(window.addEventListener){
window.addEventListener("message" , WindowMessageHandler);
}else if(window.attachEvent){
window.attachEvent("onmessage" , WindowMessageHandler);
}
}
■メッセージの送受信例 (IFRAME 要素内)
親側のコンテンツを "http://my.com/aaa.html" とします。
子側のコンテンツを "http://other.com/bbb.html" とします。
■ http://my.com 側の処理について
インラインフレーム内に「http://other.com/bbb.html」を開き、送受信処理を行う
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#fee;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>相手のコンテンツ (インラインフレーム)</legend>
<iframe id="iframe_target" src="http://other.com/bbb.html" style="width:100%; height:400px; background:#fff;" ></iframe>
</fieldset>
<script type="text/javascript">
<!--
// 信頼するオリジン
var origin_allow = "http://other.com";
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
var iframe_target = document.getElementById("iframe_target");
// ------------------------------------------------------------
// メッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 受信データを取得
var request_obj = JSON.parse(e.data);
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
if(window.addEventListener){
window.addEventListener("message" , WindowMessageHandler);
}else if(window.attachEvent){
window.attachEvent("onmessage" , WindowMessageHandler);
}
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
// ------------------------------------------------------------
// インラインフレーム内の Window オブジェクトを取得
// ------------------------------------------------------------
var window_target = iframe_target.contentWindow;
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// 相手に送信する
// ------------------------------------------------------------
window_target.postMessage( JSON.stringify(request_obj) , origin_allow );
};
//-->
</script>
</body>
</html>
■ http://other.com 側の処理について
受信検出した相手に対して、送受信処理を行う(この例では、http://my.com のみ信頼し、それ以外を拒絶している)
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<script type="text/javascript">
<!--
// 相手の Window オブジェクト
var window_target = null;
// 信頼するオリジン
var origin_allow = "http://my.com";
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
// ------------------------------------------------------------
// 親のウィンドウを取得する
// ------------------------------------------------------------
if(window.parent !== window.self){
window_target = window.parent;
}
// ------------------------------------------------------------
// メッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 相手の Window オブジェクトを取得する
window_target = e.source;
// 受信データを取得
var request_obj = JSON.parse(e.data);
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
if(window.addEventListener){
window.addEventListener("message" , WindowMessageHandler);
}else if(window.attachEvent){
window.attachEvent("onmessage" , WindowMessageHandler);
}
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
if(!(window_target)) return;
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// 相手に送信する
// ------------------------------------------------------------
window_target.postMessage( JSON.stringify(request_obj) , origin_allow );
};
//-->
</script>
</body>
</html>
■メッセージの送受信例 (別ウィンドウ)
親側のコンテンツを "http://my.com/aaa.html" とします。
子側のコンテンツを "http://other.com/bbb.html" とします。
■ http://my.com 側の処理について
window.open() メソッドを使って「http://other.com/bbb.html」を開き、送受信処理を行う
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#fee;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>相手のコンテンツ (別ウィンドウ)</legend>
<input type="button" id="input_open" style="width:100%; height:50px; margin:0px;" value="相手ウィンドウを開く" ><br>
</fieldset>
<script type="text/javascript">
<!--
// 相手の Window オブジェクト
var window_target = null;
// 信頼するオリジン
var origin_allow = "http://other.com";
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
var element_open = document.getElementById("input_open");
// ------------------------------------------------------------
// メッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 受信データを取得
var request_obj = e.data;
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
if(window.addEventListener){
window.addEventListener("message" , WindowMessageHandler);
}else if(window.attachEvent){
window.attachEvent("onmessage" , WindowMessageHandler);
}
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
if(!(window_target)) return;
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// 相手に送信する
// ------------------------------------------------------------
window_target.postMessage( request_obj , origin_allow );
};
// ------------------------------------------------------------
// 開くボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_open.onclick = function (e){
if(window_target && !(window_target.closed)) return;
// ------------------------------------------------------------
// ウィンドウを作成する
// ------------------------------------------------------------
window_target = window.open(origin_allow + "/bbb.html" , "_blank" , "width=800,height=600");
};
//-->
</script>
</body>
</html>
■ http://other.com 側の処理について
外部から開かれた相手に対して、送受信処理を行う(この例では、http://my.com のみ信頼し、それ以外を拒絶している)
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<script type="text/javascript">
<!--
// 相手の Window オブジェクト
var window_target = null;
// 信頼するオリジン
var origin_allow = "http://my.com";
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
// ------------------------------------------------------------
// 生成主ウィンドウを取得する(無ければ null 値)
// ------------------------------------------------------------
window_target = window.opener;
// ------------------------------------------------------------
// メッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 相手の Window オブジェクトを取得する
window_target = e.source;
// 受信データを取得
var request_obj = e.data;
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
if(window.addEventListener){
window.addEventListener("message" , WindowMessageHandler);
}else if(window.attachEvent){
window.attachEvent("onmessage" , WindowMessageHandler);
}
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
if(!(window_target)) return;
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// 相手に送信する
// ------------------------------------------------------------
window_target.postMessage( request_obj , origin_allow );
};
//-->
</script>
</body>
</html>
■ Internet Explorer での動作について
■ IFRAME 要素内との通信について
IFRAME 要素内との通信は、Internet Explorer 8 以降から対応しています。
別オリジン間の通信も可能です。
■別ウィンドウとの通信について
別ウィンドウとの通信は、Internet Explorer 10 以降から対応しています。
別オリジン間の通信は、Internet Explorer 11 以降から対応しています。
チャンネルメッセージングについて
■チャンネルメッセージングについて
チャンネルメッセージングを使用すると、独占的な通信経路を構築する事ができます。
1つだけでなく、複数のチャンネルを構築する事もできます。
どちらか片方がロストした場合、通信経路は自動的に閉じられます。
これにより、相手が別の Web ページに変化しても安全です。
相手のオリジンの確認は、最初の一度だけで済みます。
Internet Explorer 9 以前では、対応していません。
■メッセージチャンネルを構築する
■ MessageChannel オブジェクトを作成する
new 演算子を使って、MessageChannel オブジェクトを作成します。
複数のチャンネルを構築したい場合は、必要な数だけ生成します。
MessageChannel オブジェクトを作成する
// MessageChannel に対応している
if(window.MessageChannel){
// MessageChannel オブジェクトを作成する
var message_channel = new MessageChannel();
// 出力テスト
console.log(message_channel);
}
■ MessageChannel オブジェクトについて
中には、2つの MessagePort オブジェクトが格納されています。
どちらか片方を自分用に確保し、もう片方は相手に送信します。
ここでは、port1 を、自分が使用するものとします。
プロパティ | 型 | 解説 |
port1 | MessagePort | MessagePort オブジェクトが得られる |
port2 | MessagePort | MessagePort オブジェクトが得られる |
■ MessagePort オブジェクトを相手に送信する(発動側の処理)
相手に MessagePort オブジェクトを渡すには、postMessage() メソッドを使用します。
MessagePort オブジェクトを配列に格納して、第03引数に渡します。
MessagePort オブジェクトは、Transferable なオブジェクトです。
送信すると、所有権が相手に譲渡されます。
■相手から MessagePort オブジェクトを受け取る(受動側の処理)
相手から MessagePort オブジェクトを受け取るには、onmessage イベントを使用します。
ports プロパティから、MessagePort オブジェクトのリストが得られます。
■チャンネル経由で、メッセージを受信する
■メッセージを受信するイベント
登録したコールバック関数の引数から、MessageEvent オブジェクトが得られます。
チャンネルメッセージングでは、以下の情報が取得できます。
プロパティ名 | 型 | 説明 |
data | * | 送信者から送られたデータを取得する。 |
ports | Array | 配列を取得する。中身は MessagePort オブジェクト。 |
■受信を開始する
受信を開始するには、start() メソッドを使用します。
onmessage プロパティを使用した場合は、自動的に開始されます。
受信を開始していない場合、メッセージはキューに蓄積されます。
受信を開始すると、相手からのメッセージが、まとめて得られます。
■チャンネル経由で、メッセージを送信する
■メッセージを送信する
MessagePort.postMessage( 送信データ , [譲渡データ] ) :Void
第01引数 | * | 送信データを指定する。 |
第02引数(略可) | Array | Transferable なオブジェクトを配列に格納して指定する。MessagePort などが該当。 |
戻り値 | Void | なし。 |
■第01引数 (送信データ)
送信したいデータを指定します。
オブジェクトを指定した場合、複製されます。
■第02引数 (譲渡データ)
ここで指定したオブジェクトは、所有権が相手に譲渡されます。
自身からは、アクセス不可能になり、再利用もできません。
■大容量のデータを譲渡する
一部のブラウザでは、 ArrayBuffer オブジェクトなどの譲渡が可能です。
大容量のデータを、複製せずに、相手に渡したい場合に便利です。
譲渡するデータは、第01引数と第02引数の両方に含める必要があります。
第01引数にのみ指定した場合、データは複製されます。
■メッセージチャンネルを終了する
メッセージチャンネルを終了するには、close() メソッドを使用します。
自身や相手がアンロードされた場合、メッセージチャンネルは、自動的に終了します。
■チャンネルメッセージングの送受信例 (IFRAME 要素内)
親側のコンテンツを "http://my.com/aaa.html" とします。
子側のコンテンツを "http://other.com/bbb.html" とします。
この例では、子側からリクエストを開始します。
■ http://my.com 側の処理について
インラインフレーム内に「http://other.com/bbb.html」を開き、子からリクエストを待つ
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#fee;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>相手のコンテンツ (インラインフレーム)</legend>
<input type="button" id="input_add" style="width:100%; height:50px; margin:0px;" value="インラインフレームを追加" >
</fieldset>
<script type="text/javascript">
<!--
// 匿名関数を即時実行
(function(){
// MessagePort オブジェクトのリスト
var message_port_list = new Array();
// 信頼するオリジン
var origin_allow = "http://other.com";
// ------------------------------------------------------------
// MessageChannel に対応しているか調べる
// ------------------------------------------------------------
if(!(window.MessageChannel)) return;
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
var element_add = document.getElementById("input_add");
// ------------------------------------------------------------
// 基本的なメッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// MessagePort オブジェクトが送られてきたか調べる
// ------------------------------------------------------------
var i;
var num = e.ports.length;
for(i=0;i < num;i++){
(function(){
// ------------------------------------------------------------
// MessagePort オブジェクトを取得
// ------------------------------------------------------------
var message_port = e.ports[i];
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信時に実行されるイベント
// ------------------------------------------------------------
message_port.onmessage = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 受信データを取得
var request_obj = e.data;
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信を開始する
// ------------------------------------------------------------
message_port.start();
// リストに登録
message_port_list.push(message_port);
})();
}
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
if(window.addEventListener){
window.addEventListener("message" , WindowMessageHandler);
}else if(window.attachEvent){
window.attachEvent("onmessage" , WindowMessageHandler);
}
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
// ------------------------------------------------------------
// 全員に送信する
// ------------------------------------------------------------
var i;
var num = message_port_list.length;
for(i=0;i < num;i++){
var message_port = message_port_list[i];
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// 相手に送信する
// ------------------------------------------------------------
message_port.postMessage( request_obj );
}
};
// ------------------------------------------------------------
// 追加ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_add.onclick = function (e){
// HTMLIframeElement オブジェクトを作成
var iframe = document.createElement("iframe");
// インラインスタイルを設定
iframe.style.cssText = "width:400px; height:400px; margin-top:10px; margin-right:10px; border-width:5px; background:#fff;";
// URL アドレスを設定
iframe.src = origin_allow + "/bbb.html";
// ノードリストに登録
element_add.parentNode.appendChild(iframe);
};
})();
//-->
</script>
</body>
</html>
■ http://other.com 側の処理について
1つ上の親に対して、チャンネルメッセージングを行う(この例では、http://my.com のみ信頼し、それ以外を拒絶している)
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<script type="text/javascript">
<!--
// 匿名関数を即時実行
(function(){
// 自身用の MessagePort オブジェクト
var message_port = null;
// 信頼するオリジン
var origin_allow = "http://my.com";
// ------------------------------------------------------------
// MessageChannel に対応しているか調べる
// ------------------------------------------------------------
if(!(window.MessageChannel)) return;
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
// ------------------------------------------------------------
// MessageChannel オブジェクトを作成
// ------------------------------------------------------------
var message_channel = new MessageChannel();
// ------------------------------------------------------------
// 自身用の MessagePort オブジェクトを確保
// ------------------------------------------------------------
message_port = message_channel.port1;
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信時に実行されるイベント
// ------------------------------------------------------------
message_port.onmessage = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 受信データを取得
var request_obj = e.data;
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信を開始する
// ------------------------------------------------------------
message_port.start();
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// 相手に送信する
// ------------------------------------------------------------
message_port.postMessage( request_obj );
};
// ------------------------------------------------------------
// 読み込み完了時に実行されるイベント
// ------------------------------------------------------------
window.onload = function (e){
// ------------------------------------------------------------
// 親のウィンドウを取得する
// ------------------------------------------------------------
if(window.parent === window.self) return;
var window_target = window.parent;
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {command:"requestChannelMessaging"};
try{
// ------------------------------------------------------------
// 相手に MessagePort オブジェクトを送信する
// ------------------------------------------------------------
window_target.postMessage( request_obj , origin_allow , [message_channel.port2] );
}catch(e){
// ------------------------------------------------------------
// Safari 5 の場合 (第02引数と第03引数を入れ替える)
// ------------------------------------------------------------
// window_target.postMessage( request_obj , [message_channel.port2] , origin_allow );
}
};
})();
//-->
</script>
</body>
</html>
■チャンネルメッセージングの送受信例 (別ウィンドウ)
親側のコンテンツを "http://my.com/aaa.html" とします。
子側のコンテンツを "http://other.com/bbb.html" とします。
この例では、子側からリクエストを開始します。
■ http://my.com 側の処理について
window.open() メソッドを使って「http://other.com/bbb.html」を開き、子からリクエストを待つ
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#fee;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>相手のコンテンツ (別ウィンドウ)</legend>
<input type="button" id="input_open" style="width:100%; height:50px; margin:0px;" value="相手ウィンドウを開く" ><br>
</fieldset>
<script type="text/javascript">
<!--
// 匿名関数を即時実行
(function(){
// MessagePort オブジェクトのリスト
var message_port_list = new Array();
// 信頼するオリジン
var origin_allow = "http://other.com";
// ------------------------------------------------------------
// MessageChannel に対応しているか調べる
// ------------------------------------------------------------
if(!(window.MessageChannel)) return;
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
var element_open = document.getElementById("input_open");
// ------------------------------------------------------------
// 基本的なメッセージ受信時に実行されるコールバック関数
// ------------------------------------------------------------
var WindowMessageHandler = function (e) {
// ------------------------------------------------------------
// 信頼できる送信者か調べる
// ------------------------------------------------------------
if(e.origin != origin_allow) return;
// ------------------------------------------------------------
// MessagePort オブジェクトが送られてきたか調べる
// ------------------------------------------------------------
var i;
var num = e.ports.length;
for(i=0;i < num;i++){
(function(){
// ------------------------------------------------------------
// MessagePort オブジェクトを取得
// ------------------------------------------------------------
var message_port = e.ports[i];
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信時に実行されるイベント
// ------------------------------------------------------------
message_port.onmessage = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 受信データを取得
var request_obj = e.data;
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信を開始する
// ------------------------------------------------------------
message_port.start();
// リストに登録
message_port_list.push(message_port);
})();
}
};
// ------------------------------------------------------------
// イベントのリッスンを開始する
// ------------------------------------------------------------
if(window.addEventListener){
window.addEventListener("message" , WindowMessageHandler);
}else if(window.attachEvent){
window.attachEvent("onmessage" , WindowMessageHandler);
}
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
// ------------------------------------------------------------
// 全員に送信する
// ------------------------------------------------------------
var i;
var num = message_port_list.length;
for(i=0;i < num;i++){
var message_port = message_port_list[i];
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// チャンネル経由で相手にメッセージを送信する
// ------------------------------------------------------------
message_port.postMessage( request_obj );
}
};
// ------------------------------------------------------------
// 開くボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_open.onclick = function (e){
// ------------------------------------------------------------
// ウィンドウを作成する
// ------------------------------------------------------------
window.open(origin_allow + "/bbb.html" , "_blank" , "width=800,height=600");
};
})();
//-->
</script>
</body>
</html>
■ http://other.com 側の処理について
外部から開かれた相手に対して、チャンネルメッセージングを行う(この例では、http://my.com のみ信頼し、それ以外を拒絶している)
<html>
<body>
<fieldset style="padding:10px; margin-bottom:20px; background:#eef;" >
<legend>自身のコンテンツ</legend>
受信<br>
<textarea id="input_result" style="width:100%; height:100px; margin:0px 0px 20px 0px;" ></textarea><br>
送信<br>
<input type="text" id="input_message" style="width:100%; margin:0px 0px 10px 0px;" value="送信テスト" ><br>
<input type="button" id="input_post" style="width:100%; height:50px; margin:0px;" value="送信" >
</fieldset>
<script type="text/javascript">
<!--
// 匿名関数を即時実行
(function(){
// 自身用の MessagePort オブジェクト
var message_port = null;
// 信頼するオリジン
var origin_allow = "http://my.com";
// ------------------------------------------------------------
// 各要素を取得
// ------------------------------------------------------------
var element_result = document.getElementById("input_result");
var element_message = document.getElementById("input_message");
var element_post = document.getElementById("input_post");
// ------------------------------------------------------------
// MessageChannel に対応しているか調べる
// ------------------------------------------------------------
if(!(window.MessageChannel)) return;
// ------------------------------------------------------------
// MessageChannel オブジェクトを作成
// ------------------------------------------------------------
var message_channel = new MessageChannel();
// ------------------------------------------------------------
// 自身用の MessagePort オブジェクトを確保
// ------------------------------------------------------------
message_port = message_channel.port1;
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信時に実行されるイベント
// ------------------------------------------------------------
message_port.onmessage = function (e) {
// 出力テスト
element_result.value = "timeStamp:" + e.timeStamp + " origin:\"" + e.origin + "\"\n\n" + element_result.value;
// ------------------------------------------------------------
// 受信処理
// ------------------------------------------------------------
// 受信データを取得
var request_obj = e.data;
// 受信データを出力
element_result.value = "data:" + JSON.stringify(request_obj) + "\n" + element_result.value;
};
// ------------------------------------------------------------
// チャンネル経由のメッセージ受信を開始する
// ------------------------------------------------------------
message_port.start();
// ------------------------------------------------------------
// 送信ボタンをクリックした時に実行されるイベント
// ------------------------------------------------------------
element_post.onclick = function (e){
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {
message:element_message.value,
param:{}
};
// ------------------------------------------------------------
// 相手に送信する
// ------------------------------------------------------------
message_port.postMessage( request_obj );
};
// ------------------------------------------------------------
// 読み込み完了時に実行されるイベント
// ------------------------------------------------------------
window.onload = function (e){
// ------------------------------------------------------------
// 生成主ウィンドウを取得する
// ------------------------------------------------------------
var window_target = window.opener;
if(!window_target) return;
// ------------------------------------------------------------
// 送信用オブジェクト
// ------------------------------------------------------------
var request_obj = {command:"requestChannelMessaging"};
try{
// ------------------------------------------------------------
// 相手に MessagePort オブジェクトを送信する
// ------------------------------------------------------------
window_target.postMessage( request_obj , origin_allow , [message_channel.port2] );
}catch(e){
// ------------------------------------------------------------
// Safari 5 の場合 (第02引数と第03引数を入れ替える)
// ------------------------------------------------------------
// window_target.postMessage( request_obj , [message_channel.port2] , origin_allow );
}
};
})();
//-->
</script>
</body>
</html>