続々:Security Sandbox Violation in DragManager

まずは解決編。解決方法だけ判ればいい人はこちらで。

doDrag(..args)はstageにaddChildされているコンポネント全てに対して実施されてしまいます。そのため、ドラッグする可能性のあるImageInstanceを含むコンポネントは、外部からImageを読み込む場合は、Image.load(..arg)を読み込まないことが、考えられる対策の一つです。

簡単に書くと従来方式では下記の感じですが

//従来方式
var imageInstance:Image = new Image();
imageInstance.load("url") // これはダメ。

解決する方法ではこんな感じ

//解決方法
private var imgLoader:Loader;
private var imgInstance:Image;


  //doDragで、Security Sandbox Violationを避けるやり方
  imgLoader = new Loader() //SWFLoaderは念のため使わない
  var imgLoader.contentLoaderInfo.addEventListener(Event.Complete, onComplete);
  imgInstance = new Image();

/* ..中略.. */ 

private function onComplete(ev:Event):void{
  imgInstance.source = imgLoader.content;
  imgLoader.contentLoaderInfo.removeEventListener(Event.Complete, onComplete);
  anyContainer.addChild(imgInstance);
}

という風にやって、LoaderとロードしたImageを完全に分離します。こうすることによってdoDrag(..args)がImageInstanceのセキュリティサンドボックス呼び出しても、参照先はあくまでimgLoader.contentなので、Imageから例外が発生することはなくなります。ということで一日中悩んだ末に一応解決出来て良かった・・・。余計にインスタンスつくるから美しく無いけど。自分でクラス拡張して隠蔽しちゃうのがいいかもなー。

                        • -

ここから解説編。


Imageを利用している場合のDragManagerの処理についての続報です。無理くりブレークポイントを仕込んでどんどん潜っていった所、sandBoxRootのEventDispatcherからSWFLoaderが呼び出されていることが判りました。

その中に

//in DragManagerImpl

do Drag(.. args):void{
/* ..中略.. */ 

var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
/* ..中略.. */ 
		me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
		me.name = "mouseShield";
		me.value = true;
		// trace("-->dispatch add mouseShield.for DragManagerImpl", sm);
		sandboxRoot.dispatchEvent(me); //ここでSWFLoader呼び出し

/* ..後略.. */ 

これによって、SWFLoaderでは

//in SWFLoader

 private function mouseShieldHandler(event:Event):void{

/* ..中略.. */ 
               if (event["value"])
                {
                        if (!mouseShield)
                        {
                                mouseShield = new Sprite();
                                mouseShield.graphics.beginFill(0, 0);
                                mouseShield.graphics.drawRect(0, 0, 100, 100);
                                mouseShield.graphics.endFill();
                        }
                        //ここらへんで、SWFLoaderは自身を更新するっぽい
                        if (!mouseShield.parent) 
                                addChild(mouseShield);
                        sizeShield();

/* ..後略.. */ 
}

そのため、直接ImageInstance.load()を使ってロードした場合、イメージのロードは実施しないものの、上記の手順によって再度セキュリティサンドボックスをチェックすることになります。おそらく、ImageIntance.load()メソッドではSecurity Sandbox Violationをエスケープする記述がされているのだと思うのですが、doDrag(..args)のsandboxRootからの指示はエスケープしないままになっているのでしょう。

つまり、DragManagerImpl.doDrag(..args)内で呼ばれるsandboxRootからの呼び出しでは、ImageもSWFLoaderとして認識されているので、ロードされるものは全て "swf"として認識しているということですね。だからViolationが出ていたのです。


一言で言えば、バグだろこれ!!!!!


なんで、ImageInstance().load(arg)で登録される、ImageIntance.loaderInfoのイベントリスなを全て破棄できれば、分離用のLoaderインスタンスは必要ない気がします。ただ、私には破棄方法がわからないので、誰か細くして頂けると幸い。


参考:http://shigeru-nakagaki.com/index.cfm?mode=entry&entry=BBF19E0A-3048-79ED-9954405BB1D8F592&lang=ja_JP