Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2004-405
$eventId
ID of event: wwdc2004
$eventContentId
ID of session without event part: 405
$eventShortId
Shortened ID of event: wwdc04
$year
Year of session: 2004
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC04 • Session 405

Understanding Document Binding on Mac OS X

Application • 57:35

Uniform Type Identifiers (UTIs) are a new way of specifying document and data types. In this session, we cover how UTIs are used by Launch Services to enhance and simplify document binding. We also discuss new application information property list keys, as well as APIs for controlling document binding user preferences.

Speaker: Christopher Linn

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Thank you. Thank you and good morning. I went backwards already. This session is called Understanding Document Binding. I thought that I should start by explaining what we mean by document binding so we know what we're talking about. One of the breakthrough or revolutionary features of the original Mac back in 1984 was the ability to let users double click on a document and have it open in the right application or an application that could work with the document. And this was revolutionary just because the user didn't have to figure out which tools to use anymore. The user could just start working on a document. And it's still a very critical feature today.

So very narrowly defined, document binding is what makes that work. It's how the OS associates documents with applications that can view and edit them. And on Mac OS X, that service is provided by the Launch Services Framework. So that's the technology we're gonna be talking about for the next hour, and specifically going into what's new with Launch Services on Tiger.

First, I gave a very narrow definition. Launch Services actually does more than simply associate documents and applications, and I wanted to review what those things are. It's an API that is used heavily by the Finder and the Dock, other applications, third-party applications to open things. It's an API that can actually just open an application, open documents, and on Mac OS X, we added the ability to associate URLs, specifically URL schemes, with applications that can handle those URLs. And so there's API for opening all of those things and creating new applications in the user's workspace.

As I said, in order to make that work, Launch Services figures out and keeps track of application document bindings. So it looks at your application, looks at your info P list and figures out what kind of documents and URLs you can handle and it remembers all those associations. Now, with so many applications available today, there's often a number of applications on the system that can handle any particular type of document. Launch Services keeps track of user preferences so that we know actually which application is preferred when the user double clicks on a given document.

And then finally, because there are certain things provided or related to document binding that appear in the UI, such as in the finder and in other applications, such as kind strings for a document, localized display names for documents and applications and folders, there's this abstraction layer, a thin abstraction layer above the file system that Launch Services provides additional attributes that appear in the UI that give us the nice user experience that we expect on the Mac. So those are the things that Launch Services does. And I'd like to talk then about the topics, if I can get this to work. The topics we want to talk about today as far as what's new in Launch Services on Tiger.

The first one is actually not new. Uniform Type Identifiers were introduced in 10.3, but they were very specifically introduced for one purpose, which was to support the new Carbon Pasteboard API. And they're going to be used much more widely on Tiger, and I want to give a quick overview of what they are, how they work, because it's relevant to the rest of the session.

Uniform Type Identifiers are going to be used in a new way to declare your document kinds in your InfoP list so that you can simplify your InfoP list and benefit from other features that UTIs provide. There are three new sets of API in Launch Services. The first one is a new way to access item attributes. That's the abstraction layer over the file system. New API for actually setting and reading user binding preferences. And new options for opening things. New ways to open documents, URLs, and applications.

I've got a little spiel about security and how it relates to Launch Services. And I want to finish up with some interesting ways in which we're extending the whole idea of opening things and how, what kinds of things can be opened in the user's workspace. So let's start with Uniform Type Identifiers.

When Mac OS X was introduced, we wanted to play really well with the rest of the computing world. One of the controversial things we did was recognize file name extensions. We also wanted to work really well with the Internet. These things were all facts of life that we had to interoperate well with the computing world. It led to a kind of Tower of Babel as far as how we identify data and file system object types on the system.

And to use an example of this, these are all the different ways that TIFF data might be identified on Mac OS X. There's a MIME type. There's two file name extensions that are distinct, but they mean the same thing. There's COCO's NS TIFF keyboard type for the NS Pasteboard. And then there's the TIFF OS type, which might be on the Carbon scrap or could be associated with a file on disk. And there was no system service to kind of tie all these together.

