プログラミングノート

一からものを作ることが好きなエンジニアの開発ブログです。

sandbox間で通信を連携する方法

AIRにはAIR APIを利用できクロスドメインの制約のない変わりにJavascriptの機能が十分に利用できないsandboxと、Javascriptはブラウザと同じように利用できる変わりにAIR APIが利用できないnon-application sandboxがあります。


Extなどのライブラリを利用する場合は必然的にnon-application sandboxを利用することになりますが、IFRAMEを利用する際に『sandboxRoot="http://exsample.com/"』で指定しているURLはAIRがローカルディレクトリに置き換えてしまうため通常通りアクセスできなくなります。そのため、自分で作ったXML/JSON取得サーバへもクロスドメイン制約によりアクセスできなくなってしまうという問題が発生します。(localhostでやっててはまりました。。全部JSONPで公開すれば問題ないですが)


そこで、通信は制約のないapplication sandbox(main.html)で行い、その他処理はnon-application sandbox(SampleUI.html)で行えるようにしてみました。sandbox間でオブジェクトを公開するためのプロパティ(parentSandboxBridgeとchildSandboxBridge)を利用し、通信実行時はmain.htmlのメソッドにアクセス、通信終了時にSmapleUI.htmlのメソッドにデータを渡しています。


main.html (application sandbox)

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<script type="text/javascript" src="ext/adapter/jquery/jquery.js"></script>
<script type="text/javascript">
  
window.onload = function(){  
  //iframe(non-application sandbox)の公開オブジェクトを取得
  window.childInterface = document.getElementById("sandbox").contentWindow.childSandboxBridge;

  //frame(application sandbox)のオブジェクトを公開
  document.getElementById("sandbox").contentWindow.parentSandboxBridge = {
    access : function(target, url){
      $.ajax({
        url: url,
        success: function(data){
          window.childInterface.success(target, data);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
          window.childInterface.error(target, XMLHttpRequest, textStatus, errorThrown);
        }
      });
    }
  };
};
</script>
</head>
<body>
<!-- non-application sandbox -->
<iframe id="sandbox"
  src="http://exsample.com/SampleUI.html"
  sandboxRoot="http://exsample.com/"
  documentRoot="app:/"
  style="width:100%; height:100%;border:none"
  >
</iframe>
</body>
</html>


SampleUI.html (non-application sandbox)

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<script type="text/javascript" src="ext/adapter/jquery/jquery.js"></script>
<script type="text/javascript">

//テスト用のクラス
(function(){
  var Http = function(){};
  Http.prototype = {
    access : function(){
      window.parentSandboxBridge.access('Http', 'http://www.google.co.jp');
    },
    success : function(data){
      $("#Http").append(data);
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
      $("#Http").append("ERROR");
    }
  };
  window.Http = new Http();  
})();

//frame(application sandbox)にオブジェクトを公開
window.childSandboxBridge = {
  success : function(target, data){
    eval(target).success(data);
  },
  error: function(target, XMLHttpRequest, textStatus, errorThrown) {
    eval(target).error(XMLHttpRequest, textStatus, errorThrown);
  }
};
</script>
</head>
<body>
<button onClick="Http.access()">application sandboxの関数経由で通信</button>
<div id="Http"></div>
</body>
</html>


まだ実際に使ってないのですが、とりあえず通信はできているのでパラメタとか増やして改良すれば使えそうな感じです。もっといい方法や、そもそもこんなことしなくても通信できるよみたいなツッコミ歓迎です。ちなみに、application sandboxではscriptタグを動的に挿入できないようになっているみたいで、JSONPは利用できないのでご注意を。