Security Sandbox Violation by a Bitmap in a Flex AIR desktop application? - actionscript-3

*** Security Sandbox Violation ***
SecurityDomain 'file:///Users/Bluebird/Desktop/Demo/Project/Level_01
/Background.png' tried to access incompatible context 'app:/project.swf'
I understand that these "security" alerts are difficult to track down and even more difficult with scant information but I thought I would ask.
I have a large Flex/AIR desktop project where the user can select images off their local drive and collage them. There are also some swfs provided which they can use as "stamps". I am getting the error below when stamps are added to the app and clicked – the stamps have eventListeners attached – but the error does not reference the stamp (swf) but instead it references the background image.
The background image is a Spark Image defined in MXML:
<s:Image id="backgroundImage" x="{renderX}" y="{renderY}"
width="{renderWidth}" height="{renderHeight}"
smooth="true" smoothingQuality="high" scaleMode="stretch"
complete="backgroundImage_completeHandler(event)" />
The complete function does nothing important. The source property for the image is defined once the user has selected a local image:
backgroundImage.source = userFile.url
I don't see anywhere to provide a loaderContextfor the Image component (one solution usually suggested for "security" errors). Also, the backgroundImage component has no eventListeners – so I am completely baffled why it is throwing an error.
I've set the Flex compiler option to -use-network = false since this is just a desktop app and that is another commonly suggested "security" fix. I am also loading the "stamp" swfs through the trick of loading them as a byteArray first – another commonly suggested "security" fix.
Can someone help me hate Flash a little less?

For a quick check and probably fix, Instead the following line:-
backgroundImage.source = userFile.url
Trying giving it the relative path to the image file instead full absolute path.
like:
backgroundImage.source = "../images/bg.png";
Also, I assume you have already provided Security.allowDomain("*") in your stamp swfs.

First of all, per the Loader documentation, if you include the swf in the installed application content there won't be any security restrictions when loading it.
Otherwise, the Image component extends SWFLoader which does have a loaderContext property. Try passing in the current domain:
new LoaderContext(ApplicationDomain.currentDomain, SecurityDomain.currentDomain)

Related

DataVizExtention: issue with clearing viewables while a sprite is selected

In my code, I have this workflow:
When user wants to see some things, add Sprites using 'DataVizCore.addViewables()'
Use 'viewer.addEventListener(DataVizCore.MOUSE_CLICK, onDotClick)' to show info bubble
When user wants to show other things, call 'DataVizCore.removeAllViewables()' to clear Sprites
Repeat from step 1
This sequence works OK except in one situation.
If a sprite was selected (by clicking on it) before removeAllViewables() is called, I don't get MOUSE_CLICK event for newly added Sprites. In browser console, I see following error is thrown.
CustomViewables.js:318 Uncaught TypeError: Cannot read property 'style' of undefined at ViewableData.getViewableUV (developer.api.autodesk.com/modelderivative/v2/viewers/7.*/extensions/DataVisualization/DataVisualization.js:454)
As a workaround, I added 'event.hasStopped = true' to click event handler to prevent Sprite getting selected internally. That seems to work.
This seems like a bug in DataVizExtension to me. Or, my workflow is wrong?
Thanks
Bandu
Bandu. Thanks for the detailed steps to reproduce this issue. I tried with v7.46.0 version of the DataVisualization.js (latest as of my message) but was not seeing the same issue. I'd be curious if you are using this same version of the Forge Viewer (you can figure that out by looking at the viewer3D.js fetched under the Network tab of Chrome DevTools).
Setting event.hasStopped = true works because it internally avoided the code path calls into getViewableUV that threw the exception, but the flag is meant for other use cases (e.g. overriding default sprite selection behavior).
In any case, I've just tweaked our internal code to make use-cases like yours more robust. The changes will be released with the upcoming v7.47.0. Thank you for your feedback 🙂

How to implement Caching while loading SWCs dynamically

I'm loading dynamic loading of all my SWCs in my master SWF, in order to load master swf faster, however now I need to cache all my swcs in local machine to speed up things.
private function loadAssets():void
{
swcObj=new Object();
swcObj.swcPath='assets/swc/1.swc';
swcObj.className="Part_0_1";
swcs.push(swcObj);
swcObj=new Object();
swcObj.swcPath='assets/swc/2.swc';
swcObj.className="0_2";
swcs.push(swcObj);
swcObj=new Object();
swcObj.swcPath='assets/swc/3.swc';
swcObj.className="0_3";
swcs.push(swcObj);
}
Then I'm using this array to use all the classes in my project, but I have no idea how to cache these swcs for faster use, if anyone have idea, please share.
In fact, the browser does this pre-caching for you, you don't need to produce extra efforts. So, just load them normally and don't worry about caching. You can, however, motivate the user to increase their local browser cache in order to potentially lessen time spent on waiting while your assets are loaded, but this won't help should the user watch three tons of YouTube each day.
SWC files are not intended for dynamic loading.
They are static libraries that can be linked in a swf using
-include-libraries and library-path options of mxmlc or - since you seem to be using FlashDevelop - SWC Include Libraries and SWC Libraries in Project>Compiler options
. SWC's may hold code (classes), assets (symbols/bitmaps/sounds...) or combination of the two.
Loading assets dynamically is done through flash.display.Loader
you may use the Loader as a simple DisplayObject instance that you add on stage:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html#includeExamplesSummary
, or use its ApplicationDomain as a library of Class definitions that will allow you to create instances at will :
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/ApplicationDomain.html#includeExamplesSummary
Caching from the browser will be sufficient in most cases, unless you have VERY specific needs
In the end, there is different ways to optimize loading times, one of which is having a small swf acting as loader/home menu, and loading rest of the content on demand like you seem to try doing, but you can also create a single swf with several frames, which will be "streamed" by flash player, example:
1st frame as small as possible holding just a few kb for a splash screen/logo/loading/whatever you want, to make the initial blank screen as short as possible, then second frame holding the main content. You can event extent this system with for instance
two levels of preloader: a first tiny frame with just a logo, second one with progress bar, and full background if needed
split content like home screen/menus in a frame, gameplay in the another, if you are making a game, so that gameplay continues loading while you are already displaying the menu

