| 目次 |
|---|
|
・クロスドキュメントメッセージングとは |
クロスドキュメントメッセージングは、異なるドメイン(及びオリジン)のフレーム間でメッセージ通信を行うメカニズムを提供します。
<iframe>要素などを使うと、一つのページの中に複数のページを内包することができます。
しかし、フレーム内のページは表示は出来るものの、親ページ(フレーム)からJavascriptなどで操作することはできません。
URLにパラメータをつけて、フレーム内のページを変更することは可能ですが、ページそのものが更新するために(時間、メモリ消費などの)コストがかかります。
Javascriptなどスクリプトからサイト(フレーム)間の操作を行うことをクロスサイトスクリプティングといいます。
このクロスサイトスクリプティング、セキュリティとプライバシー保護の観点から必要不可欠な制限です。
しかし、この制限により、異なるドメイン間での通信手段がなく、WEBアプリケーションの障害になる場合がありました。
また同じドメインでも、httpプロトコルとSSLプロトコルなど、プロトコルが変わっても操作及び通信できなくなります。
このような「スキーマ(httpなど):ドメイン名:ポート番号」の組み合わせを「オリジン(orgin)」といいます。
先のセキュリティとプライバシー保護の観点から制限は、異ドメイン間だけでなく、異オリジン間にも適用されます。
そのため、httpプロトコルとSSLプロトコルで通信ができません。
html5では、クロスドキュメントメッセージング(Cross-document messaging)と呼ばれる仕様を導入することで、この問題の解決方法としています。
但し、異なるオリジン間のDOMを直接操作することはできません。
それそれのオリジンから、メッセージを送り、それを受信します。
オリジン間でメールのやりとりのようなことをすることで、異なるオリジン間をつなぎます。
クロスドキュメントメッセージングは、2011年8月現在以下のブラウザで対応しています。
FireFox 3.5~、Safari 4~、Opera 10.6~、Google Chrome 3~、IE 8~
次のサンプルスクリプトはクロスドキュメントメッセージングを使った例です。
※本来は異なるオリジン間で行いますが、本ページでは便宜上同一オリジン間にて通信を行います。
クロスドキュメントメッセージングは、ページ内にWindowProxyオブジェクトを用意します。
WindowProxyオブジェクトは、フレーム側のWindowsオブジェクトのことです。
内包するフレーム(<iframe>要素など)のcontentWindowプロパティで得ることができます。
フレーム(オリジン)間をつなぐのは「postMessage」メソッドです。
この「postMessage」メソッドで異なるオリジン間でデータのやりとりをします。
クロスドキュメントメッセージングのイベントは「onmessage」です。
リスト1. クロスドキュメントメッセージングの例(親フレーム側=このページ)
<h5>送信内容</h5>
<form id="fm0201" onsubmit="return false;">
<input id="inp0201" type="text" placeholder="メッセージ" />
<button id="btn0201" onclick="go0201();">メッセージ送信</button>
</form>
<iframe id="frm0201" src="html5_2211.html" class="OurFrm" ></iframe>
<script type="text/javascript">
//messageイベントの定義
window.addEventListener( 'load', function(){
//messageイベントのリスナをセット
window.addEventListener( 'message', rcvMe, false);
}, false);
//受け取り側コールバック
function rcvMe(evt){
/*
子フレーム(ウインドウ)には送信できます。
親フレーム(ウィンドウ)のは、IE、Safari、Chrome は問題ないのですが
FireFox、Operaは、2011年8月現在 戻ってきません。(エラーにもなりません)
*/
var pnl = document.getElementById("resP");
var org = 'http://www.nail-kobe.com';
//受信オリジンのチェック
if( evt.origin != org ){
return;
}
//戻った結果を表示
pnl.innerHTML = pnl.innerHTML + evt.data + "<br/>\n";
}
//送信ボタンのクリック
function go0201(){
var msg = document.getElementById("inp0201");
var frm = document.getElementById("frm0201");
var org = 'http://www.nail-kobe.com';
msg.value = ( msg.value === null ) ? "" : msg.value;
msg.value = ( msg.value === false ) ? "" : msg.value;
if( msg.value != "" ){
frm.contentWindow.postMessage( msg.value, org );
}
else
{
alert('メッセージを入れてください。');
}
}
</script>
リスト2. クロスドキュメントメッセージングの例(子フレーム側=html5_2211.html)
<dl id="rcvMsg"></dl>
<script type="text/javascript">
//messageイベントの定義
window.addEventListener( 'load', function(){
//messageイベントのリスナをセット
window.addEventListener( 'message', rcvMe, false);
}, false);
//受け取り側コールバック
function rcvMe(evt){
var dl = document.getElementById("rcvMsg");
var org = 'http://www.nail-kobe.com';
//現在時刻
var now = new Date();
var nh = now.getHours();
var nn = now.getMinutes();
var ns = now.getSeconds();
var tm = nh + ":" + nn + ":" + ns;
//受信オリジンのチェック
if( evt.origin != org ){
return;
}
//受取時刻を返信
var src = evt.source;
var snd = tm + " 次を受け取りました。:" + evt.data;
src.postMessage( snd, org );
//受け取った内容の表示
var msg = "\n";
msg = msg + "<dt>オリジン</dt>\n";
msg = msg + "<dd>" + evt.origin + "</dd>\n";
msg = msg + "<dt>メッセージ</dt>\n";
msg = msg + "<dd>" + evt.data + "</dd>\n";
msg = msg + "<dt>受取時刻</dt>\n";
msg = msg + "<dd>" + tm + "</dd>\n";
dl.innerHTML = msg;
}
</script>
実装例