Exception Handling in ActionScript 3 for AdBlock Plus

I was reading Coldfused about AdBlock Plus, a Firefox plug-in that blocks ads and other elements of websites while you surf. I remembered that since upgrading to Firefox 2.0.0.11, my regular AdBlock plug-in is apparently not compatible. AdBlock Plus is.

Upon installing and giving her a run, I noticed a video player application I’m writing for work started throwing an exception I hadn’t seen before. We’re using Dart for Publishers via a proxy company for one particular project, which still requires a URL request on the client to DoubleClick’s ad servers, ad.doubleclick.net, with 50 billion parameters on the URL. DoubleClick’s one of the biggest ad services on the net, one of the reasons Google bought ’em I’m sure. Therefore, they are also one of the filters that AdBlock Plus looks for and actively blocks. Any calls to doublelclick anything fail since it’s stopped at the browser level.

This causes an IOError for URLLoader’s in ActionScript 3. I reckon this’ll throw a FaultEvent for HTTPService in Flex, but if you’re doing boiler-plate coding in either ActionScript only projects or Flash CS3 using URLLoader, you’ll need to write code to handle this in case any of your clients have ad blocking software installed. We already have a lot of exception handling on our own stuff since we develop on development & QA servers first and things can get wonky when the server guys update their stuff and something goes awry… or our client code is coded wrong. The only error’s we had seen in the Ad stuff was when the DoubleClick servers were configured wrong at a client site, and you’d get back a 1 pixel by 1 pixel transparent GIF in HTML instead of the XML you were expecting. In that case, we’d just dispatch a custom error event in the parsing function. This rarely happened and our error code was sound.

…so I thought until I installed AdBlock Plus and re-tested our app. For the record, you should be doing at least this level of exception handling, if not more if you are doing any coding with classes that throw errors. In AS2 it was ok if things blew up; no one knew. Not the user, nor you. In AS3, however, the recovery isn’t always as good; a lot of times the code will just abort the whole stack. Since you can’t do this code on _root:

try
{
        runSWF();
}
catch(err:Error)
{
        // something somewhere blew up good in my appz0r
        showErrorScreenMovieClip();
}

You need catch everything possible if you want to ensure your code has any hope of continuing. The whole point of exceptions, according to Java developers, is to catch the exception, and handle as best you can. Obviously, a lot of exceptions leave you with no options. If you own the code, you can show an error screen, and if your code is going into something else, you can dispatch an error event. That’s about it for some exceptions.

For those creating applications that need to show ads inside their Flash & Flex apps, you need to assume you’re entering a hostile landscape where people are going to do everything they can to block your ads. If your policy is that ads drive the revenue of your business, you can abort everything when an exception is thrown. If your policy is to not trust 3rd party servers that cost 5 figures but don’t even allow you to do a test movie in the Flash IDE, then you log the error, and just dispatch an error so the rest of your code can move on with life.

Below is some pseudo code that shows how you write near exception-proof code that hits some URL. The only thing missing is a timeout error. Writing a timer is complicated and controversial, so I’ll skip that part and assume if you get a timeout, you destroy the URLLoader, remove the listeners, and just dispatch a custom error indicating a timeout.

// create our loader
adLoader = new URLLoader();
adLoader.addEventListener(Event.COMPLETE, onLoaded);
adLoader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
adLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);req = new URLRequest("ad.doubleclick.net/coldcrazyparams");

// attempt to load
try
{
        adLoader.load(req);
}
catch(err:Error)
{
        // Either HTTP Sniffer like Charles is running,
        // your VPN is offline, or your interwebs are silly.
        dispatchEvent(new Event("adError"));
}

// The host is ad-blocked or cannot be reached.
protected function onIOError(event:IOErrorEvent):void
{
        dispatchEvent(new Event("adError"));
}

// OT OT OT
protected function onSecurityError(event:SecurityErrorEvent):void
{
        dispatchEvent(new Event("adError"));
}

protected function onLoaded(event:Event):void
{
        // all is well in the land of Hannah frikin' Lee
        // show ads, make bling, drink & celebrate
}

Don’t forget to put [Event] metadata tags at the top, so all people using your class (including you) get code hints in FlexBuilder for addEventListener. Usually, there should be at least 2 events in my opinion; complete and error. Since we don’t have throwable like Java, exceptions break the heck out of encapsulation, and events are both synchronous and asynchronous; events for the win.

Side Rant

Unfortunately, what the code above can’t do is dodge the dreaded VerifyError, aka invalid register accessed etc etc. You get this if your SWF gets corrupted in some way. I got one of these with Flex Builder 3 Beta 2. At first, I tracked it down do a nested XML namespace. Later, it turned out there was “magic funk” around the error function itself I routed exceptions to. I noticed that older CSS files had all of these errors for every style from a Flex 2 project. If I re-wrote them the exact same, letter for letter, they were fine. So, copied and pasted the whole thing to Notepad, and then back… and everything was fine. WTF? UTF-8 demon infestation? Anyway, tried same theory here; re-wrote function a good 5 blank lines away and low and behold, no more VerifyError. I’m hoping it was just a Beta 2 problem.

Anyway, Flex Builder 3 Beta 3 rules so far.

3 Replies to “Exception Handling in ActionScript 3 for AdBlock Plus”

  1. You can get around the VerifyError by loading swfs with URLLoader and the doing a Loader.loadBytes, you can catch the exception there. BUT! Since this will load code directly into your apps’ SecurityDomain you should only use it to load from trusted sources.

Comments are closed.