mudanças LoaderContext e ApplicationDomain com o Adobe AIR?
-
03-07-2019 - |
Pergunta
Atualmente estou experimentando com o carregamento de arquivos SWF externos, tanto uma aplicação AS3 padrão, e um aplicativo AIR. Parece que o aplicativo AIR não age da mesma forma um SWF padrão correr pelo Flash Player faz.
De acordo com a , a propriedade applicationDomain
de LoaderContext
é utilizável em um aplicativo AIR também, mas ele só parece não estar funcionando.
Eu tenho o seguinte 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 um arquivo SWF e lançá-lo com o Flash Player faz esta saída, o que parece certo:
Child One parentDomain : [object ApplicationDomain]
Invoker parentDomain : null
Child One has Invoker : true
Invoker has Invoker : true
Mas o mesmo código como um aplicativo AIR faz uma saída diferente:
Child One parentDomain : null
Invoker parentDomain : null
Child One has Invoker : false
Invoker has Invoker : true
De acordo com a documentação, a primeira saída (usando um SWF com o Flash Player, e não um aplicativo AIR) é o caminho certo. Além disso, a brincar com esse trecho e mudando o domínio de aplicação para os outros possíveis configurações (como new ApplicationDomain(null)
, ou ApplicationDomain.currentDomain
) faz exaclty o que diz a documentação com o SWF, mas não altera a saída do aplicativo AIR.
Qualquer indício porque AIR é simplesmente ignorando o domínio de aplicação passou para o contexto loader? Toda a documentação sobre este assunto particular?
Muito obrigado.
Solução
Got-lo.
O problema foi causado por um comportamento diferente no sistema SecurityDomain
dentro de um aplicativo AIR. Quando um arquivo SWF é carregado dentro de um aplicativo AIR, ele sempre dependem de uma sandbox diferente. Assim, o AIR cria uma nova SecurityDomain
para este SWF.
Uma vez que um SecurityDomain
é um grupo de uma ou mais ApplicationDomain
s, este comportamento forçou a criação de uma nova ApplicationDomain
(dentro do novo SecurityDomain
), ignorando o especificado (que pertencem ao SecurityDomain
'main').
Existe uma solução usando URLLoader
. Quando carregado a partir de código de bytes (usando Loader.loadBytes
), um SWF é carregado dentro da mesma SecurityDomain
. É por isso que você tem que colocar o allowLoadBytesCodeExecution
a verdade, uma vez que pode ser inseguro. Então carregar o SWF indiretamente, primeiro embora uma URLLoader
, e depois com Loader.loadBytes
, resolver esta questão.
Aqui está o trecho:
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 isso ajude.
Outras dicas
que é uma boa, thanx:)
Apenas mais um detalhe: allowLoadBytesCodeExecution é agora uma propriedade legado, foi definido no AIR 1.0. De AIR 2.0 em uso allowCodeImport em seu lugar.
ciao, PG