Domanda

Attualmente sto sperimentando il caricamento di file SWF esterni sia da un'applicazione AS3 standard sia da un'applicazione AIR. Sembra che l'applicazione AIR non si comporti allo stesso modo di un SWF standard gestito da Flash Player.

Secondo la documentazione , la proprietà applicationDomain di LoaderContext è utilizzabile anche in un'applicazione AIR, ma sembra non funzionare.

Ho il seguente codice:

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

Compilando questo codice come file SWF e avviandolo con Flash Player si ottiene questo risultato, che sembra giusto:

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

Ma lo stesso codice di un'applicazione AIR produce un output diverso:

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

Secondo la documentazione, il primo output (utilizzando un SWF con Flash Player e non un'applicazione AIR) è quello giusto. Inoltre, giocare con questo frammento e cambiare il dominio dell'applicazione con altre possibili configurazioni (come new ApplicationDomain (null) o ApplicationDomain.currentDomain ) fa esattamente ciò che dice la documentazione il file SWF, ma non modifica l'output dell'applicazione AIR.

Qualche idea sul perché AIR stia semplicemente ignorando il dominio dell'applicazione passato al contesto del caricatore? Qualche documentazione su questo particolare problema?

Grazie mille.

È stato utile?

Soluzione

Capito.

Il problema è stato causato da un comportamento diverso nel sistema SecurityDomain all'interno di un'applicazione AIR. Quando un file SWF viene caricato all'interno di un'applicazione AIR, dipende sempre da un sandbox diverso. Pertanto, AIR crea un nuovo SecurityDomain per questo file SWF.

Poiché un SecurityDomain è un gruppo di uno o più ApplicationDomain , questo comportamento ha costretto la creazione di un nuovo ApplicationDomain (all'interno del nuovo SecurityDomain ), ignorando quello specificato (che appartiene al SecurityDomain 'principale').

Esiste una soluzione alternativa utilizzando URLLoader . Se caricato da bytecode (utilizzando Loader.loadBytes ), un file SWF viene caricato nello stesso SecurityDomain . Questo è il motivo per cui devi mettere allowLoadBytesCodeExecution su true, poiché può non essere sicuro. Quindi, caricando indirettamente il file SWF, prima tramite URLLoader , quindi con Loader.loadBytes , risolvi questo problema.

Ecco lo snippet:

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

Spero che questo aiuti.

Altri suggerimenti

questo è buono, grazie :)

Solo un altro dettaglio: allowLoadBytesCodeExecution è ora una proprietà legacy, è stata definita in AIR 1.0. Da AIR 2.0 in poi usa allowCodeImport invece.

Ciao, PG

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top