Mar 15, 2010

Flash Files, Domains and Security Errors (Oh My)

To provide a better user experience, we often use content delivery solutions like Limelight or Akamai to host bigger files and reduce load time. (Although this cuts into the user's time spent watching pretty loaders.)

During a recent project, we ran into a couple of security errors loading external module.swf files from a different domain than main.swf. The idea was to have a basic framework in main that controls IN and OUT animations of the modules and have all additional functionality in the module.swf itself. All loaded swf files extended Big Spaceships StandardInOut Class to be controllable from the main file, so we could easily cast the loaded modules.

It looked like this:
private function _onLoadComplete_handler($evt:Event):void{
	var loadedFile:MovieClip = MovieClip($evt.target.content);
	var customInOut:StandardInOut = StandardInOut(loadedFile.customInOut);
}

This worked without any problems until the Flash files were loaded from different servers, hence different domains. The following error appeared:

TypeError: Error #1034: Type Coercion failed: cannot convert com.bigspaceship.display::StandardInOut@475f7711 to com.bigspaceship.display.StandardInOut.

After a little research, we had a list of possible solutions. We made sure all crossdomain.xml files were in place and set up correctly, added Security.allowDomain("*"); to each file and tried to set LoaderContext.applicationDomain = ApplicationDomain.currentDomain. Sadly, none of that helped.

What did the trick (in part) was setting the LoaderContext.securityDomain:
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLoadComplete_handler);
var urlRequest:URLRequest = new URLRequest('http://domain.com/extFile.swf');
var context:LoaderContext = new LoaderContext();
context.securityDomain = SecurityDomain.currentDomain;
l.load(urlRequest, context);

This worked fine once it was running on the server, but testing locally lead to the following error:

SecurityError: Error #2142: Security sandbox violation: local SWF files cannot use the LoaderContext.securityDomain property. file:///Macintosh%20HD/Users/xxx/loadExtSWFTests/bin/main.swf was attempting to load http://domain.com/extFile.swf.

A simple trick to get around that would be to use error handling:
try{
	l.load(urlRequest, context);
}catch($error:Error){
	l.load(urlRequest);
}

But that’s not an ideal solution. What we really needed was a test to check if the main Flash file was running on a server or running locally and then use the corresponding path and only set context.securityDomain = SecurityDomain.currentDomain if running on the server.

To test that, we simply checked if Security.sandboxType == Security.REMOTE, which means that the file is from an Internet URL and operates under domain-based sandbox rules.

The final solution looked something like this:
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLoadComplete_handler);
if(Security.sandboxType == Security.REMOTE){
	var context:LoaderContext = new LoaderContext();
	context.securityDomain = SecurityDomain.currentDomain;
	l.load(new URLRequest('http://domain.com/extFile.swf'), context);
}else{
	l.load(new URLRequest('extFile.swf'));
}

Hope that helps everyone who has or might run into similar problems.

-----------------------------------

*Sidenote on dynamically instantiating assets from the library that use the same export name in multiple loaded flash files: Loading a swf with loaderContext.applicationDomain set to ApplicationDomain.currentDomain overwrites the current library asset with the same export name. Otherwise Flash ignores newly loaded library assets and always uses the asset that is already in the main library.

Share this Post


                           

Comments


Pişirme Oyunları     Jun 25, 2010
@jeffery i have the same question as tod,, is there anyway at all for two separate securityDomains (one local, one remote) to share the same applicationDomain?

habika     Jun 22, 2010
One security point we ran into as well was a very weird cross-domain security error that occurred when we did a BitmapData.draw after entering fullscreen mode. Turns out that Flash cannot draw the "Press Escape To Leave Fullscreen", as it's on a different, local domain.And well besides the security settings i killed all the SWFAdress in Gaia, not that i am sure it is imposible to implement inside a fecebook app but definetly not a show stopper for this project in particular.

Imprimante     May 09, 2010
Thank you for this useful piece of code. And as a side note pretty loaded is quite pretty on his own :).

Fabio Paes Pedro     May 05, 2010
Nice thread. I was running through the same problem here. Thanks for sharing... very useful information.

Todd     Mar 25, 2010
Good read, I've been searching most of the afternoon on information about this.

I'm trying to load in external SWFs and access their library (linked classes). Works fine remotely, but if I test locally, no joy.

Is there anyway at all for two separate securityDomains (one local, one remote) to share the same applicationDomain?

Michel     Mar 23, 2010
I was looking for this piece of code for a while. Thanks for sharing!

Nick Hubben     Mar 17, 2010
if(Security.sandboxType == Security.REMOTE) == OMG, thank you so very much.

Timbot     Mar 17, 2010
Nice! I was using the url property of the loaderInfo to tell if my swf is running remotely or not like this; if(String(this.loaderInfo.url) == String(this.loaderInfo.loaderURL) )
But I'll try your suggestion - thanks for that.
-timbot

Juan Bermudez     Mar 16, 2010
@Jeffery Workingon some papervision demos some time ago I ran into a problem like that with images. In that case you can use a proxt php to give you the bitmap so you can manipulate it as if it was on your server.

Jeffery Bennett     Mar 16, 2010
Hi Daniel, and thanks for the helpful post!

One security point we ran into as well was a very weird cross-domain security error that occurred when we did a BitmapData.draw after entering fullscreen mode. Turns out that Flash cannot draw the "Press Escape To Leave Fullscreen", as it's on a different, local domain.

Thanks again!

Juan Bermudez     Mar 15, 2010
Last week I was working on a Facebook app and since I have used the Gaia Framework I thought why not leverage it inside facebook as a Canvas App.

Well this exact problem occured. The Type Coercion was my first error. After looking at the AppDomain and editing Gaia's source to allowDomain on assets that would be loaded it finally started working. And well besides the security settings i killed all the SWFAdress in Gaia, not that i am sure it is imposible to implement inside a fecebook app but definetly not a show stopper for this project in particular.

This explanations is awesome for anyone who runs into this type of error. And its dead on the solution.

Thanks


venkat     Mar 15, 2010
Loading a swf into the same applicationDomain using ApplicationDomain.currentDomain will ignore the class from the loaded swf and use the definition from the parent swf. You have to load it into a separate application domain or load into a child domain of the parent to use the definition from the loaded swf. Also, application domains are only relevant when you load the swf into the same security domain. Swfs loaded into separate security domains have their own application domains.


Speak






Submit »