Loader-Class - SecurityError: Error #2000: No active security context - actionscript-3

I try to "catch" this error when I'm loading some images.
The following code is an test-case for my problem to secure that there are no errors in the surrounding code.
import flash.events.SecurityErrorEvent;
import flash.display.Loader;
import flash.net.URLRequest;
loadImage ();
function loadImage (): void {
var _imageLoader = new Loader();
_imageLoader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, imageSecurityErrorEventListener);
var request:URLRequest = new URLRequest("this-image-not-exits.jpg");
_imageLoader.load(request);
}
function imageSecurityErrorEventListener (e:SecurityErrorEvent) {
trace ("This is my own trace for the Security Error");
}
I know that there are lot's of posts and questions in the www and here, but I couldn't find an answer to my problem.
I'm working on an interactiv-movie with many images and movies which are loaded dynamically in the application.
In this snipped I generated the worst case in my application (try to load an image that not exits).
When I run this code I get the trace "SecurityError: Error #2000: No active security context" and not the trace of my the Listener.
Do you have any idea whats going wrong?

That specific security error is thrown rather than dispatched as an ErrorEvent.
It can be detected by using a try...catch block instead:
function loadImage (): void
{
var _imageLoader = new Loader();
_imageLoader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, imageSecurityErrorEventListener);
var request:URLRequest = new URLRequest("this-image-not-exits.jpg");
try
{
_imageLoader.load(request);
}
catch (error:Error)
{
trace("A different error was thrown, not dispatched as an ErrorEvent");
}
}
For a full list of all errors thrown or dispatched as Events, see the Adobe language reference page: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html#load()

Related

Worker not receiving messages after RUNNING state, but it does later

Update: Apparently, it's some kind of timing issue. In the code below I create the worker from a click handler, but if I create the worker from the Main constructor (as the doc example does), the commandChannel message gets to the worker -- even though in either case I'm doing the exact same thing: create the worker, listen for RUNNING state, then send message over commandChannel. But that first message only gets through if I create the worker from the Main constructor, while messages later in time (some undetermined timed after RUNNING) always get through. Why? If I can't rely on WorkerState.RUNNING to know when I can send messages to the worker, how can I know when the worker is ready to receive messages?
I basically have the exact same thing as the documentation example, but it's not working. My setup is:
Flash Pro CC
AIR 17 for Desktop
Windows 7
The problem is that the worker does not seem to receive messages through the incoming message channel, though it can successfully send messages to the main SWF through an outgoing message channel.
This is my main class:
public class Main extends MovieClip {
[Embed(source="TestWorker.swf", mimeType="application/octet-stream")]
private var WorkerSWF:Class;
private var workerBytes:ByteArray;
private var worker:Worker;
private var commandChannel:MessageChannel;
private var resultChannel:MessageChannel;
public function Main() {
workerBytes = new WorkerSWF();
stage.addEventListener(MouseEvent.CLICK, clickHandler);
}
private function clickHandler(e:MouseEvent):void {
stage.removeEventListener(MouseEvent.CLICK, clickHandler);
startWorker();
}
private function startWorker():void {
trace("Start worker");
worker = WorkerDomain.current.createWorker(workerBytes, true);
commandChannel = Worker.current.createMessageChannel(worker);
worker.setSharedProperty("commands", commandChannel);
resultChannel = worker.createMessageChannel(Worker.current);
resultChannel.addEventListener(Event.CHANNEL_MESSAGE, resultMessageHandler);
worker.setSharedProperty("results", resultChannel);
worker.addEventListener(Event.WORKER_STATE, workerStateHandler);
worker.start();
}
private function workerStateHandler(e:Event):void {
trace("Worker state:", worker.state);
if(worker.state == WorkerState.RUNNING) {
trace("Worker running");
commandChannel.send("START PLEASE");
}
}
private function resultMessageHandler(e:Event):void {
trace(e, resultChannel.receive())
}
}
And my worker SWF class:
public class TestWorker extends Sprite {
private var commandChannel:MessageChannel;
private var resultChannel:MessageChannel;
public function TestWorker () {
trace("isPrimordial:", Worker.current.isPrimordial)
commandChannel = Worker.current.getSharedProperty("commands") as MessageChannel;
commandChannel.addEventListener(Event.CHANNEL_MESSAGE, commandMessageHandler);
resultChannel = Worker.current.getSharedProperty("results") as MessageChannel;
resultChannel.send("Hello from worker");
}
private function commandMessageHandler(e:Event):void {
trace("commandMessageHandler")
//var message:String = commandChannel.receive();
resultChannel.send("Whatever.");
setInterval(respond, 1000);
}
private function respond(){
resultChannel.send("Whatever " + new Date());
}
}
The problem is that the worker's commandMessageHandler is never triggered. I know this because I never receive the "Whatever" message back to the Main SWF. The "Hello from worker" message does get back to the Main SWF, so it's something specific to the main-to-worker message channel. What's wrong?
Additionally, it seems that neither trace actions or runtime errors from the worker are captured by the main SWF. How does one debug a worker SWF?
This seems to be a known issue (see point 2). WorkerState.RUNNING sometimes gets dispatched before the constructor of the worker has actually run. So in my case, from the click handler, the first message got sent before the constructor of the worker had added the listener to receive it.
So I'm going with the simple workaround: when the worker loads, send a message to the main thread that says "I'm ready" at the end of the constructor. In the main thread, listen for that instead of RUNNING before sending the intial command.

