【特集】

詳解! HTML 5と関連APIの最新動向 - Webアプリ開発編

6 クロスドキュメントメッセージング

    白石俊平  [2009/08/17]

    HTML5から、ウィンドウ(フレーム)間でメッセージの送受信を行うための仕組みが用意された。この仕組みを用いると、対象となるウィンドウのインスタンスさえ手に入れば、同じオリジン(プロトコル+ドメイン + ポート番号)のWebページはもちろん、違うオリジンのWebページとも通信を行うことが可能だ。

    まず、他のウィンドウから送られてきたメッセージを受信するには、windowオブジェクトのmessageイベントを監視する必要がある。

    // messageイベントの監視
    window.addEventListener("message", function() {...}, false);
    

    他のウィンドウに対してメッセージを送信する場合は、window.postMessage()メソッドを使用する。

    postMessage(data, "targetOrigin");
    

    postMessage()の第1引数は送信するメッセージ本文で、任意のJavaScriptオブジェクトを指定することができる。

    第2引数は対象となるウィンドウのオリジンURLを文字列で指定する(例: "http://localhost:8080/")。これが実際のウィンドウのオリジンと一致していなければ、メッセージの送信に失敗する。ここには「すべてのサイト」を表す"*"(アスタリスク)を指定する事も可能だが、悪意のあるWebサイトに対して不用意にメッセージを送信してしまわないよう、既知のURLをできる限り指定したほうがよい。

    以上の知識があれば、ウィンドウ間でメッセージを送受信することができる。実際のサンプルを見てみよう。

    サンプル

    このサンプルは、iframe内のページとメッセージの送受信を行うものだ。

    1. 画面を表示するとiframe内のドキュメントに対してメッセージを送信する。
    2. iframe内のページはメッセージを受け取ると受け取ったメッセージをbody内に表示した後、メッセージをメインページに返信する。

    メッセージ受信

    1. メインページは受け取ったメッセージをアラートで表示する。

    メッセージをアラートで表示

    また、ページ自体はlocalhostの80番ポートで動作するWebサーバに配置したが、iframe内のページは「http://localhost:8080」がオリジンとなっており、クロスオリジンのデータ送受信を実現している。

    サンプルのソースコードを以下に示す。まずはメインページだ。

    main.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <script type="text/javascript">
    // (1) messageイベントを監視
    window.addEventListener("message", function(ev) {
      // (2) 既知のオリジンからのメッセージ以外は無視
      if (ev.origin != "http://localhost:8080") {
        return;
      }
      // (3) データの表示
      alert(ev.origin + "からのメッセージを受信しました:\n「" + ev.data + "」");
    }, false);
    
    function hello() {
      var iframe = window.frames[0];
      // (4) メッセージの送信
      iframe.postMessage("こんにちは", "http://localhost:8080/");
    }
    </script>
    </head>
    <body>
    <h1>クロスドキュメントメッセージングのテスト</h1>
    <iframe width="400" src="http://localhost:8080/frame.html" onload="hello()">
    </iframe>
    </body>
    </html>
    

    次に示すのはiframe内に表示するページのソースコードだ。

    frame.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <script type="text/javascript">
        window.addEventListener("message", function(ev) {
            if (ev.origin != "http://localhost") {
                alert(ev.origin);
                return;
            }
            document.body.innerHTML = ev.origin + "からのメッセージを受信しました:<br>「" + ev.data + "」";
            // (5) メインページに対してメッセージ送信
            ev.source.postMessage("こんにちは。こちらは" + this.location + "です。", ev.origin);
        }, false);
        </script>
    </head>
    <body></body>
    </html>
    

    このサンプルにおけるポイントを以下に示す。

    (1) windowオブジェクトのmessageイベントを監視することで、メッセージの受信を行える。

    (2) messageイベントのoriginプロパティにアクセスすると、メッセージ送信元のオリジンを取得することができる(この例では「http://localhost:8080」が返る)。悪意のあるページからのメッセージを処理しないためにも、オリジンのチェックは必須だ。

    (3) messageイベントのdataプロパティにアクセスすると、メッセージ本文(任意のJavaScriptオブジェクト)を取得することができる。

    (4) メッセージの送信にはpostMessage()を使用する。

    (5) messageイベントのsourceプロパティにアクセスすると、メッセージ送信元のwindowオブジェクト(正確にはWindowProxy)を取得することができる。

    このサンプルは、Firefox3.5、Safari4、Chrome3、Opera10での動作を確認した。

    関連したタグ

    新着記事

    特設サイトの情報

      人気記事

      一覧

        イチオシ記事

        新着記事

        特別企画

        マイナビニュースマガジン