Archive for April, 2008

Command Line Argument Parsing and Argv

Back in 2001, when I was still doing Java programming, I got tired of writing ad-hoc command line parsing code and wrote a small library to factor out the difficult bits. The Argv library is still available. If you want to know more about the library itself, I recommend the Dr. Dobb’s article that describes it.

Although I haven’t gotten around to porting it to ActionScript, Mark Northup has ported it to C++ and was kind enough to provide the sources for that version. They’re now posted to the Argv web page. Thanks, Mark!

Custom Update UI for Application Updates

I’ve just finished my talk on the Brussels stop of the On AIR tour. I was discussing the importance of the application update mechanism in the context of dealing with security issues and mentioned the <customUpdateUI> feature. According to the show of hands in the audience, no one knows about this feature, which is a real shame.

The feature itself is simple. By default, if your application is already installed and an .air file for your application is opened, AIR will handle the situation. It will display appropriate UI; typically, you’ll see the old and new version numbers and be asked if you wish to upgrade.

That’s less than ideal for two reasons. First, most applications have their own update mechanisms, update UI, and so on. This default behavior circumvents all of that.

Second, it puts the decision about which version of the application is newer in the user’s hands. Assuming you use a straightforward versioning scheme, this is typically not an issue. However, if an attacker can convince a user to install an older version of the application, then they may be able to use a security vulnerability you’ve already patched to compromise the user’s machine.

To avoid these drawbacks, simply declare the <customUpdateUI> element in your descriptor. With that set, any activation of an .air file for your application will cause (a) your application to be started, if it’s not already running and (b) the path to the .air file to be delivered to your application via an InvokeEvent. Your application simply needs to capture that event and handle it. You can likely handle it by re-using the logic for your own auto-update mechanism.

That’s all there is to it. Full documentation is also available.. Give it a try; I hope to see more hands go up next time I ask who’s seen this.

The AIR Browser API and User Events

The AIR browser API lets web applications detect, install, and launch AIR applications. There are some restrictions on its use, however:

  • Applications have to opt-in to the detect and launch capability. This is done by specifying <allowsBrowserInvocation> in the application’s descriptor.
  • Installing and launching applications can only be performed in the context of a user event

“In the context of a user event” means that the method is called during an event handler for some event, such as a mouse click, that’s initiated by a user action, such as clicking on a button. Note that this doesn’t mean all mouse events qualify, as they can also be dispatched programmatically.

Why this restriction? To protect the user against malicious (or just really annoying) web pages. WIthout this restriction, pages could install and launch applications as soon as the page is loaded, over and over again, until you give up in disgust and quit using the Internet.

This restriction occasionally trips people up when using the browser API because it’s tempting to wait for a user event, then call getApplicationVersion() to determine whether or not the application is installed, and finally call installApplication() or launchApplication(). But this won’t work because the getApplicationVersion() call is asynchronous; when the specified callback function executes, the code is no longer part of the original user event.

Note that getApplicationVersion(), however, need not be called during a user event. The trick, then, is to call this method right away, when your web page loads. By the time the user clicks on the button, you’ll already know whether you need to install or launch and can do either immediately within the context of the user event.

One final note: consider calling getApplicationVersion() periodically from a Timer. That way, if the application install state does change while the page is open, subsequent clicks on that button will continue to do the right thing.