TypeError: Error #1009 with loading external SWF file

I was making 3D File Viewer in Flash Player with AS3.0
and i found AWD Viewer from Away3D Example File.
(http://awaytools.com/awaybuilder/tutorial-01/AwayBuilderTutorial01_SampleFiles.zip)
it works fine.
and i loaded it in my 'Main' swf file. but it's not work. it kept showing error to me.
error message is below
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at AWDViewer/initEngine()[C:\Users\wintec\Desktop\Flash3DViewer\source\AWDViewer.as:74]
at AWDViewer/init()[C:\Users\wintec\Desktop\Flash3DViewer\source\AWDViewer.as:57]
at AWDViewer()[C:\Users\wintec\Desktop\Flash3DViewer\source\AWDViewer.as:49]
and that error line is just this
line 74 : stage.scaleMode = StageScaleMode.NO_SCALE;
line 57 : initEngine();
line 49 : init();
and I know that error message mean there's no properties that name.
I checked that, there's nothing wrong.
also, when I loading another swf file in my 'Main'swf, that's works. weird...
I don't understand why this error kept showing.
please help me.
below code is from Main.as
package
{
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
public class Flash3DViewer extends MovieClip
{
private var _request:URLRequest = new URLRequest("AWDViewer.swf");
private var _loader:Loader = new Loader()
public function Flash3DViewer()
{
init();
}
private function init():void
{
stop();
_loader.load(_request);
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, initLoaded);
}
private function initLoaded():void
{
_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, initLoaded);
var extSwf = _loader.content as MovieClip;
swfContainer.addChild(extSwf);
trace("contents loaded");
}
}
}
I found the issue with your application based on the code you provided via DropBox. And just as I suspected, the stage property was being referenced before the object's addition to the stage was completed, which is why the null reference error was being generated.
The AWDViewer class was prematurely calling the stage property from one of the functions that is being called when the init function is called. I've updated the Flash3DViewer.as and AWDViewer.as files with the proper usage of the ADDED_TO_STAGE event so that this does not occur. I have also added comments to the code for you to follow along. Also, I had to modify the init function in the AWDViewer class to take a parameter of type Event to account for the fact that the function is now called when the ADDED_TO_STAGE event fires.
Flash3DViewer.as:
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
public class Flash3DViewer extends MovieClip
{
private var loader:Loader;
public function Flash3DViewer():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
loadSWF("AWDViewer.swf");
}
private function loadSWF(url:String):void
{
var urlRequest:URLRequest = new URLRequest(url);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded, false, 0, true);
loader.load(urlRequest);
addChild(loader);
}
private function onLoaded(e:Event):void
{
var target:AWDViewer = e.currentTarget.loader.content as AWDViewer;
trace(target);
//target.init(); // no longer need to call the init function manually as the AWDViewer calls it when it 'knows' it has been added to the stage. This line can be deleted.
addChild(target);
}
}
}
AWDViewer.as:
public function AWDViewer()
{
/* Used ADDED_TO_STAGE event to know when to trigger the init
function call to avoid the null reference errors when accessing
the 'stage' property */
addEventListener(Event.ADDED_TO_STAGE,init);
// init(); // no longer need to manually call the init function as the ADDED_TO_STAGE event listener will take care of this. This line can be deleted.
}
/**
* Global initialise function
*/
public function init(e:Event):void
{
initEngine();
initListeners();
AssetLibrary.enableParser(AWD2Parser);
//kickoff asset loading
var loader:Loader3D = new Loader3D();
loader.load(new URLRequest("assets/monkey.awd"));
_view.scene.addChild(loader);
}
While I did attempt to compile the code above, and the null reference errors ceased to generate with my corrected code, there were some compiler errors on my machine because of the different configurations of our computers. You'll just need to ensure that these compiler errors do not appear on your machine.
Warning: Library path "C:\Users\wintec\Desktop\3D_VR\source\libs" does not resolve to a valid directory.
Warning: Library path "$(FlexSDK)/frameworks/libs/flex.swc" does not resolve to a valid file.
If you have any other questions, just let me know.
Cheers.
That error means that you are trying to access something which has not been instantiated. You should put some breakpoints and run your app in debug mode when you are not sure what exactly is null.
It's very likely that stage is null in your case. Stage property of DisplayObject is set to the instance of app's stage when this display object is added to stage. However, all parents of this display object should be added to the stage too. Thus, make sure that the instance of Flash3DViewer has the stage before loading AWDViewer.

