7.6. Launching ApplicationsUsers typically create new processes by launching applications through the graphical user interfacefor example, through the Finder or the Dock. The Launch Services framework, which is a subframework of the Application Services umbrella framework, provides primary support for application launching. Launch Services allows programmatic opening of executables, documents,[22] and other entities either by file system references or by URL references. The framework provides functions such as the following.
The Cocoa NSWorkspace class uses the Launch Services framework to launch applications. Launch Services eventually performs a fork() and an execve(). 7.6.1. Mapping Entities to HandlersApplications can register themselves with Launch Services to advertise their ability to open documents of a certain type. Such ability can be specified by file extension, by URL scheme, and, more appropriately, through a generalized data identifier scheme called Uniform Type Identifiers (UTIs).[23] We will look at UTIs in the next section.
Typically, registration with Launch Services occurs automatically, without requiring any action from the user. For example, it could occur at the following times:
When examining the output of the ps command, you can see that the parent of processes corresponding to GUI-based applications is the WindowServer program. When a user launches a GUI-based application through the Finder, Launch Services sends a message to WindowServer, which in turns calls fork() and execve() to run the requested application. You can use the kdebug program from Chapter 6 to monitor the invocation of fork() by WindowServer. In particular, the AppServices startup item (/System/Library/StartupItems/AppServices/AppServices) runs the lsregister programa support tool that resides within the Launch Services framework bundleto load the Launch Services registration database. lsregister can also dump the contents of a registration database fileeach user has a separate database stored as /Library/Caches/com.apple.LaunchServices-*.csstore. Figure 761 shows an example of using lsregister. Figure 761. Dumping the Launch Services registration database
Consider the situation when an application wants to handle a document or URL type that is already registered in the Launch Services database. Launch Services considers several aspects before selecting a candidate. A handler explicitly specified by the user takes the highest precedence. An application on the boot volume is preferred over applications on any other volumesthis is important to avoid running potentially malicious handlers from untrusted volumes. Similarly, an application on a local volume is preferred over those on remote volumes. 7.6.2. Uniform Type IdentifiersA Uniform Type Identifier (UTI) is a Core Foundation stringfor example, "public.html" or "com.apple.quicktime-image"that uniquely identifies an abstract type. Mac OS X uses UTIs to describe data types and file formats. In general, a UTI can be used to describe arbitrary type information about in-memory or on-disk entities, such as aliases, files, directories, frameworks, other bundles, and even in-transit data. Since UTIs provide a consistent mechanism for tagging data, services and applications should use UTIs to specify and recognize data formats that they support. The following are examples of using UTIs.
A UTI string is syntactically similar to a bundle identifier. UTIs are written using a reverse DNS naming scheme, with certain top-level UTI domains being reserved for Apple's use.[24] For example, Apple declares types that it controls with identifiers in the com.apple domain. Public typesthat is, those types that either are public standards or are not controlled by an organizationare declared with identifiers in the public domain. Third parties should use Internet domains they own for declaring their UTIsfor example, com.companyname. The use of a reverse DNS naming scheme ensures uniqueness without centralized arbitration.
The Apple-reserved domain dyn is used for dynamic identifiers that are automatically created on the fly when a data type with no declared UTI is encountered. The creation of dyn UTIs is transparent to users. An example of a file whose content type is a dyn UTI is a .savedSearch filethese files correspond to Smart Folders and contain raw Spotlight queries. The information property list file of /System/Library/CoreServices/CoreTypes.bundle contains specifications of various standard UTIs. For example, we can list the public types contained in that file as follows: $ cd /System/Library/CoreServices/CoreTypes.bundle $ awk '{ if (match ($1, /public\.[^<]*/)) { \ substr($1, RSTART, RLENGTH); } }' Info.plist | sort | uniq public.3gpp public.3gpp2 public.ada-source ... public.camera-raw-image public.case-insensitive-text ... public.fortran-source public.html public.image public.item public.jpeg ... The UTI mechanism supports multiple inheritance, allowing a UTI to conform to one or more other UTIs. For example, an instance of HTML content is also an instance of textual content. Therefore, the UTI for HTML content (public.html) conforms to the UTI for textual content (public.text). Moreover, textual content is, generically speaking, a stream of bytes. Therefore, public.text conforms to public.data. It also conforms to public.content, which is a UTI describing all content types. The UTTypeConformsTo key is used in a UTI's declaration to specify its conformance to a list of UTIs. UTIs can be declared in the property list files of application bundles, Spotlight metadata importer bundles, Automator action bundles, and so on. Figure 762 shows an example of a UTI declarationthat of the public.html UTI. A bundle can export a UTI declaration using the UTExportedTypeDeclarations key, making that type available for use by other parties. Conversely, a bundle can import a UTI declaration through the UTImportedTypeDeclarations key, indicating that even though the bundle is not the owner of that type, it wishes to have the type made available on the system. If both imported and exported declarations for a UTI exist, the exported declaration takes precedence. Figure 762. Example of a UTI declaration
Note that UTIs do not preclude other tagging methods. In fact, they are compatible with such methods. As shown in Figure 762, content of type HTML text (as specified by the UTTypeDescription key) can be identified by several tags (as specified by the UTTypeTagSpecification key): an NSPasteboard type, a four-character file type code, multiple file extensions, or a MIME type. Therefore, a UTI can unify alternative methods of type identification. |