And make it clear that they were related. There was Internet config, but it didn't cover all of these namespaces, and it was really geared towards the Internet. And we wanted to provide a general service for abstractly recognizing types, and that's what UTIs are. We decided we needed to introduce a new namespace because none of the existing ones really did the trick.

They were too prone to collisions, or in order to avoid collisions, like MIME type, they required registration. And there were all sorts of MIME types that aren't even declared or don't exist yet that we wanted to associate with the files on the system. And so we didn't want to be tied to MIME types. We created a new naming convention called Uniform Type Identifier. This is an example, public.tiff. And what's key to making it not just another namespace is that built into the system is the ability to map it to other type namespaces.

The API associated with UTIs allows you to go back and forth between a UTI and a MIME type, file name extension, and so on. It's very easy to, given a file, figure out what its UTI is, given some data on the pasteboard, see its UTI, and so on. That's one thing that's built in that helps us make sense of all this type identification stuff.

I'm gonna have to bend down like this to get the slides to go forward. What about the namespace? Well, we... When Mac OS X was introduced, we borrowed from Java to use the reverse DNS namespace for bundle identifiers. In a way, a bundle identifier is the modern replacement for the creator signature on an application. It was natural to extend that to type identifiers. Let me bring up a couple of other examples. For types that are proprietary or owned by a particular organization, we use the reverse DNS naming convention. com.apple.picked is a quick draw picture data.

com.adobe.photoshop.psd would be an example of a Photoshop document. The important thing is that they're unique. The name doesn't imply any sort of type hierarchy, as with mind types. But the important thing is that using reverse DNS makes it naturally unique, and we're not going to have collisions. They're also kind of verbose.

You can read them. You know what organization they're associated with, who to go to for more information about a type you're not familiar with. And then for types that really are in the public domain or not owned by any of the standard types, we just put those in the public. So that it's clear that they're UTIs and that they're standard.

Now, I mentioned the type hierarchy with MIME types. We wanted to go further than that. The MIME type hierarchy is very fixed. It's built into the name and fairly simple. You've got images, audio, video, text. We felt it was important to have a runtime to identify types in a hierarchy. As we go through the session and other sessions later this week, you'll see how that hierarchy is useful. These are all examples of images, the same types I had on the last slide. They are declared as being subtypes or conforming to public.image, an abstract type.

This is important because users think of these files as images. By associating them as subtypes of something called public.image, we can associate certain attributes that are associated with images, such as the resolution, height, width, and so on. This is something that Spotlight uses a lot for building the metadata store.

To go a step further, all images are data streams, and so pretty much every file on disk is a subtype of public.data because it's a data stream. But because it's a multiple inheritance hierarchy, we can add other tags, if you will, or names to a type. And content is something that reflects document content, something that when the user double clicks on it, it's going to open as a document, something they can edit. Just some other examples of abstract types like that. Let's look at subtypes of content. We've got images, of which I gave a few concrete examples.

We've also got public.text, which is anything which is text encoded. This is not going to be a complete overview of the type hierarchy. This session is not supposed to be about UTIs, but it's important to get a feel for what it's like. There's some documentation I can point you at later. Audiovisual Content Audiovisual Content is a way to group all time-based media together.

We can also model different kinds of directories. So we use directories in a lot of different ways in the file system now. But the root type for directories is public.directory. And everything pretty much goes into two categories. Either it's a folder, which is something the user can navigate into, or it's a package, which is something we define as something that to the user looks like a file. And an example of a concrete package is an application bundle.

Finally, I just wanted to give another example of how multiple inheritance can be used. There's several kinds of applications on the system. There's application bundles. There's also files with the type APPL, which can be applications. And so we have an abstract supertype com.apple.application. And you can use that, for instance, in a file selection dialog. If you filter for just one UTI, com.apple.application, the user will be able to select any kind of application, whether it's a bundle or a file.

So it gives us this very rich type description model. And it's extensible. Because the name space naturally avoids collisions, you can add your type to the hierarchy. And you do that by putting a declaration in your info P list. It's some XML, which is pretty simple. It's similar to how document types are currently declared.