MVVMCross Downloadcache - ProgressView during loading

I'm currently testing the downloadcache and this really looks great.
I have some questions regarding this plugin (I'm pretty new to C# and don't understand the full source code of the plugin):
1) ProgressView
I would like to show a progressview on the image until it has been loaded.
To do that, I need to be notified when the image is loaded.
In the "MvxImageViewLoader" I see there is an Action "afterImageChangeAction" (null by default).
However, I don't understand if and how I can access that Action from "MvxImageView"?
(how to set it)
2) Don't load old image
When using Tables or Cellectionviews in iOS, it's important to check if the URL has been changed before setting the image (because iOS reuses the objects). I looked at the source code of the downloadcache and I don't see this check.
However, in the "MvxDynamicImageHelper.cs" class, I see that when a new URL is set, it calls "ClearCurrentHttpImageRequest();" which removes the "update" Events.
So I assume this is enough to prevent that an image is set to the wrong UIImageView?
3) ImageCache size in (mega)bytes
The ImageCache does not have a property to define the mamiximum size (megabytes for example) of the persistent image store (on the HD). I prefer to use a maximum size in (mega)bytes instead of a maximum amount of files because the user will care more how much space an app takes instead of how many files are stored by the app.
I assume the easiest for me is to define a "TimeSpan PeriodSaveInterval" independent from the one in MvxFileDownloadCache to just check the size of the folder defined for the Image Cache or any other recommendations?
Is it dangerous for performance to scan the folder and calculate the size of all the images in a folder?
Regards,
Matt
1) ProgressView
I would like to show a progressview on the image until it has been loaded. To do that, I need to be notified when the image is loaded.
There is a DefaultImagePath which provides the path of an image that should be shown during loading.
But if you need a dynamic animation or other custom view, then afterImageChangeAction can be used
As you've seen, you can't do this in MvxImageView - the Action wasn't really a suitable candidate to be a bindable property so it wasn't exposed as a property.
However, you can:
do this by using MvxImageViewLoader directly in your View - there are several samples of using this in views in the N+1 samples - https://github.com/slodge/NPlus1DaysOfMvvmCross/search?q=MvxImageViewLoader
do this by creating your own MyImageView class - it's not a big class to write - https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxImageView.cs
As an alternative to using the Action callback, you can also inherit from MvxBaseImageViewLoader<T> and provide an override for the ImageHelperOnImageChanged method - see https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding/Views/MvxBaseImageViewLoader.cs#L49
2) Don't load old image
3) ImageCache size in (mega)bytes
The interface-driven and plugin structure of MvvmCross is defined to allow you to implement alternatives.
In the case of loading images from HTTP, there are many alternatives - you don't have to use the MvvmCross download cache for image loading.
The only docs available for the download cache plugin currently is https://github.com/slodge/MvvmCross/wiki/MvvmCross-plugins#downloadcache
For Android, some suggestions for alternative implementations are listed in: https://github.com/slodge/MvvmCross/issues/416
For iOS, it may be useful to read https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html including the section on <Application_Home>/Library/Caches
I know Stuart already provided an excellent answer. But what I did, when I needed the exact same feature, was to subclass MvxImageView and override the UIImageView.Image property. When the image is set I fire an event which is caught by the viewcontroller.

Externally loaded images in AS3 un-clickable?

