PostMessageを使ったクロスドメイン通信によるメッセージの送受信を試してみた!

javascript

JavaScriptでいろいろ実装していると時に別ウィンドウを開いて、呼び出し元のウィンドウとの間で通信をしたい時に立ちはだかるのがクロスドメイン問題です。

クロスドメイン自体は、異なるドメイン間をまたがったデータのやり取りする事なんですが、なんとhtml5から新たに使えるようになったpostMessageという機能がありまして、このpostMessageを使えば異なるドメイン間でのデータの通信ができるので今回はそのpostMessageの使い方を少し紹介したいと思っています。

Web Messagingとは?

コードによるほかのウィンドウ、タブ、フレームへのアクセスは、通常、セキュリティ上の理由から、同一オリジンのドキュメントの間だけに制限されています。

クロスドメインとは、異なるドメイン間をまたがったデータに対してアクセスをすることを言うんですが、調べてみると異なるドメイン間でメッセージ送信が可能のようで、この異なるオリジンの間での通信を安全に行うことを目的としたAPIとして、postMessageとMEssageEventがあるようです。またMessageChannelという2つのポートを利用した送受信もあるようですが、それは追々時間があったときにでも

Web Messagingの流れと解説

さて、ここからが本題ですが、メッセージを送信・受信するにはhtml5のjavascript apiを利用します。

windowオブジェクトに用意されている「postMessage」というメソッドで送信して、windowオブジェクトの「onmessage」イベントが発生して受信する流れになります。

1:postMessageのよるメッセージを送信

targetWindow.postMessage("送信するメッセージの値","オリジン");
targetWidow

targetWidowとは、適当に名前をつけましたが、別ウィンドウへの参照。例えば、iframe要素のcontentWindowプロパティの利用、window.open によって返されるオブジェクトなどがあたります。

オリジンについて

オリジンとは、ページはどこから持ってきたものかを示す情報ですが、ドキュメントのURLのスキーム・ドメイン・ポートを指します。

サンプルではこの「js do it」のサービスを利用させていただいてるのですが、オリジンには「http://jsrun.it」のドメインを指定しています。

2:MessageEventによるメッセージ受信

//
window.onmessage=function(event){};

//
window.addEventListener("message",function(event){});

MessageEventには3つのプロパティがあります。そのプロパティはeventオブジェクトから参照します。

event.data

送信元のウィンドウから渡されるメッセージを保持しているオブジェクト

event.origin

メッセージを送る送信元であるウィンドウのorigin

event.source

メッセージを送った送信元のwindowオブジェクトへの参照。

サンプルのhtmlファイル

今回はとりあえず、メッセージの受信先のウィンドウを開いてそこにテキストフィールドに入力した内容を送信してみようと思う。

htmlファイルの構造で必要最低限の部分だけ抜き出してます。

送信元のhtmlファイル






各IDとその役割

sbtn メッセージの受信先となるウィンドウを開くボタン
message 送信するメッセージを記入するエリア
btn メッセージを送信するボタン

と、まぁいたって普通ですが、実際にサンプルを実行する際はまず、メッセージの受信先となるウィンドウを必ず先に開く必要がある。

これは後述しますが、javascriptで送信する際に、受信先のウィンドウオブジェクトを取得しておく必要があるからです。

受信先のhtmlファイル


//受信データを表示するためのエリア

サンプルのjavascriptファイル(送信元)

まずは、送信元となるファイルのjavascriptに関する説明。*ざっくりで申し訳ないのだが・・

//1:各要素を取得
var btn=document.getElementById("btn");
var sbtn=document.getElementById("sbtn");
var textdata=document.getElementById("message");
var pop;

sbtn.addEventListener("click",function(){

//2:window.openで受信先のwindowオブジェクトを変数に保持する
pop=window.open('http://jsrun.it/assets/k/9/M/W/k9MWq', 'mywindow1',"width=300, height=200");
					
},false);
				
btn.addEventListener("click",function(){
    //3:テキストデータを取得してpostMessageで送信
	var t=textdata.value;
	//post-message
	pop.postMessage(t,"http://jsrun.it");
					//
		return false;
	},false);

1:各要素を取得

あまり説明も必要ないと思うが流れ上一応(笑) 各ボタンやテキストエリアなどを取得。

2:window.openで受信先のwindowオブジェクトを変数に保持する

となる、ファイルをwindow.openで開き、その受信先windowオブジェクトを変数popに代入しておく。

注意点として、受信先のwindowオブジェクトを取得しておかないと、postMessageメソッドが動作しないので先にwindow.openでウィンドウを開いて、windowオブジェクトを取得しておく必要がある。

3:テキストデータを取得してpostMessageで送信

テキストエリアに入力されたデータを取得して受信先のwindowオブジェクトよりpostMessageメソッドを呼び出して送信する。

サンプルのjavascriptファイル(受信先)

window.addEventListener('message', function(event){

//event.dataより受信データを取得する
var msg = '受信メッセージ: 
' + event.data; document.getElementById('get-message').innerHTML = msg; });

event.dataより受信データを取得する

event.dataに受信したテキストの内容が保存されているので、そのデータを受信先のdiv要素にinnerHTMLで表示しています。

参考サイト

今回は、ちょっと長くなったので下記にまとめました。