Bug? LoaderInfo getLoaderInfoByDefinition security sandbox violation in AIR - actionscript-3

This question is specific to Adobe AIR ActionScript/Flash applications. I've spend quite some time researching this and kept finding discussions about either the Flash Player security model when running in the browser, where issues with SWF loading can be mitigated in various ways (loading from the same domain, using a crossdomain.xml file, etc.) or for AIR HTML applications, where the JavaScript security model is discussed with it's per-frame sandboxes and the sandbox bridge approach. My problem is different, I believe.
First some code. To demonstrate, I created a very simple Flex application (LoaderInfoTest.mxml):
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="onCreationComplete(event)">
<mx:Script>
<![CDATA[
import flash.display.LoaderInfo;
import flash.system.ApplicationDomain;
import flash.utils.getQualifiedClassName;
import mx.events.FlexEvent;
public function onCreationComplete(event:FlexEvent):void
{
// the following line of code throws an exception
var info:LoaderInfo = LoaderInfo.getLoaderInfoByDefinition(this);
}
]]>
</mx:Script>
</mx:WindowedApplication>
... and an application.xml descriptor file (LoaderInfoTest-app.xml):
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<application xmlns="http://ns.adobe.com/air/application/1.5.2">
<id>LoaderInfoTest</id>
<filename>LoaderInfoTest</filename>
<name>LoaderInfoTest</name>
<version>v1</version>
<initialWindow>
<content>LoaderInfoTest.swf</content>
</initialWindow>
</application>
I build this using Flash Builder 4 Beta, but I presume the issue remains the same when using the SDK command line tools. When executing this either from within Flash Builder or from the command line via:
> adl LoaderInfoTest-app.xml .
I get a popup with this exception:
Security sandbox violation: caller app:/LoaderInfoTest.swf cannot access LoaderInfo.applicationDomain owned by app:/LoaderInfoTest.swf. at flash.display::LoaderInfo$/getLoaderInfoByDefinition() ...
I don't understand why the SWF cannot access the LoaderInfo.applicationDomain property (presumably a protected or internal property) owned by itself. The documentation for LoaderInfo.getLoaderInfoByDefinition states that it's possible for a SecurityError to be thrown, if "[t]he caller is not running in the local trusted sandbox". Unless I really have a gross misunderstanding of the AIR security model, a local SWF runs with full trust (application sandbox). So, why is this not working? Is it a bug in the AIR runtime?.
I should note that in a different scenario, when running this code as a pure Flash (not AIR) application in the Flash player, it does work.
The best answer would be some sort of configuration or setting I can change to make this work (maybe in the application descriptor?) ... or pointing out where I am making a mistake. The second-best answer would be a definite source of explanation of why this will never work.
1st Edit - Before anyone points it out: I know that inside the onCreationComplete method, this.loaderInfo gives me access to the current LoaderInfo instance. My example here is the simplest I could come up with to demonstrate the "problem." The context in which I want to use LoaderInfo.getLoaderInfoByDefinition(this) is not a DisplayObject instance.
2nd Edit - I am considering even accepting a link to where I can post a bug to Adobe AIR's issue tracker as an answer. The public Flex issue tracker doesn't count, because this is not a Flex problem.
3rd Edit - It is apparent that there are differences between the "local trusted sandbox" and the "AIR application sandbox," but (some of) these differences seem non-sensical and I now consider them a bug, at least in the context of this question and especially because it works in Flash Player.

The documentation is correct that getLoaderInfoByDefinition is available only to content in the localTrusted sandbox. Although AIR application content has many privileges, it is not in localTrusted and therefore cannot use the API.
It's certainly a reasonable request, however, to add access for application content.
As a workaround, you can use this API (and Sampler APIs) in AIR by loading another SWF in localTrusted sandbox. To do this, you need to add the file to one of the trusted lists, and load the file with a file:// URL (not app:/). There are then a number of ways for the localTrusted and application content to communicated.

You can file bugs against AIR (as well as make feature requests) at www.adobe.com/go/wish
I suspect the security error may be a red herring. It doesn't look like there should be one here.