You give the type identifier. You say what it conforms to. And then you list out the different kinds of tags or other name spaces, such as this one has two file name extensions and one mind type. And that's how you create automatic mappings between the UTI, the abstract type, that is, and specific name space tags.

So those are the key points about UTIs. We've got naming conventions that ensure uniqueness. It gives us an abstract idea of what a type is independent of all the different namespaces. They also exist in a hierarchy, which gives us a nice model for filtering and associating metadata. And the key is to declare your own types so that other applications can take advantage of them.

And you'll see some advantages of that later on. In 10.3, there were not a whole lot of types declared because, as I said, it was targeted really just the pasteboard. But we've added a lot more. There are string constants for them along with some commentary in this header, UTCoreTypes.h. So enough of that. Let's go on more specifically to Launch Services and how UTIs can simplify your application development.

When you declare your document types, that is, what kinds of documents you can open in your application, It's fairly laborious. You have to, even for basic types like JPEG, TIFF, or text files, you have to go through and you list every possible OS type, every MIME type, every file name extension that you want to recognize. It's kind of very literal.

And there's no notion of abstractly recognizing a type. And that means every application that opens JPEGs has to come up with the right list of JPEG identifiers. And more importantly, if you open text, well, there's no way in the world that you can possibly list every file name extension that might be a text type. So, UTIs allow us to simplify that process and leverage the type hierarchy and type knowledge contributed by other applications on the system. is the founder of the company, and he's been working with us for a long time.

Here is, this is pulled from preview.app. This is... Not even the whole type declaration, but this is just for three types. We've got TIFF, JPEG, and PICT. And it's saying that it's a viewer for these three types. It lists all of the different file name extensions and OS types, and it provides an icon and a kind string. And it's a lot of text. I purposely made it unreadable. That's the point.

It's small because there's a lot of it, and I had to fit it all in one slide. On Tiger, you can simplify all that. We've got one dictionary here of listing several document types, and it uses a new key: LS_ITEM_CONTENT_TYPES. And it's an array of UTIs. claiming JPEG, TIFF, and PICT, the same three types from the last slide. And it says that the application is a viewer for these types.

And it doesn't... If you don't want to, you don't even have to provide an icon or a kinestring because the system will provide the default icon and kinestring associated with those types. You still can if you want to have a branded icon when a file is bound to your app. You can provide an icon, but you don't have to.

You don't risk having a completely generic document show up, document icon show up by not providing one. So as you can see, this is much simpler. And it allows all applications using this style of declaration to have the same definition of what a JPEG is, what a TIFF is, and what a PICT is.

So everyone's using the same extensions, the same OS types, because that's controlled elsewhere by the type declaration. Another way to think of it is that we've... We took what was document type declarations and we split it up into an abstract type and then an association of the type with a role, in this case, viewer.

Another example, I call this a free lunch, because if you want to claim to open all plain text files, The advantage of doing this is that you suddenly gain the ability to open a plain text file declared by some other application on the system. So you don't even have to know what the extension is or how it's identified as text.

You rely on the system to determine that. Christopher Linn If you declare this this way, then somebody will take a plain text file, try to drop it on your application, and they'll get the right feedback, and the document can be dropped, even though you might have no idea what the extension is.

[Transcript missing]

is a new way to allow folders and hard disks to be dropped onto an application. Now we have UTIs for those, as well as for package types and so on. And those can be listed as LS item content types in your plist. So I think what I should do now is switch over to the demo machine and just give an example here of what I've been talking about.

The example I picked is TextEdit. Everyone knows what it is. The source code is available as an example on the DVD you received. We're starting out with stock TextEdit. Let's see what it can do. I'm going to show a series of drag and drop operations because that's an easy way to test document binding. You get feedback as to whether the application is going to accept a document. Here's a plain text shopping list. Obviously, that is going to work. Let's move along. Here's a .c file, source code. Is it going to be able to handle that? Probably.

