2009-03-03 7 views
8

J'expérimente actuellement le chargement de fichiers SWF externes à partir d'une application AS3 standard et d'une application AIR. Il semble que l'application AIR n'agisse pas de la même manière qu'un SWF standard exécuté par Flash Player.LoaderContext et ApplicationDomain sont modifiés avec Adobe AIR?

Selon le documentation, la propriété applicationDomain de LoaderContext est également utilisable dans une application AIR, mais cela semble ne pas fonctionner.

je le code suivant:

package { 
    import flash.display.Loader; 
    import flash.display.LoaderInfo; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.net.URLRequest; 
    import flash.system.ApplicationDomain; 
    import flash.system.LoaderContext; 

    public class Invoker extends Sprite 
    { 
     private var _ldr : Loader; 

     public function Invoker() 
     { 
      _ldr = new Loader(); 
      _ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onChildOneComplete); 

      var ldrC : LoaderContext = new LoaderContext(false, 
       new ApplicationDomain(ApplicationDomain.currentDomain) 
      ); 

      _ldr.load(new URLRequest("otherSwf.swf"), ldrC); 
     } 

     private function onChildOneComplete(e : Event) : void 
     { 
      var c1ad : ApplicationDomain = (e.target as LoaderInfo).applicationDomain; 
      var inad : ApplicationDomain = ApplicationDomain.currentDomain; 

      trace("Child One parentDomain : " + c1ad.parentDomain); 
      trace("Invoker parentDomain : " + inad.parentDomain); 

      trace("Child One has Invoker : " + c1ad.hasDefinition("Invoker")); 
      trace("Invoker has Invoker : " + inad.hasDefinition("Invoker")); 
     } 
    } 
} 

Compiler ce code en tant que fichier SWF et le lancement avec Flash Player fait cette sortie, qui semble droite:

Child One parentDomain : [object ApplicationDomain] 
Invoker parentDomain : null 
Child One has Invoker : true 
Invoker has Invoker : true 

Mais le même code comme une application AIR fait une sortie différente:

Child One parentDomain : null 
Invoker parentDomain : null 
Child One has Invoker : false 
Invoker has Invoker : true 

Selon la documentatio n, la première sortie (en utilisant un fichier SWF avec Flash Player, et non une application AIR) est la bonne. En outre, en jouant avec cet extrait et en changeant le domaine d'application à d'autres configurations possibles (comme new ApplicationDomain(null), ou ApplicationDomain.currentDomain) fait exaclty ce que la documentation dit avec le SWF, mais ne change pas la sortie de l'application AIR.

Pourquoi AIR ignore-t-il simplement le domaine d'application transmis au contexte du chargeur? Toute documentation sur ce problème particulier?

Merci beaucoup.

Répondre

14

Vous l'avez.

Le problème a été causé par un comportement différent dans le système SecurityDomain dans une application AIR. Lorsqu'un fichier SWF est chargé dans une application AIR, il dépend toujours d'un sandbox différent. Ainsi, AIR crée un nouveau SecurityDomain pour ce fichier SWF.

Depuis un SecurityDomain est un groupe d'un ou plusieurs ApplicationDomain s, ce comportement a forcé la création d'une nouvelle ApplicationDomain (dans le nouveau SecurityDomain), en ignorant celui spécifié (qui appartiennent à la « principale » SecurityDomain).

Il existe une solution de contournement utilisant URLLoader. Lorsqu'il est chargé à partir du bytecode (en utilisant Loader.loadBytes), un fichier SWF est chargé dans le même SecurityDomain. C'est pourquoi vous devez mettre le allowLoadBytesCodeExecution à true, car il peut être dangereux. Donc, en chargeant le SWF indirectement, d'abord par un URLLoader, puis par Loader.loadBytes, résolvez ce problème.

Voici l'extrait:

package { 
    import flash.display.Loader; 
    import flash.display.LoaderInfo; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.net.URLLoader; 
    import flash.net.URLLoaderDataFormat; 
    import flash.net.URLRequest; 
    import flash.system.ApplicationDomain; 
    import flash.system.LoaderContext; 
    import flash.utils.ByteArray; 

    public class Invoker extends Sprite 
    { 
     public function Invoker() 
     { 
      var uldr : URLLoader = new URLLoader(); 
      uldr.dataFormat = URLLoaderDataFormat.BINARY; 
      uldr.addEventListener(Event.COMPLETE, onBytesComplete); 

      uldr.load(new URLRequest("otherSwf.swf")); 
     } 

     private function onBytesComplete(e : Event) : void 
     { 
      var bytes : ByteArray = (e.target as URLLoader).data; 

      var ldr : Loader = new Loader(); 
      ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onChildComplete); 

      var ldrC : LoaderContext = new LoaderContext(); 

      // This property was for AIR 1.0. 
      //ldrC.allowLoadBytesCodeExecution = true; 

      // Since AIR 2.0, it's allowCodeImport. 
      ldrC.allowCodeImport = true; 

      ldr.loadBytes(bytes, ldrC); 
     } 

     private function onChildComplete(e : Event) : void 
     { 
      var c1ad : ApplicationDomain = (e.target as LoaderInfo).applicationDomain; 
      var inad : ApplicationDomain = ApplicationDomain.currentDomain; 

      trace("Child One parentDomain : " + c1ad.parentDomain); 
      trace("Invoker parentDomain : " + inad.parentDomain); 

      trace("Child One has Invoker : " + c1ad.hasDefinition("Invoker")); 
      trace("Invoker has Invoker : " + inad.hasDefinition("Invoker")); 
     } 
    } 
} 

Hope this helps.

+0

Notez que vous aurez besoin d'utiliser [allowCodeImport] comme le dit @pigiuz –

+0

j'ai modifié ma réponse à prendre en compte. Merci! – Tyn

1

qui est un bon, merci :)

Juste un détail: allowLoadBytesCodeExecution est maintenant une propriété héritage, il a été défini dans AIR 1.0. À partir de AIR 2.0, utilisez allowCodeImport à la place.

ciao, PG