I'm loading in an external image (a book cover from goodreads.com) into a library viewer AIR app (used on ipad and in-browser) running on Starling (in case you need to know). After it loads, the cover should be clickable to take further action.
This all works fine on ipad and when directly built from FlashDevelop, but when it's viewed in-browser, click events don't do anything on the loaded images. It'll work on my embedded placeholder bitmaps no problem (sitting in a "Book" class extending Sprite).
It seems to be a security problem, but if it was, I'd expect the image to not load at all. But instead it loads but isn't interactive anymore. I've tried various things like:
Add loader and click listener to the Book object
Add loader.content as Bitmap and click listener to the Book
Create a BitmapData and draw the Loader.content, then add the resulting Bitmap (it's blank in-browser, but works perfectly when built from FD)
Add loader and place a transparent sprite on top of it, add listener to the sprite
Has anyone had this problem? Would anyone know a work-around?
Thanks!
This was a sand-box problem.
I think it's intentional; you shouldn't be able to hot-link other site's assets unless given express permission.
I fixed this by only pulling images hosted locally and using crossdomain.xml to make sure there was no lookup issues when www.domain.com and domain.com were different.

How many levels deep can you nest swf's - will 3 work - like child inside parent inside grandparent?

The code at the bottom of this post nests an AS2 "player" inside a Flex app (AS3). Look at the part that says "[AS2 player swf]". That AS2 player swf has almost no code - just one function that loads an asset from a remote server. Very simple:
this.onLoad = function(){
content.loadMovie("http://URL_TO_REMOTE_SWF");
};
And it has no other assets. Just one MovieClip - "content".
So we've got a Flex app that loads an AS2 swf that loads a remote swf. No dice. Remote swf doesn't load and display. No errors reported.
Important: The AS2 app on its own works. If I go navigate to it in my file system and double click, remote swf does indeed load and display. So I've established that the unwrapped AS2 swf player works and does indeed load remote swf's. Something about nesting that player inside the Flex app creates a problem. Are you not allowed to do this - 3 levels of swf nesting (child - parent - grandparent)?
UPDATE: Target remote swf's load and display fine directly in Flex as well (skipping AS2 swf). So problem doesn't appear to be with AVM1/AVM2 discrepancy between target content and Flex app. Could be AVM1/AVM2 problem with how the Flex app displays the AS2 swf but only when it contains content.loadMovie("http://URL_TO_REMOTE_SWF"). Loads and displays without that line.
UPDATE: This is a Flex packaged IOS application and thus is subject to ActionScript restrictions for dynamically loaded code. But it doesn't work in a regular Flex (non packaged IOS) app either which is not subject to these limitations. THE FOLLOWING CODE SHOULD WORK AS FAR AS I CAN TELL IN A REGULAR FLEX BROWSER BASED APPLICATION.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize="init()">
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
private var request:URLRequest = new URLRequest("[AS2 player swf]");
private var loader:Loader = new Loader();
private var myComponent:UIComponent = new UIComponent;
private function init():void{
myComponent.percentHeight = 100;
myComponent.percentWidth = 100;
loader.load(request);
myComponent.addChild(loader);
player.addElement(myComponent);
}
]]>
</fx:Script>
<s:Group id="player"
height="100%" width="100%"/>
</s:Application>
Since all Sprites and MovieClips are both display objects and display object containers, you could theoretically keep nesting them forever. There are physical restraints, of course, but I see no reason why there should be a limit other than memory and processing power (at some point, refreshing the screen will become sluggish, and eventually painful to wait for).
I've searched the web to see if I could find any information about a built-in limit enforced by the AVM, any documents or error codes that would suggest there is one, but I couldn't find anything at all. Of course, that doesn't mean there isn't - it just means the limit hasn't been reached by many people yet ;)
So if anyone else knows more...
EDIT
Since the information about your loaded MovieClip is new, here's my update: AVM1 (AS1 & 2) SWFs don't always execute in the same way when loaded into an AVM2 (AS3) movie. This has nothing to do with the number of nested display objects. I originally thought this was because the _lockroot property was removed in AS3, but I've searched a bit and found out it is assumed true by default, and should therefore not be a problem.
There may be many things about your scenario that are different from when the file runs on its own, and I would start by looking at these:
Do you use relative path names to load other data into the AS2 swf?
Do you get any error messages (particularly, security sandbox violation errors)?
Does your AS2 SWF rely on external variables to be set (FlashVars)
Does your AS2 SWF need ExternalInterface access?
FINAL EDIT
Since this new info has just come up:
There is absolutely no way to execute dynamically loaded AVM byte code on an iPad at runtime, for the same reason that there is no Java VM and no Flash Player for iOS: Apple does not allow the execution of dynamically loaded byte code at all. Period.
Hence, you can load and play SWF animations, but not ActionScript. It will simply be ignored. Also, neither of the apps that you did run is in fact AVM byte code - they are compiled into LLVM byte code instead.
You will have to find a way to check for the end of the animation that does not involve stop() commands. Perhaps this can be done by checking frame numbers from your AS3 container?
To answer you question directly, yes, you can load AS2 swfs that way. And you code looks correct to me.
I suspect it is loading the AS2 swf fine, but that the AS2 swf is not initializing correctly for some reason. Perhaps it is a video player that has no visible assets besides the loaded video. AS2 tends to fail without throwing errors, which makes it hard to debug. I would suggest publishing an AS2 swf with some graphics in it but with no code that could fail. No code at all. Maybe just a timeline animation of a moving circle or something, then load that. In that way you can eliminate your Flex code as the source of the problem.
If it turns out that your test movie works, then you will need to determine what resource the loaded swf is expecting that it is not receiving.