AIR Loading server hosted swf into same sandbox

2019-02-25 14:58发布

问题:

I have an AIR App I'm working on and need to load a swf(always from localhost) which will access some methods in it's parent and vice versa. I'm not concerned with opening gaping security holes in a desktop app though. I've been searching all over but keep hitting walls with each implementation out there.

My current setup loads in the swf and it plays but I get a small error from the sandbox since I'm not in the same one as the app. Does anyone know how to get past this error so there is complete freedom opened up between the AIR app and the swf?

* Security Sandbox Violation *

SecurityDomain 'http://localhost/test.swf' tried to access incompatible context 'app:/Test_Player.swf'

public function loadSWF():void {

//var context:LoaderContext = new LoaderContext();
//context.checkPolicyFile = true;
//context.applicationDomain = ApplicationDomain.currentDomain;
//context.securityDomain = SecurityDomain.currentDomain;

var req:URLRequest = new URLRequest(swfURL);
adLoader = new Loader();

videoCanvas.rawChildren.addChild(adLoader);

loader.contentLoaderInfo.addEventListener(Event.INIT, adLoadedHandler, false, 0, true);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError, false, 0, true);

//loader.load(req, context);
loader.load(req);
}

回答1:

You need to load your distant SWF with an UrlLoader and then reload it through loadByte. With this method you will by pass security.

package
{
    import flash.display.Loader;
    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;

    public class TestDistantSwf extends Sprite
    {
        private var _urlLoader : URLLoader = new URLLoader;
        private var _loader : Loader = new Loader;

        public function TestDistantSwf()
        {

            addChild(_loader);
            // Won't work
            //_loader.load(new URLRequest("http://localhost/test.swf"));

            // Load it as binary
            _urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
            _urlLoader.addEventListener(Event.COMPLETE, onLoad);
            _urlLoader.load(new URLRequest("http://localhost/test.swf"));
        }

        private function onLoad(e : Event) : void
        {
            // Load distant swf data locally
            _loader.loadBytes(_urlLoader.data, new LoaderContext(false, ApplicationDomain.currentDomain));
        }
    }
}

If you need to pass arguments like flash var, two way to do it, if use Air 2.6 or later, you can use LoaderContext.parameters :

private function onLoad(e : Event) : void
{
    var lc : LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
    lc.parameters ={
        foo:"hello !"
    };
    lc.allowCodeImport = true;

    // Load distant swf data locally
    _loader.loadBytes(_urlLoader.data, lc);
}

And then get it with loaderInfo.parameters in your loaded SWF.

Or you can call a function of loaded Swf :

private function onLoadBinary(e : Event) : void
{
    e.target.content.init("hello 2 !");
}

private function onLoad(e : Event) : void
{
    var lc : LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
    lc.allowCodeImport = true;

    // Load distant swf data locally
    _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadBinary);
    _loader.loadBytes(_urlLoader.data, lc);
}

This will call from loaded swf in its main class:

public function init(foo : String) : void
{
    trace(foo);
}