Question

Je teste 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 géré par Flash Player.

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

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

La compilation de ce code en tant que fichier SWF et son lancement avec Flash Player produisent cette sortie qui semble correcte:

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

Mais le même code qu'une application AIR produit une sortie différente:

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

Selon la documentation, la première sortie (à l'aide d'un fichier SWF avec Flash Player et non d'une application AIR) est la bonne. De plus, jouer avec cet extrait de code et changer le domaine d'application en d'autres configurations possibles (comme nouveau ApplicationDomain (null) ou ApplicationDomain.currentDomain ) ne fait que ce que dit la documentation SWF, mais ne modifie pas la sortie de l’application AIR.

Avez-vous la moindre idée pourquoi AIR ignore simplement le domaine d'application transmis au contexte du chargeur? Une documentation sur ce problème particulier?

Merci beaucoup.

Était-ce utile?

La solution

J'ai compris.

Le problème était dû à un comportement différent du système SecurityDomain au sein d'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 SWF.

Etant donné qu'un SecurityDomain est un groupe d'un ou plusieurs ApplicationDomain , ce comportement a forcé la création d'un nouveau ApplicationDomain (au sein du nouveau SecurityDomain ), en ignorant celui spécifié (appartenant au 'principal' SecurityDomain ).

Il existe une solution de contournement utilisant URLLoader . Lorsqu’il est chargé à partir de bytecode (avec Loader.loadBytes ), un fichier SWF est chargé dans le même SecurityDomain . C'est pourquoi vous devez attribuer la valeur true à allowLoadBytesCodeExecution , car cela peut être dangereux. Alors, chargez le fichier SWF indirectement, d'abord via un URLLoader , puis avec Loader.loadBytes , résolvez ce problème.

Voici l'extrait de code:

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

J'espère que cela vous aidera.

Autres conseils

c’est une bonne chose, merci:)

Encore un détail: allowLoadBytesCodeExecution est maintenant une propriété héritée, elle a été définie dans AIR 1.0. Depuis AIR 2.0, utilisez plutôt allowCodeImport .

ciao, PG

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top