do I really need to have an event handler for URLLoader?

I am new to actionscript, and I am following a tutorial by Joseph Devore. I understand that when I want to do a network query I can create a URLRequest, and send this with a URLLoader. I expected to find the response data in the URLLoader.data attribute, but after making the query this was still null in my case. Then it seemed that I must create an event handling to actually access the response. Is this true?
I wrote this small example code, and wonder how I (the easiest way) can access the response in this get request.
package
{
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class stackQuery
{
public function stackQuery()
{
}
public function makeQuery(): String {
var request: URLRequest = URLRequest("http://www.google.com");
var loader: URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, handleResponse);
try{
loader.load(request);
}
if(loader.data == null){
return "Empty"
}
return "data not empty"
}
private function handleResponse(event:Event):void
{
//something with event.target.data here??
}
}
}
There isn't any nice way to do a synchronous load (like you can in some other languages) with AS3. Your data is null because in AS3 the load command is asynchronous - meaning it doesn't halt the rest of the application (locking it up) until the load completes, it moves on to the next line of code and dispatches an event once the load is complete.
Here is a code example of how you would want to handle this based off of the code you supplied:
package
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class stackQuery
{
private var loader: URLLoader = new URLLoader(); //let's move it out to the class level so you can easily reference it from other methods (though this is purely optional)
public function stackQuery()
{
}
public function makeQuery(): String {
var request:URLRequest = URLRequest("http://www.google.com");
//add you listeners before loading
loader.addEventListener(Event.COMPLETE, handleResponse);
loader.addEventListener(IOErrorEvent.IO_ERROR, handleResponse); //it's good practice to also listen for errors
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleResponse); //this kind of error will happen if you're trying to load a local resource but have published as network only (or vice-versa)
//load the request, any code after this will run before the load completes.
loader.load(request);
}
//this function will run once the load completes
private function handleResponse(event:Event):void
{
if (event is IOErrorEvent) {
//you had an IO error, better do something
return;
}
if (event is SecurityErrorEvent) {
//url wasn't allowed to load
return;
}
trace(loader.data); //this is what was returned from the page
//you could also get it by referencing the currentTarget of the event
trace(URLLoader(event.currentTarget).data);
}
}
}
Yes, of course it is true. Imagine you load one megabyte of data. You need time in order to load it, right? So there's no way that you will have this data on the very next line of code.
The listener will get executed when the target dispatches the event - in your case when that megabyte is loaded.
This is a normal behavior.
While the answers given are correct, the real explanation is that Actionscript 3 is an asynchronous language as opposed to other language like Python for example that are synchronous. In python after loading something like an url the next line of code will not be executed until the url is loaded (which can create lag or idling execution), in Actionscript 3 the code execution doesn't wait and move on to the next line. That is the reason you need to use events (Actionscript 3 is an event based language) so you can find out when the data you are waiting for is available all that while your code is still executing.

AS3 Error reporting from event callback