Here's some HTML. I'm not sure what it's gonna do with that, but it is text, so let's see. Okay, so actually TextEdit knows how to render HTML. That's kind of nice. It gives me a nice rich text display. Now here's a PDF. That's not really a text file, but let's see what TextEdit's going to do. Looks like maybe it is going to open it. Oh, that's kind of disappointing, isn't it? It's kind of a downer because it looked like it was going to do the right thing, and it really didn't.

This just -- that's not what I want. Well, so that's not so good. I wonder -- well, I wonder what would happen if I grabbed a hard disk. Well, it looks like it can open those, too. At least it didn't try to display the contents of my hard disk.

[Transcript missing]

gives a stab at recognizing anything as a text file and trying to display it.

[Transcript missing]

is a very good example of how to use the CFBundle document types. is a very interesting person. He's been working on a lot of things in the last couple of years.

and that asterisk is really what, they don't even have to list anything else in their P list. If you just list an asterisk, it says, let anything be dropped on this application. And with UTIs, we can do a little bit better than that. And I'm gonna, Go in here and just get rid of everything.

And I even want to... Get rid of most of these here. Get rid of the icon, line types, type name. OS types, we need that. We've got the role, it's an editor. And I'm gonna create a new key, LS item content types. And if I don't get it exactly right, it'll be a sad demo. And this is an array.

And let's add a UTI here. Public.Text. So this is saying open any kind of text file. By the way, the difference between text and plain dash text is that text includes things like HTML or RTF, text with markup. Plain text has no markup. So I built it, I think. and let's see, this was actually the build target right here. Let's see what happens. We can still open shopping lists.

[Transcript missing]

If we grab PDF, however, it won't let us drop it anymore, because PDF is not a type of text. And why don't we grab the hard disk, and sure enough, it won't let us drop that either. In fact, the finder is showing the Make Alias icon, because it's gonna make an alias in this folder if I drop it here. So we've improved the user feedback there and simplified the P list at the same time. Now, just one more quick example. Suppose for some reason we wanted to add back the ability to open volumes, TextEdit suddenly could browse volumes. So let's add one more UTI in here.

should be able to drop that if we wanted to. So by adding one value to the P list, we can really get very precise definition or declaration, if you will, of what kinds of documents your application can open.

[Transcript missing]

When you double click a particular kind of document, if there's an application that specifically claims that UTI or document kind, it will be preferred. But if there is no specific application available like that, then an application, say, claiming plain text will become a candidate for opening a text file.

So one problem with all this is that you're going to start getting open document events, ODoc, Apple events, for files that you may not know anything about. You may not recognize any of the metadata associated with that file. So you need to know what kind of file it is. And for that, we're providing new API in Launch Services.

There's a new content type property associated with everything on disk. It's not actually on disk, but you get at it through Launch Services. There's really no need to store yet another type identifier on disk, because we've got file name extensions, we've got OS types. And so the content type is a UTI that is essentially derived from all the available metadata, and you just have to ask Launch Services what the content type is, and then you know.

And it may be a very specific subtype that, again, you don't know anything about, but you can test it for conformance to the types you do recognize. So if you recognize plain text, you say, okay, I've got a UTI. Does it conform to plain text? You ask us that, and we say yes, and then you know what to do with it.

As far as API, to get at the content type attribute, we could have just added a new method, say, given this FSRef, what is the content type? The reason we didn't do that was that we kind of have been adding a number of those on with each release of Mac OS X.

First, there was the kind string that you could get for a file. Then there was the display name. The problem is that each of those introduce I.O. or cause I.O. to happen. And so if you have to get several attributes, the I.O. gets done over and over again.

So we've generalized that to two new functions, LS copy item attribute and, more interestingly, LS copy item attributes, a bulk call. So that attributes have names, and you also have to provide a role mask, which means, you know, you're asking for an attribute as an editor or a viewer, because the role can affect the document binding.

And you get back a value, which is often a string, but it could be any core foundation object type, such as a Boolean, a number. In the case of the bulk call, you pass in an array of attribute names, and you get back a dictionary of key value pairs.

And the bulk call is really nice. If you know what attributes you need in your UI, what you're going to have to display or work with, you can ask for all of those at once, and we only have to do the I.O. once on the file to get the attributes.

