Pregunta

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

De acuerdo con la documentación , 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"));
        }
    }
}

La compilación de este código como un archivo SWF y su lanzamiento con Flash Player hace este resultado, que parece correcto:

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

Pero el mismo código que una aplicación de AIR hace un resultado diferente:

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

De acuerdo con la documentació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 de código y cambiar el dominio de la aplicación a otras configuraciones posibles (como new ApplicationDomain (null) o ApplicationDomain.currentDomain ) hace exactamente lo que dice la documentación con El SWF, pero no cambia la salida de la aplicación AIR.

¿Alguna pista de por qué AIR simplemente ignora el dominio de la aplicación que se pasa al contexto del cargador? ¿Alguna documentación sobre este tema en particular?

Muchas gracias.

¿Fue útil?

Solución

Lo tengo.

El problema se debió a 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 sandbox diferente. Por lo tanto, AIR crea un nuevo SecurityDomain para este SWF.

Dado que un SecurityDomain es un grupo de uno o más ApplicationDomain s, este comportamiento forzó la creación de un nuevo ApplicationDomain (dentro del nuevo SecurityDomain ), ignorando el especificado (que pertenece al 'main' SecurityDomain ).

Hay una solución alternativa utilizando URLLoader . Cuando se carga desde el bytecode (usando Loader.loadBytes ), un SWF se carga dentro del mismo SecurityDomain . Esta es la razón por la que tiene que poner el allowLoadBytesCodeExecution en true, ya que puede ser inseguro. Entonces, cargando el SWF indirectamente, primero a través de un URLLoader , y luego con Loader.loadBytes , resuelva 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.

Otros consejos

esa es buena, gracias :)

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

ciao, PG

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top