Have you ever wondered how Mac OS X knows which file type belongs to which application? On Windows there is the registry. An installer writes the necessary info into it. Most applications on Mac OS X doesn’t come with an installer, they are just moved from the downloaded DMG file to the
/Applications folder. So a developer doesn’t have the ability to take action when the user “install” the application. Anyway there is no need to provide an installer for just this task, cause Mac OS X register file type associations on the first start of the application. In the following post, I will show how to do this, but furthermore I will show where this information is stored and how it could be reseted.
Providing the necessary information to Mac OS X
Applications on Mac OS X need some defined structure. They are so-called bundles, which means on the filesystem layer they are directories. You can prove this by checking the Applications directory within the Terminal.app. You could also right-click on an application and select “Show Package Contents”. The content of the bundle directory is usually hidden from the user when he works with the Finder or any other high level function of Mac OS X (like the open dialog). Additional to this layout on the filesystem, an application provide information about itself to the system with a plist file. This file has to be named
Application.app/Content/Info.plist. The following shows exemplary the content of the Tunnelblick application:
<xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleExecutable</key> <string>Tunnelblick</string> <key>CFBundleIconFile</key> <string>tunnelblick.icns</string> <key>CFBundleIdentifier</key> <string>com.openvpn.tunnelblick</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>3.1beta20 (build 2132)</string> <key>CFBundleSignature</key> <string>OVPN</string> <key>CFBundleVersion</key> <string>2132</string> <key>NSMainNibFile</key> <string>MainMenu</string> <key>NSPrincipalClass</key> <string>NSApplication</string> <key>NSUIElement</key> <string>1</string> <key>SUEnableSystemProfiling</key> <true/> <key>SUFeedURL</key> <string>http://tunnelblick.net/appcast.rss</string> <key>SUPublicDSAKeyFile</key> <string>dsa_pub.pem</string> </dict> </plist>
The keys are mostly self explaining, you can find a full list here.
To register a file type association you have to add an array of the type
CFBundleDocumentTypes. Again, here is an extraction of the Tunnelblick application, which shows the registration of the
<key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeExtensions</key> <array><string>tblk</string></array> <key>CFBundleTypeIconFile</key> <string>tunnelblick_package.icns</string> <key>CFBundleTypeName</key> <string>Tunnelblick VPN Configuration</string> <key>CFBundleTypeRole</key> <string>Editor</string> <key>LSTypeIsPackage</key> <true/> <key>NSPersistentStoreTypeKey</key> <string>Binary</string> </dict> </array>
You have to provide a file extension or mime-type, can add an icon and give a hint what your application can do with this type of file (viewer, editor or nothing).
Beside this passive way of announcing this information, there is also an active way (e.g. for use in an installer). See here for further information.
Where is this information stored
Although Mac OS X hasn’t a registry like windows, some information are stored in global databases, too. Applications are registered at the
launchd. The launchd is the central place for starting all kind of programs, from a background service to any common application, like Thunderbird. E.g. background services can register itself and even made their start depending on different events. VirtualBox has an example configuration included, which let launchd start the vbox webservice on activity on a certain port. Although this isn’t used by many users out there (and therefore disabled by default), it shows some generic usage of this functionality.
If you look around in Mac OS X you have the tool
launchctl, which allows you to start jobs or register background services with launchd. But it seems there is no tool which is able to get some information about the knowledge of launchd. Well, there is one. It’s a little bit hidden in
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister. To be more comfortable with it, we should include it into the user path by linking it to a known path, like this:
sudo ln -s /Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister /usr/local/bin/lsregister
With this tiny tool we are able to dump the launchd database.
lsregister -dump | grep -n10 Tunnelblick displays something like this for Tunnelblick:
10823--------------------------------------------------------------------------------- 10824-bundle id: 6984 10825: path: /Applications/Tunnelblick.app 10826- name: 10827- identifier: com.openvpn.tunnelblick (0x800097b8) 10828- version: 2132 10829- mod date: 10/31/2010 12:37:08 10830- reg date: 11/19/2010 11:13:39 10831- type code: 'APPL' 10832- creator code: 'OVPN' 10833- sys version: 0 10834- flags: relative-icon-path ui-element 10835- item flags: container package application extension-hidden native-app ppc i386 10836- icon: Contents/Resources/tunnelblick.icns 10837: executable: Contents/MacOS/Tunnelblick 10838- inode: 3800129 10839- exec inode: 3800213 10840- container id: 32 10841- library: 10842- library items: 10843- -------------------------------------------------------- 10844- claim id: 17864 10845: name: Tunnelblick VPN Configuration 10846- rank: Default 10847- roles: Editor 10848- flags: relative-icon-path package 10849- icon: Contents/Resources/tunnelblick_package.icns 10850- bindings: .tblk 10851---------------------------------------------------------------------------------
As you see, all the information provided by the plist file is registered. Beside other information, it also has the registration and modification times stored. To let launchd reread the plist file, usual its only necessary to change the modification time of the application. This could be done by simply executing
touch /Applications/Application.app. Anyway, it’s sometimes necessary to reset the content of this database for the own application. This could be done by executing the following:
lsregister -u /Applications/Application.app
To register the application again, just remove the
-u parameter. You should also check if your application isn’t registered more than once, with different paths, by using the
-dump parameter. To fully reset the launchd database, you could use
-kill. This will remove any file type association and registered application. You have been warned.
This article shows how Mac OS X handle informations about installed applications. With this knowledge a developer is able to register the own application into the launchd ecosystem and see how launchd interpret this information. Furthermore, the usage of lsregister allows a developer to analyze the content of the launchd database and make changes to it.