There was a feature I wanted to implement in Automatic 2.0 that required registering the prefPane to handle a specific (custom) URL scheme to pass data into the app. After a lot of digging, I came to the inevitable conclusion: it can’t be done. This post describes both my findings regarding URL schemes in prefPanes and the workaround I used.
Normally, an app can register specific URL schemes with LaunchServices, telling the system that if a user clicks on a URL, it should be forwarded to that app. The information about the URL schemes is stored in the app’s Info.plist, under the
Unfortunately, that doesn’t work with prefPanes (as usual: the prefPane’s bundle is not the app’s bundle). What’s very interesting however, is that apparently Apple’s Accounts prefPane can handle URLs with the
So how does it do it? Looking at the Info.plist file for System Preferences.app, it normally registers the
macosxserverinvite scheme, but also adds the key
preference pane identifier, with a value of
com.apple.preferences.users which is the bundle identifier for the Accounts prefPane. It seems that when System Preferences.app intercepts a registered URL, it forwards it to the prefPane whose bundle matches the
preference pane identifier key-value. The big problem here is that this set up is not extensible: as is the norm for Apple apps, System Preferences.app is signed, which means no touching the Info.plist file to add additional URL schemes and redirects (and even without the signing, editing another app’s bundle is very naughty).
That’s where the trail ends. There doesn’t appear to be any way to register a URL scheme for a prefPane inside System Preferences.app. However, there is a workaround: use a helper app.
The process goes like this: register a background helper app to handle the URL, and when the helper intercepts a URL, either process the information itself, or store the data and then launch the prefPane. Of course, because the helper can only launch the prefPane, but not provide it with any other information, it is the prefPane’s responsibility to check every time it launches if there is any URL data stored that hasn’t been handled.
It’s quite a hassle, but the end result for the user is seamless: click on the URL, the prefPane launches and takes appropriate action.