Archive for August, 2009

Preventing ESC in Full Screen Interactive

Penultimate post on the AIR 1.5.2 update: Prior to AIR 1.5.2, if a user hit the escape key when an application was running in fullScreen or fullScreenInteractive, the application would be forced out of full screen mode. This remains the intended behavior for fullScreen, but was a defect in the implementation of fullScreenInteractive.

Starting with AIR 1.5.2, hitting escape causes fullScreenInteractive to exit by default but the behavior can be canceled by calling preventDefault() on the keydown event. Applications that use full screen to keep users (perhaps kids) from too easily leaving the application may find this change useful. As always, remember to update your namespace to take advantage of this new behavior.

SWFs in HTML in Transparent Windows in AIR 1.5.2

One of the admittedly more annoying limitations of the Adobe AIR HTMLLoader implementation is that it does not render SWFs embedded in the HTML when displayed in a transparent window. In AIR 1.5.2, this restriction has been partially lifted.

The problem arises because, by default, Flash Player renders content into a separate window that is positioned on top of the correct location relative to the underlying HTML. This is the original browser rendering for plug-ins. It’s straightforward, but makes it impossible for the rendered plug-in content to participate in the blending of the transparent window’s contents against whatever lies behind the window.

Flash Player has for some time offered alternate rendering models in which the contents are drawn as part of the HTML content instead of as a separate window. This allows the content to be covered by HTML elements–drop down menus, for example. These modes are accessed by setting the “wmode” parameter to “transparent” or “opaque”. See this Tech Note for details.

Prior to AIR 1.5.2, the HTMLLoader refused to display any SWF when it was inside a transparent window in order to avoid the incorrect rendering that would otherwise result. Starting with 1.5.2, the wmode of the content is inspected. If the wmode is “window”–the default value–the content can still not be rendered correctly, and the old behavior still applies. However, if the wmode is “transparent” or “opaque”, the SWF will be rendered and, because it is rendered into the HTML content, will correctly participate in the window transparency.

Using LocalConnection Reliably

Following up on my previous post about changes to LocalConnection in AIR 1.5.2, I thought I’d post some further information about how LocalConnection operates. Although definitely in the realm of implementation detail, it’s critical to know if you want to use LocalConnection in a reliable fashion. To the best of my knowledge, the following applies to all versions of LocalConnection to date.

LocalConnection operates via a shared memory segment that contains a list of endpoints listening for messages, plus a buffer in which messages can be queued up. All clients using LocalConnection periodically poll the segment, removing any messages for which they are the recipient and enqueueing any new messages they wish to send.

Clients that exit gracefully will remove themselves from the endpoint list during shutdown. However, to avoid a crashed client clogging up the segment with undeliverable messages, endpoints (and associated messages) are timed out by the other clients. Basically, any client that finds old messages queued up, thus indicating an unresponsive endpoint, removes that endpoint and associated messages from the segment. “Old” is defined as a few seconds.

This heuristic for detecting crashed clients can be tripped up by clients that merely become unresponsive–i.e. are in a tight loop in ActionScript–for too long. When this happens, the client’s endpoint is closed even though the client itself is still running. After this, the client can no longer receive any messages destined for that endpoint. Note that there are two things that have to happen to get into this situation: the listener has (1) to be unresponsive for a “long” time while (2) simultaneously having LocalConnection messages sent to it.

Clearly, the implementation could be modified to avoid this issue, and you certainly shouldn’t depend on this behavior. Still, I hope that knowing about this issue might help you avoid it by keeping your applications responsive. Keeping applications responsive is, of course, a good thing in any case.

LocalConnection.isPerUser in AIR 1.5.2

New to the AIR 1.5.2 release (and the corresponding Flash Player, 10.0.32) is the LocalConnection.isPerUser property. Note that you’ll need to update your application’s namespace to …/1.5.2 to access this property. Here’s why you should do that.

LocalConnection provides local (i.e., on the same machine) communication between SWFs and AIR applications. It operates via a shared memory segment that’s visible to all processes that use the mechanism.When LocalConnection was first implemented on Mac OS, it used a memory segment that is visible to all processes running on the machine. This was reasonable at the time, but problematic now that Mac OS is a multi-user operating system. The unfortunate result is that LocalConnection can be used to communicate across user accounts on Mac OS.

To address this a new, per-user implementation has been implemented on Mac OS. You should always use this mode; it’s safer. To do that, set LocalConnection.isPerUser = true on every LocalConnection object you create.

Unfortunately, AIR can’t do this for you transparently. The problem is that, if it did, you could get into a situation where version skew breaks use of LocalConnection. For example, this can occur if an application is running on AIR 1.5.2 and attempts to communicate with a SWF in the browser running on Flash Player 9. Until both sides are updated, there’s no way to use the isPerUser = true option. By adding an API and making this an option, we’ve given you a chance to migrate to this option without breaking anything along the way.

This issue is specific to Mac OS. Windows and Linux use a user-scoped LocalConnection in all cases, regardless of the isPerUser setting. You can safely set LocalConnection.isPerUser = true everywhere and be confident that the Windows and Linux behavior won’t change.

Final note: The default setting of this property is likely to change to true in a future release, in order to be consistent with our general philosophy of defaulting to safe behavior.

Pauses When Using ELS and DRM APIs

Lately I’ve fielded a couple of different queries about long pauses in applications using the EncryptedLocalStore (ELS) and DRM capabilities in Adobe AIR. Two questions on the same topic in one week is usually a good indication that some additional explanation is required, so here it is.

As you are probably aware, AIR applications are protected during deployment by digital signatures. These signatures are checked at installation time in order to verify that the application has not been tampered with and, when possible, to reliably display the application’s publisher.

The signatures are preserved by the installation process but are not normally checked when an application is running. However, there are two exceptions to this: the signature is validated when the application uses the ELS or DRM APIs. This is done to prevent attacks on the application’s protected data that operate by modifying the application itself–any such modification would invalidate the signature.

When we designed this mechanism, we targeted applications in the 1 MB to 10 MB size range. This is important because checking the signature requires computing hashes over the entire application. For these sizes we determined that we could compute hashes over the entire application without significant delay, and so we went with the straightforward implementation that does just that. Larger applications, however–and I’ve seen examples of applications over 1 GB in size–will suffer painful delays during these signature validation pauses.

Our current recommendation is that you avoid making applications this big. That may sound trite, but every large application I’ve seen so far was that big because it included assets, such as videos, that consumed the majority of the space. Moving these kinds of non-code-containing assets out of the application itself–for example, downloading them separately into the application storage directory–is a straightforward way to reduce the application to a tractable size.

For completeness, I’ll note that it is possible to design a validation mechanism that works incrementally. For example, Mac OS uses a clever scheme that hashes each page of the executable separately; the kernel can then amortize validation cost across each page as it is first referenced. (If the page is never referenced, it doesn’t matter if it has been modified.) At this time, however, we have no plans to adopt such a scheme for AIR.

One final note: This signature validation usually occurs just once, the first time either the ELS or DRM capabilities are used. However, if you set “stronglyBound” to true when using the ELS API, signature validation will occur on every access. I don’t recommend using this stronglyBound feature, for this and other reasons.