Accessibility for The Rest Of Us
Saturday, January 26th, 2008So, in addition to giving you an update on Google Importer, it is about time for another Cocoa post.
Google(Web) Importer for Leopard makes extensive use of the Accessibility API. This may seem a bit weird. Most people would think it would be for things like screen readers and speech recognition, but it can be used for a lot more. For example, the Watch Me Do feature in Automator that lets you record and replay every action you do in an application uses the Accessibility API. Google(Web) Importer will use it to get the search terms from Spotlight and the Finder.
The Accessibility API is great for getting the state of the GUI, such as the location of the mouse, the text typed into a field, or the button a user clicks. It is also great for controlling the GUI, like actually clicking a button or entering text. So, it can really be used in a lot of applications.
(By the way, the front end to the Accessibility API in Applescript is called UI Scripting. Same idea.)
Also, unlike Input Managers (which Google Importer for Tiger used), using the Accessibility API:
- Is fully supported and documented
- Works with practically every application (not just Cocoa apps)
- Should not break between releases, if coded carefully
Now, I don’t think it is necessary to write about how to use the API. It is a C API, but just read the documentation and look at this sample code that demonstrates just about everything.
Instead, I will focus on something else that probably will be purely for the benefit of the mighty search engines…
Aside from being really useful, the Accessibility API is also really powerful and therefore subject to abuse. For example, one could very easily write a keylogger with it. That is probably why Apple decided to disable it by default. To enable it, the user has to open System Prefrences, click on Universal Access, and check the box labeled “Enable access for assistive devices.” Now, there are a couple problems with that approach:
- It enables access system wide (or user wide, I’m not sure). That means that any application can use it if that little box is checked. In the keylogger example, if the user checked that box to let Automator use it legitimately, the keylogger can also use it without any sort of notification to the user.
- It is annoying. A user should not be asked to change their preferences just to run your application.
So, Apple came up with another solution in Tiger that solves these problems: the magic function AXMakeProcessTrusted. That will enable the API just for your application and needs to be called from a process running as root, so it is secure. It is also all automatic, so aside from asking the user for his/her password, there is nothing the user needs to do.
The problem is that it seems no one uses it. Every third party application I have seen and even Automator just asks the user to manually check the box in System Preferences. It is more work to implement and has one huge undocumented bug (the application must be relaunched before it is actually trusted Update: reported as #5711990), but I really think people should be using it. So, I thought I would release the code to make it easy to implement it in your app. It includes a helper agent that you should be able to just drop into your project.