Question

This happens on many occasions when loading content from the web, but for us, it's most common loading images through Facebook's graph shortcut call.

Something as simple as:

package
{
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;

    public class RedirectTestFail extends Sprite
    {
        private const url:String = 'https://graph.facebook.com/4/picture';
        private const context:LoaderContext = new LoaderContext(true);

        public function RedirectTestFail()
        {
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
            loader.load(new URLRequest(this.url), this.context);
        }

        protected function onComplete(event:Event):void
        {
            this.addChild((event.target as LoaderInfo).content);
        }
    }
}

Gives a dreaded "SecurityError: Error #2122" error.

Was it helpful?

Solution

Despite other answers suggesting something as simple as:

Security.loadPolicyFile("https://fbcdn-profile-a.akamaihd.net/crossdomain.xml");

This isn't clear, nor comprehensive enough. Facebook have different image servers, that I've which I've been caught with before. This could be deemed a Flash Player Bug, which I'd accept, but as a security concern, I can understand them not allowing a redirect by default, as in you should handle it yourself.

I now use below. You try to do your normal behaviour, but wrap it in a try/catch for SecurityError. If one is thrown, catch it, and if the domain of the loaderInfo is different to the domain you requested, you run a 'Security.allowDomain' and 'Security.loadPolicyFile' on it, and attempt to load it one more times. This works perfectly in practise, with only a tiny amount of overhead.

package
{
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.system.Security;

    public class RedirectTest extends Sprite
    {
        private const url:String = 'https://graph.facebook.com/4/picture';
        private const context:LoaderContext = new LoaderContext(true);

        public function RedirectTest()
        {
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
            loader.load(new URLRequest(this.url), this.context);
        }

        protected function onComplete(event:Event):void
        {
            try
            {
                this.addChild((event.target as LoaderInfo).content);
            } 
            catch(error:SecurityError) 
            {
                trace(error);
                var loaderInfo:LoaderInfo = (event.target as LoaderInfo);
                var loaderDomain:String = loaderInfo.loader.contentLoaderInfo.url;
                if(-1 == this.url.indexOf(loaderDomain))
                {
                    Security.loadPolicyFile(loaderDomain + 'crossdomain.xml');
                    if( 0 == loaderDomain.indexOf('https') )
                    {
                        Security.allowDomain(loaderDomain);
                    }
                    else
                    {
                        Security.allowInsecureDomain(loaderDomain)
                    }

                    loaderInfo.loader.load(new URLRequest(this.url), this.context);
                    return;
                }
                throw error;
            }
        }
    }
}

OTHER TIPS

if you no need to manipulate pixels with loaded image BitmapData object, then you can just remove context from the loader.load

but without context.checkPolicyFile = true you will cant add smoothing to image

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top