So there's a number of string constants naming the attributes now in the Launch Services headers. The attributes include, and there's a few other ones, but the major ones are the content type, which is the UTI. And by the way, content type is also the term used for Spotlight for the metadata framework, which you'll learn more about tomorrow. And it's very important property for categorizing metadata. Content type is the only new attribute. We also provide the display name, the kind string, and just for completeness and to allow bulk access, you can get the type, the creator, and the extension of the target object.

So that's the Attributes API. I want to go on now to the next set of API, which is new in Tiger, which is setting handler preferences. I didn't want to go through another WWDC without being able to say that we can essentially replace the Internet config functionality. Finally, on Mac OS X, and that's what the Preferences API provides, is a way to do part of what Internet Config did, which was associate file types and extensions with a creator code that would be the default handler, and also associate schemes with a creator code, which would be the default handler for a given URL. And we've tried to keep it simple and in that spirit, but using the data types that are in common use on Mac OS X. So the terminology goes like this: A handler is an application which is capable of opening a particular kind of document or a particular URL scheme.

And for a given document type or scheme, you can get what the default handler is, that is the one that the user prefers. You can get all the known handlers in a list, and that's useful for driving a UI, say for a pop-up menu. and you can set the default handler.

Now, handlers are specified not by a specific application instance, but by bundle ID. And so it allows us to pick the user's preferred app. Say if an app is already running, for instance, and the user prefers that bundle ID, we're gonna use the app that's already running, not another one on disk. So when you set preferences, you give a bundle identifier. And as I mentioned, this pretty much replaces a key part of the Internet Config API. So here's a simple example of a bundle ID.

Content type handlers are driven by UTIs, expressed with a content type, in this case, JPEG. If you were to ask Launch Services for a list of possible handlers, you would actually get back a pretty long list of JPEG handlers on the system. But to simplify it, here are three: Preview, of course, which is the one that ships out of the box as the default. BBEdit can actually display JPEGs, I found, and Internet Explorer.

and each handler has a role. So this is saying that the default viewer for JPEG is com.apple.preview. and so if you ask the default viewer, you'll get back that bundle identifier. If you set the default viewer to BBEdit, it will create an association to handle JPEGs by default in BBEdit.

Now, Here are the APIs real quick. All I need to say about them is that there's three functions for UTIs. You can get the default role handler, copy all the role handlers to get a list of

[Transcript missing]

It's a little bit simpler for URL schemes, but the same idea.

You can pass in a URL scheme. There's no roles with handling URLs, but you pass in a URL scheme, you can get the default handler, you can get a list of all the available handlers for a given scheme. So you pass in HTTP, you get back all the browsers on the system, for example, and you can set what the default handler is.

So, very simple API, and this is something that developers have requested for some time. There are various reasons why in your preferences dialogue or at application launch, you might want to give the user some choice about making your app the default. But I want to put some guidelines out there for setting handlers that you need to remember. These are -- because we're taking a little bit of a risk by making all these public because they can be abused.

The idea of these APIs is that they set user preferences, not developer preferences. You may want all of your documents and URLs to go to your application, but this is not an invitation to just slam the settings. All of these should be used with the user's wishes in mind. So, if you're going to be changing preferences, you should be informative about what you're doing, what you're changing.

Give the user a choice and make sure that you have the user's consent. You follow what the user asks for and don't pester the user. I know that there's a desire sometimes on first launch of an application to ask if you want the app to be the default handler. And that's okay. Throwing up an alert isn't the ideal UI, but just don't do it every time. If the user says no, the user has said no. If the user says yes, great. Thank you.

The third set of new API that I want to talk about today is opening things. We've had a bunch of developer requests over the last couple of years, and they've piled up enough so that we can provide them all in one fell swoop. So I actually tried to include Everything we had a record of in our bug database for things people wanted from the LS open calls. Those include getting back a process serial number when you open a document or an application.

works with me. The initial Apple event, so you can put together any arbitrary Apple event you want and pass it to an application that you're launching.

[Transcript missing]

Finally, being able to open a document with a specific role. If you want to open a document for viewing or specifically for editing or for some other role, this API lets you do that.