This issue is also showing up in a regular flash application. Basically, I have a helper class called UrlInfo.
It's constructor looks like this
import flash.display.LoaderInfo;
public class UrlInfo
{
private var _loaderInfo:LoaderInfo;
public function UrlInfo():void
{
_loaderInfo = LoaderInfo.getLoaderInfoByDefinition(this);
}
}
In a fla file, I have this:
import my.namespace.UrlInfo;
var ui:UrlInfo = new UrlInfo();
I get the same error:
SecurityError: Error #2119: Security sandbox violation: caller file **SAMEFILE.swf** cannot access LoaderInfo.applicationDomain owned by **SAMEFILE.swf**.
at flash.display::LoaderInfo$/getLoaderInfoByDefinition()
at com.honda.ttd.content.as3.util::UrlInfo()
at urlinfo_fla::MainTimeline/frame1()
Launching the .html that calls the swf does not trigger this.
Launching the .swf does trigger this.
I know that I can fix it by going to the flash settings and adding the location of the swf into the Flash Security Settings Tab.
For instance, if the SAMEFILE.swf is on my Desktop, I can add C:/ to the list of trusted locations.
I AGREE THAT THIS IS ODD because the file is accessing itself, yet it is violating some security. I would like to know if there is any fix for this or if this is actually expected behavior.

Related

ServiceLocationProvider is null when launched as a Share Target

I'm using MVVM Light and everything is fine except when launching my Windows Phone 8.1 WinRT app as a Share Target.
When I try to assign MainViewModel viewModel = ServiceLocator.Current.GetInstance<MainViewModel>(); I get an exception for ServiceLocator.Current.
Exception Message: ServiceLocationProvider must be set.
Do I need to do something extra in App.xaml.cs OnShareTargetActivated event to insure the Locator is running?
UPDATE:
A ShareTarget page needs to be thought of as a small extension of your app. It seems that not all of the app's resources are loaded (including app-wide resources in App.xaml). So I just created a new instance of MainViewModel in the share page's constructor, loaded only the things I need for the share to complete, save the information and call ShareOperation.ReportCompleted. This returns the user back to the app that is sharing.
I still haven't found a good solution for getting other resources in my ViewModel, but this works for now.
This indicates that the following line has not been executed:
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
This line will instruct the ServiceLocator class to use the SimpleIoc.Default instance as its ServiceLocator.Current. When you run your app as a Share target, the initialization is slightly different and probably the ViewModelLocator doesn't get initialized. You need to find a good location to perform the initialization before you use the ServiceLocator.
Cheers
Laurent

Portable Class Library - Windows Store App: "Could not load file or assembly Microsoft.Threading.Task"

I have an MVVM Light infrastructure which is all contained within a Portable Class Library targeting .Net 4, SL5, Win 8, WP 8.1, WPSL 8, Xamarin.Android and Xamarin.iOS. This works perfectly with a WPF client, however, when I try and use it in a Windows Store App/Win 8 environment I am coming up against some resistance. The first issue is found in App.xaml:
<Application
x:Class="Win8Client.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:INPS.Vision.Appointments.Shared.ViewModels"
xmlns:local="using:Win8Client">
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" />
</Application.Resources>
</Application>
At design time I get "Could not load file or assembly 'Microsoft.Threading.Tasks', version=1.0.12.0 ..." which is referring to my ViewModelLocator. This compiles and appears to run ok but I don't get any design time data. The design time data works fine in the WPF client.
Once running I see my first view but once this line gets called:
Slots = await _appointmentsDataProvider.GetAppointments(SelectedDate);
I get the following exception in the setter of my slots property which takes advantage of MVVM Lights Set method of ViewModelBase. The Slots property is NOT bound to any UI yet.
Exception:
"The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))"
Slots Property:
public List<Slot> Slots
{
get { return _slots; }
set
{
Set(SlotsPropertyName, ref _slots, value); // <-- Exception thrown here
}
}
Realised I haven't actually asked a question. Simply, I would like to know, what is the best approach for using MVVM Light with a Windows Store App?
Thanks in advance for any help or advice!
The first issue "Could not load file or assembly 'Microsoft.Threading.Tasks', version=1.0.12.0 ..." I haven't worked out yet but from time to time I do see the design data. Seems very temperamental...
The second issue - The reason this through me a bit was because is "just worked" in WPF and I assumed it would just work in a Windows Store App. Wrong. It looks like Windows Store Apps handle async/await threading differently - that's my guess.
Fix: Created an IDispatcherHelper interface in PCL with a single method declaration:
void RunOnUIThread(Action action);
Then created a single concrete DispatcherHelper class in each platform specific project (WPF/Windows 8.1) which implement IDispatcherHelper. Each implementation simply calls MVVM Lights:
DispatcherHelper.CheckBeginInvokeOnUI(action);
In App.xaml.cs in the WPF and Windows 8.1 I simply registered the concrete implementations with MVVM Lights SimpleIoc with the IDispatcherHelper as the handle. Within the view model I then use the platform specific implementations through the interface:
var slots = await _appointmentsDataProvider.GetAppointments(SelectedDate);
IDispatcherHelper dispatcherHelper = SimpleIoc.Default.GetInstance<IDispatcherHelper>();
dispatcherHelper.RunOnUIThread(() =>
{
Slots = slots;
});
Got to love abstraction!

