First, the background:
I am creating a Flex application with a component that displays various dynamically loaded SWFs, one at a time (kind of like a kiosk). These loaded SWFs are created in Flash IDE, not Flex. They will not be created by us (we will provide a .fla template but that's it), so I am loading them into a separate SecurityDomain.
My Questions:
I want the application to be able to call methods inside the loaded SWF. To do this, would I just call Security.allowDomain("domain original app was loaded from") in the startup process for the loaded SWF?
I want the loaded SWF to be able to throw events that are caught by the application. Can I accomplish this through the SWFLoader.swfBridge property?
I am defining an interface for the methods inside the loaded SWF. But, I don't want to leave the implementation up to the customer. Instead, I want to provide another SWF that contains the interface implementation and have it be a constraint that the customer includes it in their SWF. I am not very familiar with the Flash authoring environment, how would it work so that the interface implementation SWF exposes its methods in such a way to be accessible to Flex? Is there a way to sign the SWF so that the Flex application knows that it is dealing with the original, not a spoof? How would the Flex code pass in arguments, since it is across SecurityDomain boundary -- is there marshalling involved (say if I want to pass in a Dictionary or some kind of object graph)?
The Flex application may load hundreds of these smaller other SWFs during its lifetime. How do I make sure it doesn't keep using up more memory? I plan on using SWFLoader.unloadAndStop() and clearing all references in the Flex object that refers to it. Is this enough? Will the AppDomain for the loaded SWF be torn down automatically so that the class definitions are no longer in memory?
Thanks,
Karthik
Some answers:
2) No. Well, you could try, but it would be a mess. You can look into some of the bootstrap loading documentation, but if you're not in complete control of the flash development, this is a lost cause and will end in headache for you.
Depending on your architecture, I would abstract everything out in such a way where communication is happening through javascript or through a localConnection. It might be a pain to use a localConnection to start (giving the serialization size constraints, etc.) but once you get everything hashed out, you won't need to fight with all the security sandbox restrictions. I understand that you want everything to be secure, but if you have control of the server and know where the swfs are being loaded from (and can add numerous layers of security that you invent [for example: having a loaded swf talk to a server when loaded]), you may be better off.
Random thoughts....
Good luck in any case.
Alex Harui from Adobe gave some extremely helpful answers on my post on the Adobe forums. Check them out if you are interested in this same question.
Karthik
Related
I've recently been slated with a task to port an existing Flash Player-base game to a desktop app for publication on the Steam platform. The Adobe AIR framework seems like a logical choice for distribution, especially given the latest updates in AIR 3. Given the fact that I'm relatively new to flash/flex development, I've read through a fair amount of AIR documentation on the Adobe site in order to gain a better understanding of what the task involves. In general, I think I have a decent idea of what needs to happen, but there are a couple of wrinkles that may affect if/how it is even possible to port to the AIR framework:
The AIR application will need to load the actual game client from an external server due to the quick turnaround time of the client development.
Since the AIR application will be deployed on Steam, I want to use the Captive Runtime bundling that's available in AIR 3.0, i.e. no need for the user to 'OK' a separate AIR installation.
Have minimal impact on code changes within the external SWF as I'm not the primary developer of the game.
My first priority is to figure out the best approach for loading an external game client SWF into an AIR application. Initially, I tried to utilize Loader.load(), but that resulted in the following exception:
SecurityError: Error #2070: Security sandbox violation: caller http://localhost/MyClient.swf cannot access Stage owned by app:/AS3_AIRTest.swf.
at flash.media::SoundMixer$/set soundTransform()
at com.company.client.sound::SFXManager$/load()
at global/client.util::loadEmbeddedSounds()
at MyClient()
The offending code is:
static public function load():void {
SoundMixer.soundTransform =
new SoundTransform(Client.Settings.PlaySFX ? 1 : 0);
}
Upon hitting this exception, I decided to read up a bit more on the AIR / Flash player security domains. I have a much clearer understanding of why the exception occurred, but I'm still uncertain what the best approach would be to load the SWF and not receive the exception above.
After scouring through numerous posts on various forums, I found that a number of developers use Loader.loadBytes() to bring the SWF into the application sandbox. From an ease of implementation standpoint, I can see why many choose to go that route; however, I'm not inclined to pursue that approach due the potential dangers to user systems in the event that the external server is compromised.
The second approach that I've read about is that I can utilize a sandbox script bridge, and write an interface to grant certain privileges to the external client SWF. I'm hesitant to go this route at the moment because the game client is fairly complex, and I'm not entirely certain how much access it will require of the stage via different flash APIs. I haven't written this approach off as it sounds like it may be the best bet, but it could potentially be a large endeavor and I want to have minimal impact on the client SWF.
The final approach I've read about is by making an HTML AIR application. My understanding (sketchy at best) is that a SWF loaded via HTML (I believe in a frame/iframe) will have its own stage. My line of thinking is that if the HTML app loads a main page, which in turn has an iframe with SWF embed of the game client, then the client SWF will load in a remote security sandbox and have access to its own stage. My hope is that the SWF would behave as it does in the Flash Player.
This leads me to the following questions:
Is my line of thinking correct about the HTML app?
Would the client SWF have access to its own stage and pretty much behave like it does in the Flash Player?
Can HTML-based AIR applications be bundled with the captive runtime?
Can I use a traditional flex application with HTMLLoader to accomplish the same goal or does it need to be a full-blown HTML app?
If HTMLLoader can be used, would I need to provide the sandbox script bridge meta tags in the iframe tag?
Any help would be very much appreciated at this point. It seems like there are a number of options available, but I'm not sure which path is the right one to pursue at this point in time.
Thank again.
Josh
You have already investigated a lot. I was going to mention Loader.loadBytes technique but you mentioned that it is not secure. Actually, you could take care of security if you knew the signed hashes of the SWFs that may be downloaded. I remember to have read this approach in a AIR team's manager's blog but I can't recollect the link at this time. Basically, the approach would work if you knew all of the SWFs before hand that could be downloaded, and then generated their signed-hashs and put those hashes in an XML which shipped with the initial AIR app. Then, the initial AIR app can download those SWFs, compare their signatures and load them in application sandbox if it matches up with shipped hashes etc.
(Long question with lots of points, but here goes)
You are correct that passing the Stage object through a script bridge isn't going to work. So, removing the code that accesses the stage and possibly using the script bridge to get the job done in each specific case would be necessary.
If you embed the SWF in an HTML page, it will indeed get its own stage. It does not matter whether this is an "HTML-based" AIR application or an ActionScript-based application that uses the HTMLLoader. (Really the two are the same thing.) You don't need an iframe for this. This sounds like the easiest approach, especially if you aren't adding many AIR-specific features.
For information on signing, see http://www.adobe.com/devnet/air/flex/quickstart/articles/xml_signatures.html
The other thing I'd look at, if you haven't already, is what facilities Steam offers for doing such updates. Is the turn around time for uploading a new project/update to Steam really greater than the time it would take to add this post-install update system to the app itself? (I hope you aren't in one of those Dilbertian situations where, on paper, it looks like you can save time by doing weird things. In my experience, miracles created by dragging sliders around in Microsoft Project (or the like) don't pan out.)
what is difference between swfLoader(load application) and ModuleLoader(load module)?
which is better to use?
thanks
The SWFLoader is used to load sub-applications while the ModuleLoader is used to load Modules, as you stated yourself.
The difference is that Modules have a tight link to the application their are loaded in and cannot be used standalone. A subapplication on the other hand really is a separate application that has no direct link to the application it is loaded in. Depending on your use cases, you might consider one or the other.
There is a good stuff available from Adobe here
Be sure to check the section "Comparing loaded applications to modules".
I have a large flex application (the app) running on one server, and many small flex applications (widgets) running on another server, which are to be included in the app so that visually the user see's one continuous application. Due to proprietary third party software, this structure cannot be changed. I am looking for some way to allow the app and the widgets to communicate, allowing the app to make changes to the widgets and the the widgets to notify the app when events are triggered, so that user interaction is fluid and continuous.
There are a few related questions which indicate it's possible to do this by setting up event triggers and listeners. I am wondering if there is any standardized way to do this (the answers aren't very clear) or if anyone has developed a library or API to make this easier.
Something I've had success with is using javascript as a bridge between the swf files. It's a nightmare to debug but it works quite well. Check out the tutorial here for a quick discussion of how to interact with javascript from within flash and vice versa
I assume you are running your Flex apps on a client, not a server; is that correct? You want to swfs from multiple servers to act as single application, correct?
I believe that you can communicate between two swfs using LocalConnection:
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/net/LocalConnection.html
The other questions you link to seem to talk about loading onw swf inside the oher; which is a separate approach.
Use Modules and ModuleLoaders. You'll be able to set the security context, and if you sublcass the Module class and add your own API, you can have a consistent way to communicate with your modules.
Check here for a simple Module:
http://blog.flexexamples.com/2007/08/06/building-a-simple-flex-module/
I'm about to start a project where there will be a Flash application where the visitor customizes a profile with externally loaded images and texts. Then the visitor needs to be able to download that profile as a dynamically created swf with all that external content baked into the swf.
Any ideas how to achive this?
Thank you!
Which aspect are you curious about? The overall workflow of setting up the server-side architecture? Information on tools that can generate SWFs? Or information on the SWF format itself?
As for tools, here are a few options off the top of my head:
The Flex SDK (i.e. mxmlc) will compile a pure AS3 project with embedded assets. If you've got reasonable control over the server, and don't mind a relatively heavyweight approach, that's probably the most "supported" way to go.
SWFMill (http://www.swfmill.org) has its own XML format for generating SWFs and importing assets. It's not quite up-to-date on newer SWF formats, but that may not matter depending on the requirements.
www.swftools.org has a few things that may be useful.
haxe.org has several options for generating SWFs.
If your question is about generating the format from scratch, all those projects are open-source, and personally, I've found the haxe sources to be the easiest reading. The library you want is http://code.google.com/p/hxformat/. Taking a look at the swf format spec might be helpful as well: www.adobe.com/devnet/swf/.
Or were you looking for more step-by-step detail?
(note: sorry for the lack of active hyperlinks, apparently the system doesn't believe I'm human yet :)
I believe you would have to create the SWF on the server side and then either
1) provide the user with a URL
or
2) dynamically load it in to your application and use it as the target for a button click, or something like that.
There are a number of ways to create SWFs on the server, but that's an area outside of my experience. Maybe someone else can post some better information on it, but here's a link to one approach, to get you started.
http://www.sephiroth.it/weblog/archives/2006/02/swf_server_side_compiler_with.php
My Flash (AS3/AIR) application is currently using a slightly unusual architecture (for a Flash app) to provide particular base classes for loaded content at runtime. The external content is published with 'stub' base classes, which are eclipsed by the 'real' base classes at runtime when it is loaded. I've heard this referred to by Adobe as bootstrapping (pdf), and it has been working very well for me until now. It's not unlike a DLL architecture I believe, although I'm not qualified to say for sure.
Until now, the external content I have been loading has been loaded from within the same SecurityDomain (same sandbox), which allows me to easily load the content in a child ApplicationDomain. Unfortunately, as far as I can tell, an ApplicationDomains that span SecurityDomains cannot be related - that is, I cannot make an AppDom of one SecurityDom the child of an AppDom from another SecurityDom.
But now I need to load this external content from outside my Application sandbox. There are plenty of ways to achieve communication across SecurityDomains - although most of them are very limited, AIR's sandboxBridge API is probably the most powerful. Unfortunately, none of these communication methods allow me to achieve this bootstrapping architecture.
I notice that the LoaderContext object has a securityDomain property, but Flash security prohibits 'local swfs' from touching it (it throws a SecurityError or similar).
Flex's SWFLoader has a trustContent property that looks promising, but I'm inclined to assume that it has the same restrictions as setting the SecurityDomain in the Loader's LoaderContext.
I suspect I'll have to redesign (which won't be easy), but I thought I'd just check here that I've not missed something in my research.
So ... any ideas or pearls of wisdom? I'd especially freaking love it if someone from Adobe who works on the Security model could gimme a definitive "yes/no it can/can't be done"...
Thanks in advance!
Addendum: I've since decided to re-design the architecture so that the bootstrapping all happens on the external domain. My question still stands, however, out of curiosity.
Technically speaking, wouldn't it be possible for your AIR application to simply save the external SWFs inside your application directory, and load them from there so that they live in the same security sandbox?
However, there are some really obvious reasons why this would be Bad Karma, so it seems like any solution necessarily raises the question of whether trying to put local application content and remote untrusted content into the same app domain is the right architecture approach..?
At the time of writing, I determined that you cannot load an ApplicationDomain into your own SecurityDomain if it is from another domain, even with AIR.
By design, I guess.