What does it look like? Well, first of all, there's a structure which is used by the three functions which are going to follow. And inside the structure is everything related to specifically launching an application. That is, nothing related to documents or URLs, but just specifying an application and how it should be launched.

It's called LS application parameters. And There's Launch Flags, which are already used in the old LS Open API. There is an FS Ref for which application should be launched. And then there's some other things like the environment as a dictionary of key value pairs, the command line arguments as an array of strings, and the initial Apple event. And this is nice. You don't even have to flatten the Apple event like you did with the Process Manager APIs. You just create an Apple event. is the first Apple event to be delivered to the Target app.

If you want to open an application, you have this simple function to call: lsopenapplication. You pass in the parameters structure that we just looked at, and you get back a process serial number. That's a nice simple one.

[Transcript missing]

And then there's a similar API for URLs. In this case, it's very similar, except that you have an array of URLs to open. These could be document URLs, by the way, which is especially convenient for, say, Cocoa apps. You can pass in file URLs here, and they'll be handled as documents.

That's all the new API I want to talk about. There's a few other odds and ends, but that is the bulk of it. It's new in Tiger. Now I want to talk about security. Just earlier this month, there was a security update that went out, and Launch Services was in that security update. In fact, it was happening just as I was trying to gear up for WWDC, so it distracted me for a while. But we actually had to change the Launch Services behavior in order to avoid running an application that the user didn't trust.

That is, an application which the user may have downloaded, perhaps accidentally, and then maybe the user clicked on a URL on a web page, and that application was a handler for the URL, and it would get launched. So there's a small chance there could be a malicious application that got launched this way.

We didn't actually have any cases of this, but we wanted to close that. that up as soon as possible. So the important thing I want to pass along is kind of what changed in Launch Services and also how you guys participate in maintaining security with respect to launching things. The main goal was don't run untrusted code without user consent.

In this context, untrusted code we define as an application which has never before been launched. If the application has been launched, we take that as kind of an implicit statement of trust. The user asked for that application to be launched. If it's a malicious app, once it's launched, it's done its thing. Running it again probably isn't going to be any worse.

And furthermore, it's the user's system. We have to allow the user to do what the user wants to do. So once an app is launched, it's trusted. But if it's never been launched before, then we don't necessarily want to trust its bindings. That is, we don't want to use it in particular when the user double clicks a document or opens a URL, which is bound only to that application.

So the design principles, we kind of had to be really careful because we didn't want to ruin the user experience. But the design principles are do what the user is asking for. When we're evaluating document bindings and URL bindings, always prefer trusted applications. If there's several choices of applications, pick a trusted one, one that the user has run before.

If there are no trusted apps, then give the user a chance to intervene and stop an app from launching that they may not be expecting. But then once an app does launch, trust that application in the future. So this results in A minimal, I guess, disruption of the user experience.

But now, if the user double clicks, essentially when an app is first installed on the system or it's downloaded, it's in an untrusted state. And if the user launches that application, there's no intervention, no UI. If the user drags something and drops it on that application, that's an explicit gesture to launch an application.

But if the user clicks a URL in the browser and we're about to launch an untrusted app, then we actually will show some UI. And it's a warning. The internet location you are opening will open the application malware for the first time. Are you sure you want to open this application? And this is the chance we're giving the user to intervene and say no. And there's no default button. They have to make a choice. This is the way we came up with to minimally disrupt the user experience, but also give the user a chance to stop an application from running unexpectedly.

So, what are your responsibilities in making all this work? As I said, if the user double clicks an application, we're going to launch it. And all the finder is doing is calling LS open on the application. So likewise, if you are going to launch an application, we're not going to put up a dialogue.

asking the user if this is what they really want to do. So it's up to you guys to make sure that you're launching an application which is trusted. Either it's an application you know about, like it's one of the applications in your suite of applications, one of your helper apps, or it's something that was explicitly selected by the user, like in James Thompson's drag thing is a launcher app. So if the user clicks a tile there, it's essentially user consent. So those are the main things. If you launch an application, either it's one of your trusted apps or it's something the user explicitly asked for.

