Posts in Category "Mac OS"

Device Proliferation and the Cost of Software

I purchased my first application from the Mac OS App Store this week; it cost $99. Before I hit the purchase button, though, I wondered: Was I going to have to spend that $99 three times? Unlike my phone, of which I have only one, I have a Mac at work, one at home, and a laptop. Multiplying every purchase by three was going to make this a much more expensive proposition.

Being in the business of writing software for a living, I try to be conscientious regarding software license terms. To do that, I actually read the license agreements. Or at least, the part of them that deals with how many computers the software can be installed on.

In my experience with such terms, there has been a gradual evolution away from licenses tied to specific computers to accommodating the desktop/laptop combination that’s common these days. But, that still left the typical number of machines per license at two, and one of them had to be a laptop.

The Mac App Store licensing terms are much more generous: Each purchase can be used on any Mac that you own or control. From the Mac App Store FAQ:

Can I use apps from the Mac App Store on more than on computer?

Apps from the Mac App Store may be used on any Macs that you own or control for your personal use.

Re-assured that I’d only have to spend my $99 once, I proceeded with the purchase.

Does this represent a shift towards lower software costs for consumers? That $99 license from the Mac App Store cost the same as buying the software directly from its publisher, but the publisher’s license was more restrictive: I would have had to purchase two copies for twice the price.

Yes and no. The kicker is thatĀ the Mac App Store works only for my Mac. Want the same app for your iPad? That’s another $40. And for your iPhone? That’s another $20. So yes, this change in licensing terms brings down the cost of software for desktop and laptop computers. But at the same time, I’m spending moreĀ on software than ever before because I’m also buying it for different types of device. Device proliferation is driving costs right back up.

 

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.

How to Launch an AIR Application from the Command Line

These days, desktop applications are usually launched either from the Windows Shell, Mac OS Finder, KDE Desktop, etc. Less well-known is that these operating systems all also allow applications to be launched directly from the command line, terminal, DOS prompt, etc. When launched from the command line, applications can also receive command line arguments.

Consistent with our goal of making AIR-based applications as much like regular desktop applications as possible, this also works for AIR-based applications. In AIR, those command line arguments are received via the InvokeEvent dispatched from NativeApplication. This can prove useful in a variety of situations, especially when writing scripts for testing or other automated work.

On Windows and Linux, invoking AIR-based applications at the command line is straightforward. On Windows, inside the application’s install directory you’ll find an executable with the application’s name; that’s the thing to run from the command line. On Linux, the executable is inside the “bin” subdirectory.

On Mac OS things are slightly trickier. In Finder, applications appear to be a single file, but they’re really a folder with with an extension of “.app” and a particular interior folder structure. To launch them from the command line with arguments, you have to dig into this structure and find the executable. For example, to launch an application named HelloWorld you’d run:

/Applications/HelloWorld.app/Contents/MacOS/HelloWorld

You can also run an application on Mac OS via the “open” command, but open doesn’t support passing any command line arguments to the application.

One final note: You can also pass arguments to your application when debugging with adl. However, since adl takes its own arguments as well, you need to separate the adl arguments from the arguments intended for the application with the double-dash argument, like so:

adl HelloWorld-app.xml — a b c

In this example, the application will receive an InvokeEvent with arguments a, b, and c.

iCal Scalability

I switched to using iCal when my MacBook Pro became my primary email machine a while back. Continuing to run Outlook was too much trouble because it meant keeping a virtual machine running all the time. I tried Entourage, too, but iCal was simpler yet sufficient for my needs. True, iCal doesn’t integrate with our corporate calendaring solution–but in my job that apparently doesn’t matter much.

I found that iCal under 10.4 was a bit on the slow side. Performance enhancements were rumored for 10.5; another reason to look forward to the upgrade. Yet after the upgrade, iCal seemed as slow as ever–and sometimes worse. It’s easy to find complaints about iCal on the web, I couldn’t find many practical steps for speeding up. Time to do a little digging.

My events are divided among five calendars. With all five displayed, even changing the view from week to week was slow. I’d seen one reference on the web about a particular calendar giving someone trouble, so I tried mine one-by-one. Sure enough, just one calendar–let’s call it “A”–was responsible for the slowdown.

This matched up with a hunch of mine: there was a repeating event on calendar A that was basically un-editable in iCal. It didn’t cause a freeze or crash, but it hung iCal up for so long that I never had the patience to wait it out. Searching through the calendar event-by-event for a troublemaker could take a long time; starting with this troublemaker seemed like a good idea.

First, I exported the calendar to an .ical file which–thankfully–is a line-oriented text format. It was over four megabytes. Running “grep SUMMARY A.ical | wc -l”–SUMMARY is the field that contains the name of each event–showed it contained about twelve thousand events. I’m busy, but I’m not that busy.

Following up on my hunch, I searched manually for the repeating meeting. There were many, many instances–over eleven thousand. That’s a lot–so many that if I’d been to this meeting once a day, every day since I was born I would had my eleven thousandth meeting just a few years ago.

How did there get to be so many instances? That I don’t know. I suspect it’s related to the fact that this meeting occurs four days a week, so there’s probably no built-in recurrence rule for it. Worse, on one of those four days the meeting is in an alternate location, so that’s an additional exception to the recurrence. Even so, eleven thousand is clearly excessive.

Should iCal have been able to handle this event without slowing excessively? Hard to say. It’s not a large number of events in absolute terms; someone with ten years of experience and eight meetings a day would have more events in their calendar. Still, I suspect iCal scales more gracefully across a large number of different events and that the culprit here is the bizarrely large number of instances for the same (recurring) entry.

I removed all instances of the meeting by hand, deleted the original calendar, and imported the patched up version. Result? iCal is fast again.

Bonus question: Given what little I’ve said about our development process, what meeting do I attend four times a week?