Flash ActionScript - Trace from background Worker

Is it possible at all, or traces are part of the API which is not avalible from background Worker?
Consider this code:
public class Main extends Sprite {
public function Main(container : DisplayObjectContainer = null)
{
if(Worker.current.isPrimordial) {
trace("isPrimordial");
var m_worker : Worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes);
m_worker.start();
}
else {
trace("is NOT Primordial");
}
}
The string "is NOT Primordial" does not appear, however I do see that m_worker.state is "WorkerState.RUNNING".
Some UPDATE: The main thread works and racts to events, however it appears like the backgroung worker does not start until I desconnect the debugger.
And if it is possible, how do I setup the fdb to show these logs?
PS. Im using flash standalone debug player 13 with latest FDT and Apache Flex 4.12.1 SDK.
Ok, so the results for now are:
The background thread (Worker) can write traces with no problems at all if the debugger is not attached, for example if we are using flashlog.txt for the output (output to file).
What is required is: flash debug player (me used v. 14 stand alone and firefox versions).
The setup for using text file as output discussed here:
http://helpx.adobe.com/flash-player/kb/configure-debugger-version-flash-player.html
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7fc9.html
Correct location of mm.cfg on modern operating systems (and not on Win95!) discussed here:
https://forums.adobe.com/thread/1218258
For me the output to file started to work only after the flashlog.txt file was created by some 3rd party tool (I used Vizzy), but probably it is a permission problem of flasho n windows 8 and the file just can be created manually.
Detailed discussion of the flash traces topic (althoug a little old, but mostly still relevant) is here:
See trace() of Flash when running in browser
Thanks everyone for help.
Create a static Log class that output it's log to trace. Use this log class in your main thread and in your worker. Only the main thread log definition will be used allowing to trace from anywhere.

Html applet tag, accessing through chrome developer tools

i happen to receive a Html with an applet tag, is there a way to access the class received through chrome developer tools, i cant see it in the scripts. If there isnt how can i access it?
<applet name="tradesapp" id="tradesapp" code="loader3.SunLoaderApplet.class" archive="loader_20110113.jar" codebase="http://ih.advfn.com/" width="1100" height="2000" mayscript="" alt="This browser either has java disabled or does not support it" title="Java"><param name="manifestcrc" value="1211857157"><param name="storagepath" value="ih.advfn.com"><param name="masterloader" value="master"><param name="initial_focus" value="false"><param name="cache_archive" value="loader_20110113.jar"><param name="cache_version" value="1.0.7.7"><param name="java_arguments" value="-Dsun.java2d.d3d=false"><param name="advfn_url" value="http://ih.advfn.com/"><param name="streamer" value="stream-9.advfn.com"><param name="user" value="ih_340884"><param name="root" value="advfnclient.framework.BaseControl"><param name="page" value="advfnclient.TradesContainer"><param name="tz" value="US/Eastern"><param name="clearAllDateStamp" value="1272534624504"><param name="clearCacheDateStamp" value="1272534624504"><param name="language" value="us"><param name="view" value="ih"><param name="config_name" value="trades"><param name="config_default" value="Default"><param name="params" value="w=1100&h=2000&symbol=N%5EMSFT&montage=true&sources=afx:ukreg:rssnon&dims=664 79 15 0&col_widths=45 55 344 90 115&sid=1f58fa6b4ea88725c5b8e23d614a6e80&page_key=1338581393&w=1100&h=2000&pid=applet_embed&mypid=trades"><center><iframe width="600" height="300" src="/p.php?pid=javadisabled"></iframe></center></applet>
Chrome doesn't include a Java debugger and an applet isn't a script.
You can access it via document.getElementById('tradesapp'); in the JS console. If you want to do anything with it, then the applet will have to explicitly expose methods to JavaScript.
I suspect this is not your Java project, so I can't imagine Quentin's advice will help you. It sounds to me like you want to run the Java Applet yourself, perhaps making changes and having access to a debugger. I decided to see what I could do as I've never had experience with this kind of stuff before.
First of all, you can download the .jar file in the archive property. In your case it looks to be located at http://ih.advfn.com/loader_20110113.jar
You can then use Java Decomipler to decompile the .jar file. If you do so, you'll see that this jar file acts as a loader, and pulls more java classes from advfn.com. It saves them in the location given by:
String path = System.getProperty("user.home");
On windows this is C:\<USER>\advfn
You can decompile these classes as well if you're interested. You'll be left with an approximation of the original source code. In this case, a fairly good one.
If want you go one step further and decide to build the project yourself, you can import the classes into Eclipse. You'll notice there are some strange errors such as the following:
LoadFile(String paramLong, long arg3)
{
this.name = paramLong;
Object localObject;
this.size = localObject;
}
I've never built a decompiler myself and am not at all familiar with Java bytecode, but if I had to guess, I'd imagine that the decompiler was trying to represent a local instance of the argument that was passed in to it.
The fix is fairly obvious once you know this.size is of type Long.
LoadFile(String paramLong, long arg3)
{
this.name = paramLong;
this.size = arg3;
}
If you continue to make these changes, your code will compile successfully. But it still won't run as you're missing parameters set in the HTML. A sample line in LoaderApplet.java is as follows:
this.manifestCRC = Long.parseLong(getParameter("manifestcrc"));
If you return to the HTML page you found this at, you'll find a variety of parameters are specified there. You should be able to go through your project and replace requests for parameters with their appropriate values.
This was my first experience decompiling Java, so I might have missed a few details. Let me know if you need more help.