If you are going to open a document or a URL, generally just let Launch Services choose which application. If you pass in a document and a specific application to use, it's like a drag and drop gesture. It's interpreted as an explicit request to launch an app, and we're not going to pester the user with an alert in that case.

But if you just say open a document and let Launch Services choose, that is specify null for the application, then you'll get two benefits. First of all, it'll be respecting the user's binding preferences because LS will follow that choice. And it will also enable us to show the consent alert if it's necessary to block an untrusted app from launching.

There's one other new thing in Tiger which we want to build awareness of and over time will help us improve security. We want to encourage people to use a new role of shell, role shell, in your info.p list. Prior to Tiger, the only two roles you could list in your InfoP list were editor and viewer. It turns out that there's really another kind of document commonly in use, which isn't really a document.

It's an executable, which isn't an application. It could be a JAR file, a Java application, or an Apple script or any other kind of proprietary scripting language. People clicking it is going to execute the program in that document. And if you are offering that kind of service for one of your documents, put it in your info.p list as role shell.

This will allow us to know that you're not actually going to edit or view the document, you're going to execute the document. And so there may be special security measures that we want to provide in the future in order to help the user know what's going to happen. For instance, we might change the appearance of things which are going to get executed when they're double clicked. It might look a little bit different than regular documents. I'm not saying we're going to do that. In fact, we haven't even tried that, but it's a possibility.

So, likewise, if all executable files are claimed with role shell, then when you go to LS open something, if you want to make sure it's not executed, you can just specify role editor or role viewer, and we'll refuse to pick an app that claims role shell for the type of document that you're opening. So that's something new to Tiger, and we just are encouraging people to start using it. It will become more useful over time.

The last topic today I want to talk about is extending the open metaphor. This is something I've been wanting to do for a while, and it's fun to show it in Tiger now. Since the doc was introduced, it's this really nice access point for applications. And from the beginning, we've been able to drag documents down to the dock and drop them onto application tiles.

And it's a great drop target because it's always there, it's always at the top layer, it's never hidden behind anything. And I found that there were times when I was frustrated because there were other things I wanted to drag down to the dock and nothing would happen. I would hover over an application tile and there's no feedback, you can't drop anything.

And so, By extending the open metaphor, I'm looking at what other kinds of things can we open. Currently, we can open applications, documents, and URLs, and we can do that through various methods, such as the open menu command in the finder, single clicking a URL, double clicking a document, and then there's drag and drop.

Drag and drop is something that you can do with documents, but you can also drag content out of an application window. You can drag a URL out of an application window. And wouldn't it be nice if we could do something with that in the doc? And in order to really help you understand, I'm just going to show it to you.

I've done this demo a couple of times now for various people at Apple, and a common reaction is, "Can't we do that already?" And that's very promising, very... I like that reaction because it means it's a natural thing. And amazingly, all the stuff I'm about to do, we can't do in Panther, in 10.3.

So, I'm in mail, and my friend Keith has sent me an email, which I want to take a look at. It says, "Chris, did you see this morning's news about Spaceship One?" This was last week. No, I hadn't seen the news about Spaceship One, but I'm wondering what he means. Then I noticed Keith's kind of a knucklehead. He put the URL up in the subject line.

You know, mail doesn't expect a URL in subject line, so it's not a live link like it would be in the body. And invariably, this happens, right? You get into some context where there's not a live link, and you've got a URL, and you have to copy it out onto the pasteboard, go to a browser, paste it in, press return to get there. And it would be much smoother if we could just grab that URL and drag it down, say, to Safari, and have it open the URL.

So, it's much faster. And it got me here to this article about Spaceship One, the first privately funded spaceship to leave the atmosphere. And that's pretty cool. And there's some info about the first successful test flight and some photos. But I really actually would like to get to the Spaceship One official website. And I'm wondering if there's any way I can do that. Well, maybe I can grab this and drag it down here. But that's not a URL, so what does Safari do with it? Well, it does a Google search on it.

Christopher Linn And the first... The first hit here is the SpaceshipOne homepage. So let's go there and see what we've got. Here it is. They've got a bunch of information about the spaceship and the test flight. And let us, oh, there's some photos.