I have been experimenting with supplying better debugging information when an error happens in asynchronous code in AS3.
As an example of the poor error reporting be default, take the case where I force a null pointer in a Timer callback (github gist), I get the following stacktrace back on the console:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Function/<anonymous>()[/[path-to-source-file]/TestClass.as:14]
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
This tells me very little about how the timer callback actually links to my code.
The question is: How can I get information about what code created the callback?
I have added one of my solutions below. I'm interested to see if this can be improved.
One possible solution is to pre-create an Error object in the consumer "thread"/"scope"
var errorInConsumerScope:Error = new Error()
var timer:Timer = new Timer(1000, 1)
timer.addEventListener(TimerEvent.TIMER, internalCallback)
timer.start()
function internalCallback(e:TimerEvent):void
{
try
{
// do something that could cause an error
}
catch (e:Error)
{
errorInConsumerScope.message = e.message
throw errorInConsumerScope
}
}
This now gives me the stacktrace back into my calling code:
Error: Error #1009: Cannot access a property or method of a null object reference.
at TestClass()[/[path-to-source-file]/TestClass.as:10]
at Main()[/[path-to-source-file]/Main.as:9]
The complete gist is here
Interesting thing.
The doc to Error.getStackTrace() says:
Returns the call stack for an error as a string at the time of the
error's construction
According to this, the stacktrace works as expected. The error is constructed in your event handler which is called by the timer tick event.
In your second example you create the error to be dispatched in the constructor of the TestClass. So your stacktrace will show the chain up to the TestClass constructor.
You probably ask for a general solution. I would go with unit tests and proper debugging using breakpoints and object inspection. But here another idea:
TestClass:
package {
import flash.events.TimerEvent;
import flash.utils.Timer;
public class TestClass {
public function TestClass(userCallback : Function, fail : Function) {
var timer : Timer = new Timer(1000, 1);
timer.addEventListener(TimerEvent.TIMER, internalCallback);
timer.start();
function internalCallback(e : TimerEvent):void {
try {
var nullProperty : String;
nullProperty.length;
} catch (e:Error) {
fail();
return;
}
userCallback();
}
}
}
}
Main:
package {
import flash.display.Sprite;
public class Main extends Sprite {
public function Main() {
new TestClass(
function() : void { trace('Call me back when your done.'); },
function() : void { throw new Error('Something went wrong.'); }
);
}
}
}
Output:
Exception fault: Error: Something went wrong.
at Function/<anonymous>()[Main.as:8]
at Function/TestClass/$construct/internalCallback()[TestClass.as:16]
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()

In flash AS3 How to put single try catch code, in order to catch any errors in whole class?

In Flash AS3 I wanna write the single try catch block in order to catch any errors in whole class.
For example, I have a lot of functions in myClass.as. I don't wanna write in each function try catch blocks in order to catch errors in this function.
Is there any methods to do this?
Thank you!
you can't! there is no such easy way like that even in other language either than AS3 except they use AOP approach to do that.
The best practice is just let you classes bubble the Error (Exception) and let the higher layer catch and process the error.
EDIT - regarding coment
Actually the idea is the natural way.. still you need to manually catch every possible error. i'll give you example. Note that the purpose of the example only for clarity between lower layer and higher layer.
for example you have a class in the mid layer (Your Business Process):
public class MyBussiness {
public function loadImages(){
//for example here is a block of method
//possibly throws exception.
}
public function getLoan(){
//lets assume here too
}
}
in the higer layer (I Assume in your View - MXML) you catch the exception like bellow:
var myBussiness:MyBussiness = new MyBussiness():
try {
myBussiness.loadImages();
//any other sequence process
myBussiness.getLoan();
}
catch(error:Error){
//here you process error
//show it to user or make LOG
}
still it can't do a magic like you expect but it is the best practice. Rember only put try catch only on code that has possibility to throw error because try catch is expensive.
The best way is using try catch:
try{
//your command
} catch(e:Error){
//your command
}
You can catch all not handled errors in your program by using UncaughtErrorEvent class.
So, may be it what you want. There is an example from the docs (you could place addEventListener in the constructor of your main class):
package
{
import flash.display.Sprite;
import flash.events.ErrorEvent;
import flash.events.MouseEvent;
import flash.events.UncaughtErrorEvent;
public class UncaughtErrorEventExample extends Sprite
{
public function UncaughtErrorEventExample()
{
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorHandler);
drawUI();
}
private function uncaughtErrorHandler(event:UncaughtErrorEvent):void
{
if (event.error is Error)
{
var error:Error = event.error as Error;
// do something with the error
}
else if (event.error is ErrorEvent)
{
var errorEvent:ErrorEvent = event.error as ErrorEvent;
// do something with the error
}
else
{
// a non-Error, non-ErrorEvent type was thrown and uncaught
}
}
private function drawUI():void
{
var btn:Sprite = new Sprite();
btn.graphics.clear();
btn.graphics.beginFill(0xFFCC00);
btn.graphics.drawRect(0, 0, 100, 50);
btn.graphics.endFill();
addChild(btn);
btn.addEventListener(MouseEvent.CLICK, clickHandler);
}
private function clickHandler(event:MouseEvent):void
{
throw new Error("Gak!");
}
}
}
See the docs, please.