2009-03-03 20 views
8

Actualmente estoy experimentando con la carga de archivos SWF externos desde una aplicación AS3 estándar y una aplicación de AIR. Parece que la aplicación de AIR no actúa de la misma manera que un archivo SWF estándar ejecutado por Flash Player.LoaderContext y ApplicationDomain cambia con Adobe AIR?

De acuerdo con documentation, la propiedad applicationDomain de LoaderContext también se puede usar en una aplicación de AIR, pero parece que no funciona.

tengo el siguiente código:

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")); 
     } 
    } 
} 

Compilar este código como un archivo SWF y el lanzamiento con el reproductor Flash hace esta salida, que parece derecho:

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

Pero el mismo código como una aplicación de AIR tiene una salida diferente:

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

De acuerdo con la documentatio n, la primera salida (utilizando un SWF con Flash Player, y no una aplicación de AIR) es la correcta. Además, jugar con este fragmento y cambiar el dominio de la aplicación a otras configuraciones posibles (como new ApplicationDomain(null) o ApplicationDomain.currentDomain) explica exactamente lo que dice la documentación con el archivo SWF, pero no cambia el resultado de la aplicación AIR.

¿Alguna pista de por qué AIR simplemente está ignorando el dominio de la aplicación pasado al contexto del cargador? ¿Alguna documentación sobre este tema en particular?

Muchas gracias.

Respuesta

14

Lo tengo.

El problema fue causado por un comportamiento diferente en el sistema SecurityDomain dentro de una aplicación de AIR. Cuando se carga un archivo SWF dentro de una aplicación de AIR, siempre depende de un entorno limitado diferente. Por lo tanto, AIR crea un nuevo SecurityDomain para este SWF.

Desde un SecurityDomain es un grupo de uno o más ApplicationDomain s, este comportamiento obligó a la creación de un nuevo ApplicationDomain (dentro de la nueva SecurityDomain), ignorando el especificado (que pertenecen a la 'principal' SecurityDomain).

Hay una solución usando URLLoader. Cuando se carga desde bytecode (usando Loader.loadBytes), se carga un SWF dentro del mismo SecurityDomain. Es por eso que debe poner el allowLoadBytesCodeExecution en verdadero, ya que puede ser inseguro. Entonces, cargando el SWF indirectamente, primero a través de URLLoader, y luego con Loader.loadBytes, resuelve este problema.

Aquí está el fragmento:

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")); 
     } 
    } 
} 

Espero que esto ayude.

+0

Tenga en cuenta que tendrá que utilizar [allowCodeImport] Según lo dicho por @pigiuz –

+0

He editado mi respuesta para tener esto en cuenta. ¡Gracias! – Tyn

1

que es una buena, Gracias :)

Sólo un detalle más: allowLoadBytesCodeExecution es ahora una propiedad heredada, que se definió en AIR 1.0. Desde AIR 2.0 en uso allowCodeImport en su lugar.

ciao, PG

Cuestiones relacionadas