[Transcript missing]

I kind of would like to get a closer look, so I'm gonna grab that photo and drag it down to preview and drop it on preview.

And I get a new window here in preview. Whoops, switch back to preview. And that's kind of useful because I can zoom in. I'm not really getting more resolution, but I can see it a little bit better and I can grab it around. So it was just a nice, simple way to get an image into another application. Maybe I wanna save it at this point, or I could even drag it into an image editor.

Let's go back to the website. Here's the press release page. Here's their press release for announcing their first successful flight. Maybe I want to send that back to my friend Keith. I'm going to do select all and grab that and drag it down to mail. I get a new message ready to be addressed to mail. It doesn't have the image yet, but we're working on that. As you can see, this is all very natural gestures, saves time, and it really leverages the dock as a great drop destination.

Now I get to one of the coolest parts about this is that I didn't have to change those applications except for preview. I made no changes to those applications to make that demo work. I added about five lines to preview in order to allow it to accept the drop.

But otherwise, Mail and Safari were already set up to do this, and you wonder, how can that speed? The way it works is that we already have a very well-established mechanism for working with data on the pasteboard coming from another application, and that is the Services menu. Applications in their InfoP list can declare services, and they show up under the application menu, say for mail. You can select some text, go to the Services menu, and you see a bunch of services offered by other applications that operate on text, for example. Amen.

This is really then just a new way to invoke a service. So we're integrating existing technology with the doc, and this is the details of how it works. Some of the details, I guess. We do use an Apple event in order to send the data between applications because we want it to be all asynchronous.

And so there's the new Apple event, KAEOpenContents, or Ocon, and it... is very similar to an ODOC event, except instead of a list of document references, it's a list of data items, of AE desks. And each desk contains the data to be opened. So when I drag that image out of Safari down to preview, we created an Ocon event, we stuffed the entire image into the Ocon event, and we very efficiently moved it between processes, delivered it to preview. But preview doesn't have an Ocon event handler, and none of those applications have an Ocon event handler. You can choose to handle the Ocon event directly if you want, or you can allow Launch Services to handle it for you.

And what Launch Services does in Tiger is it installs a system default handler for the Ocon event. And when an Ocon event goes unhandled, we look at the current application's list of services, and we look to see, is there a service that the app provides? Which can handle this type of data? And if there is, we just invoke the service. So if you adopt services, not only will you appear in the services menu, but now you will also be able to have the service invoked as a drop target on your application icon.

We'll also integrate this into the Finder for dropping things in the Finder as well. That is, dropping things on application icons in the Finder. And that might be it. Oh, one more slide. So, some of this I already went over. You add a services declaration to your P-list.

I'm going to share some of the tips and tricks I use to help you understand how to use Ocon. You can be a little more creative than that if you wish. Safari was a good example there. It got some plain text. It was able to take that and figure out that it should do a Google search on it because that's the most logical thing to happen. So feel free to be creative.

So what are the main points I want you to take away today? They are the following. Uniform Type Identifiers are used much more widely in Tiger than they were on Panther, both in Launch Services, Carbon Pasteboard, what else? The new Translation Services Carbon API. We have plans in Tiger to use them in Navigation Services for filtering, and Cocoa has plans to adopt them more widely also in its API. Spotlight organizes metadata around Uniform Type Identifiers. It's a great foundational technology on the system. We have new API for setting handler preferences. Use them, don't abuse them.

We have new LS Open functions with a bunch of features that you guys have asked for. Please try to follow our new guidelines for opening things and help us maintain security on the system. and finally, using services now with integration with drag and drop gives you a great new kind of portal into your application, increasing the value of your application to the user. And I am done now. I think we have one more. I asked documentation.

We have some documentation now on Uniform Type Identifiers. It was just finished a couple of weeks ago, and it's available on the WWDC Reference Library site. And also, it didn't make the DVD, but I encourage you to read the release notes, also the Launch Services release notes. Not everything you've seen is implemented yet. And so, it's good to read the release notes before you get frustrated. We're going to get it to you as soon as we can.