MEF: "Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information"

Scenario: I am using Managed Extensibility Framework to load plugins (exports) at runtime based on an interface contract defined in a separate dll. In my Visual Studio solution, I have 3 different projects: The host application, a class library (defining the interface - "IPlugin") and another class library implementing the interface (the export - "MyPlugin.dll").
The host looks for exports in its own root directory, so during testing, I build the whole solution and copy Plugin.dll from the Plugin class library bin/release folder to the host's debug directory so that the host's DirectoryCatalog will find it and be able to add it to the CompositionContainer. Plugin.dll is not automatically copied after each rebuild, so I do that manually each time I've made changes to the contract/implementation.
However, a couple of times I've run the host application without having copied (an updated) Plugin.dll first, and it has thrown an exception during composition:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information
This is of course due to the fact that the Plugin.dll it's trying to import from implements a different version of IPlugin, where the property/method signatures don't match. Although it's easy to avoid this in a controlled and monitored environment, by simply avoiding (duh) obsolete IPlugin implementations in the plugin folder, I cannot rely on such assumptions in the production environment, where legacy plugins could be encountered.
The problem is that this exception effectively botches the whole Compose action and no exports are imported. I would have preferred that the mismatching IPlugin implementations are simply ignored, so that other exports in the catalog(s), implementing the correct version of IPlugin, are still imported.
Is there a way to accomplish this? I'm thinking either of several potential options:
There is a flag to set on the CompositionContainer ("ignore failing imports") prior to or when calling Compose
There is a similar flag to specify on the <ImportMany()> attribute
There is a way to "hook" on to the iteration process underlying Compose(), and be able to deal with each (failed) import individually
Using strong name signing to somehow only look for imports implementing the current version of IPlugin
Ideas?
I have also run into a similar problem.
If you are sure that you want to ignore such "bad" assemblies, then the solution is to call AssemblyCatalog.Parts.ToArray() right after creating each assembly catalog. This will trigger the ReflectionTypeLoadException which you mention. You then have a chance to catch the exception and ignore the bad assembly.
When you have created AssemblyCatalog objects for all the "good" assemblies, you can aggregate them in an AggregateCatalog and pass that to the CompositionContainer constructor.
This issue can be caused by several factors (any exceptions on the loaded assemblies), like the exception says, look at the ExceptionLoader to (hopefully) get some idea
Another problem/solution that I found, is when using DirectoryCatalog, if you don't specify the second parameter "searchPattern", MEF will load ALL the dlls in that folder (including third party), and start looking for export types, that can also cause this issue, a solution is to have a convention name on all the assemblies that export types, and specify that in the DirectoryCatalog constructor, I use *_Plugin.dll, that way MEF will only load assemblies that contain exported types
In my case MEF was loading a NHibernate dll and throwing some assembly version error on the LoaderException (this error can happen with any of the dlls in the directory), this approach solved the problem
Here is an example of above mentioned methods:
var di = new DirectoryInfo(Server.MapPath("../../bin/"));
if (!di.Exists) throw new Exception("Folder not exists: " + di.FullName);
var dlls = di.GetFileSystemInfos("*.dll");
AggregateCatalog agc = new AggregateCatalog();
foreach (var fi in dlls)
{
try
{
var ac = new AssemblyCatalog(Assembly.LoadFile(fi.FullName));
var parts = ac.Parts.ToArray(); // throws ReflectionTypeLoadException
agc.Catalogs.Add(ac);
}
catch (ReflectionTypeLoadException ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
}
CompositionContainer cc = new CompositionContainer(agc);
_providers = cc.GetExports<IDataExchangeProvider>();