Application Frameworks • 50:18
Go in-depth on how to embed Safari HTML rendering capabilities within your Mac OS X application and customize its behavior. Details are provided on how to change locations, manage contextual menus, show progress indication, and take advantage of history and page caching.
Speaker: Richard Williamson
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good morning. Thanks for coming out at 9 o'clock on Friday morning, especially after the beer bash last night. There's one point of order I'd like to just mention before we start. The network's down. Apparently over in Moscone, they cut through the OC3. So no network today. We have a few backup strategies, and I hope they'll work, but please bear with us if there are a few glitches during the demos.
So there have been several sessions on the WebKit technologies at the conference so far, and you've probably seen overviews about WebKit and Safari and how Safari uses WebKit. What I'm going to do in this session is drill down a bit into the WebKit APIs and show you a few specific features and some code demos to explain how to use WebKit.
As you all know, Safari was a great success, and we're going to bring that success to you through WebKit. So what is WebKit? WebKit is a framework that's installed on your system when you install Safari 1.0, and it's also included with Panther. And it allows you to embed web content: HTML, images, plugin content like QuickTime, Java, Flash, and it entirely encapsulates the open source engine. Now I want to drill down into a demo pretty quickly here. And like I said, no network connection. So we'll see how this goes.
Now, good demos tend to flow up the management chain. So some of the other sessions have shown you this demo already, the Codeless Browser. But I want to use this demo to illustrate some points. So I'm going to build the Codeless Browser for you. How many of you saw this demo before, the Codeless Browser demo? OK.
Do you want to see it again? Yeah, OK, OK. No? I'll try and move quickly and show you a few different things in this demo. So I'm going to launch Interface Builder and show you the new palette, the WebKit palette. And this palette has a single class on it, the WebView.
And this little rectangle, this deceptively simple rectangle, really is your high-level view into the WebKit. It's where the web content will be shown. What I'm going to do is hook this up to a text field using the normal--actually, let's skip the target action and go directly to the binding technology. So I'll create a-- I'm going to use the controller for the web view. And I'm going to bind the text field to the mainframe's URL.
And what this will allow me to do is keep the web view and the text field in sync as I navigate around a page. Now, one thing you haven't seen before is showing the favorite icon for a page. So in Safari's address bar, sometimes we show an icon for a URL. That's called a favicon. So I'm going to hook up a favicon for this demo. I'll place that in the window. And I'll bind that to the icon for the page. And then let's add some back/forward buttons.
and then we'll bind the back and forward buttons to the The Web Controller. So that when we know we can go back, they'll be enabled and disabled as appropriate. So that's pretty much it. Let me set the resize flags for these things. And then we'll test the interface.
And hopefully we'll have some degree of net connection so I can show you Some of the capabilities of WebKit. Let's go ahead and test this interface. Now, what I'd like to do is attempt to access this local web server. that we just set up five minutes before the presentation. And let's hope that it is running.
So I'm going to just cut and paste the URL directly out of Safari into-- There we go. Woo-hoo. Worked. Forgot to set the resize flags on the text field. So let me go ahead and just do that. So that's a quick overview of the high-level capabilities of the WebView.
Now, I'd like to ask somebody to come up on stage. We're going to attempt to use a modem to connect to the World Wide Web. So you may not see the speed of -- What you're used to with Safari, but at least we'll get some external connection to the web.
So, slides please. Could you switch to the slides please? slides? Cue slides? Thank you. So I'm going to recap the design goals, a few of the design goals of the WebKit. Some of these you may have heard before. First and most importantly, we wanted to support a world-class web browser, and we think we've done that with Safari.
Secondly, and very importantly for this discussion, we wanted to support embedding. So that's what the WebKit's all about. And you get the same benefits that Safari has in terms of high performance: small footprint, fast loading, fast rendering, and excellent standard support that Apple is really committed to continuing to enhance and extend and, very importantly, too, a simple and flexible API. Now, you've seen how simple it is, but often simple means limited and inflexible. We think the WebKit API, even though at the surface level is very, very simple, it provides you with enough hooks to really extend and customize as appropriate in your applications.
So I'm really going to focus on this design goal, embedding, for this discussion. This is a high-level overview of the architecture of WebKit, and it illustrates how WebKit entirely encapsulates the open-source internals of WebKit KHTML. And we depend on a few key system frameworks: the AppKit for native Cocoa widgets, Core Graphics for hardware-accelerated rendering, and Foundation for fast URL loading. Now even though Apple focuses on the WebKit in terms of its API, we are committed to extending and enhancing KHTML. Now, laid above this is a C API that facilitates using the WebKit classes and technology in common applications.
So as you already know, probably, the WebKit is based on KHTML, and the WebKit is an umbrella framework. And embedded inside the umbrella framework are two sub-frameworks, WebCore and JavaScript Core. As you know, probably, at this point, they're open source, and they include Apple's work on KHTML. Now, a really important point is that we're not supporting the WebCore API, which you can see if you download the WebCore table. We're not supporting that as a public API. It will change in the future. So instead, use the WebKit API if you want to embed this technology in your applications.
So I'm going to focus on these key concepts when I talk about the WebKit now. Now, this isn't the only set of functionality provided in the WebKit, but if you understand these four basic ideas, you can really start to use the WebKit. Views -- that's how things actually get rendered on screen. Web frames, which is how we represent an individual frame. How you get data into the WebKit. And finally, the delegates, which is our mechanism for extending the API.
So for the next few slides, please keep this diagram in mind. This--I'm going to come back to this so you don't have to understand it all right now, but this is where we're going to go for the next few slides. These are the classes and the relationships between the classes that we're going to talk about.
And to talk about the classes, I'd like to use an HTML document, a really simple document on the left side of the screen. On the right side of the screen, I'm going to talk about the classes that represent the various different aspects of that HTML document. So first up, WebView, which you've seen already in the Codeless Browser demo.
It is the rectangle that will show you the content that's represented by your web page. Now, web pages are a little bit more detailed than simple documents. Web pages can actually be compound documents as represented by a frame set. So in this case, we have a really simple frame set with two subframes. We represent a frame with a class called WebFrame.
Now, there's not a one-to-one correspondence between a web frame and an HTML frame or an iFrame. We use a web frame even for frameless documents to represent what we call the mainframe. So a web view will always have at least one web frame, the mainframe. In this particular example, there are three frames: the mainframe, and a web frame representing A.html, and a web frame representing B.html.
WebFrames, in turn, have two pieces, what we call the Web Data Source and the Web Frame View. The Data Source holds the data, the actual bytes that represent the document or the image, whatever else is being shown in a Web Frame. And the Web Frame View is the piece that does the rendering.
There's a little bit more detail. So web documents can actually be various different data types, various different MIME types can be represented in a frame. In this case, an HTML document and a JPEG. So for each different MIME type that can be shown in a web frame, we have MIME type specific classes. These are actually protocols that are implemented on private classes in WebKit. So the web data source has a web document representation that's MIME type specific, and the web frame view has a MIME type specific view, the web document view.
So if you understand these core classes, you really understand WebKit. Again, this is a summary of the classes and the relationship to each other. You see we have the WebView, and underneath the WebView we have a hierarchy of web frames that represent the frame set on a page, or the iframes on a page, or even just the main frame of a document.
So how do you get data into the WebKit? Well, we use the new Foundation URL loading mechanism, and there was a great talk on that yesterday. I hope you had a chance to see that. And the two key classes that show up in the WebKit API are the NSURL request and the NSURL response. The request represents a response to go get data, and the response is the reply once you receive that data. The session on this has already happened yesterday, but I encourage you to go back and look at it on DVD.
So how do you initiate a load? You initiate a load on a web frame. Typically what you'll do is get the main frame off the web view and tell that to load data. And you can load data in one of three ways. You can use a request. Typically if you're going to go and get a resource off the web, you'd use a URL request. You can specify string data. You can actually create a little HTML page and place that right into a web view.
Or alternatively, you can use NSData. And you could even, for example, provide image data, raw image data, to a web frame, specify the MIME type, and we'll correctly decode that and do our best to render that image. And of course, all aspects of loading at the frame level can be monitored.
So not only can web pages be compound documents, but a single web page typically has many sub-resources-- images, CSS, JavaScript, We even consider subframes resources in a certain sense. Now, these resources are loaded automatically for you. You don't have to do anything to have WebKit load resources for you.
It happens behind the scenes. But you can, if you wish to, monitor the load of these subresources and even change the loading of these resources. You can redirect URLs to completely different sites. You can change the caching mechanisms. You have complete flexibility about how these subresources are loaded if you want to.
So I'd like to actually jump down into some code before we go back to another demo and show you how easy it is to create a web view. Now typically you would do this with Interface Builder. You wouldn't have to write this code. But if you want to, this is how you would create a web view. You simply alloc an initWithFrame like any other NSView and then add that to your view hierarchy, depending upon how your application is set up.
Then to load data, you typically get the mainframe of the web view and Create a request and then load that request. It's as simple as that. Alternatively, in this example, I've created a little HTML fragment. And the WebKit engine, the KHTML engine, is really-- is smart enough to understand fragments of HTML. So in this case, it's really malformed. There's not even an HTML tag. But the WebKit engine will still go ahead and render this correctly.
So one more code example before we jump to a demo. This is a little snippet that shows you how to extract the HTML source off the data source's representation once a document is loaded. So in this case, I simply get the mainframe. I get the data source off the mainframe.
I get its representation, which again is MIME type specific. And I ask that if it's capable of providing document source, because if it's an image, a JPEG for example, it won't be able to provide me with document source. I get the document source, and then I log it to the console.
So the demo I'd like to show you next highlights one specific aspect of the WebKit, which I think is really interesting and allows for some creative opportunities. Hopefully it will inspire you to think about different ways to use WebKit in your applications. So one thing we get asked a lot is how do I interact with the document? If I load a document in WebKit, in my application code, how can I change the document? How can I modify the DOM? Well, the way you do that is to execute JavaScript in the document's context. And a typical approach to this is in the content that you may display via WebKit, define a JavaScript function. And then from your application code, invoke that JavaScript function.
And as I said, you can use this to modify the DOM of the document in pretty creative ways. So this is a little code example that shows an HTML page with a JavaScript snippet that has a function to find an element on a page, in this case an image element, using the standard DOM API getElementById. And then it modifies the image width. Now, by default, when you modify one dimension of an image, both the width and the height of that image will change. So this effectively scales down the image.
How do you invoke that from your application code? This is how, with this little piece of Objective-C. I create a string that represents the JavaScript I'd like to execute, and then I simply tell the WebView, "Execute this string," and that will execute the JavaScript in the context of the document. So let's go ahead and do a demo of this.
Am I actually live on the net? Sure. Okay. Before we do this, let me try and show you another piece of the demo I would have liked to have shown you earlier had the net been up. And bear with me if it doesn't work. We're on a modem, and it's been a long time since I've used a modem. So who knows what the speed will be like.
Isn't it back by the way? Are we? No, we're not? Okay. So this is a site that I don't know if you've been to, brainjaw.com. And is it going to load? I don't think it's going to load. Okay, so give it a few more seconds. Loading, loading, loading. No, we're not going to get to see anything there. So let me -- Exit Interface Builder. Okay, how about we force quit Interface Builder? Time to move on. Force quit. Bye-bye. Okay. So let me bring up a project in Xcode.
[Transcript missing]
So let me go ahead and just show you the content that I'm going to display here. This content's kind of interesting. It's three divs, and they're layered, and one of the divs has a transparent image in it, so you can see this nice transparency. Gives you a sense of some of the advanced features of our engine.
Now what I'd like to do is add a couple of buttons to this window. And when I click those buttons, I'd like to zoom the picture of the spider. Now this spider happens to be the mascot of the Safari team before we had the nice compass. We used this internally for a long time. So let me go ahead and add those two buttons in Interface Builder. I'm going to shrink this window a little bit. And I'm going to add a button to zoom in. Don't need the capital N. And a button to zoom out.
Then we'll go ahead and connect these. Zoom in and zoom out. And what I'm connecting these to is just a simple custom class that's been instantiated. It's called Zuma. Now let's write these methods that we've just connected. Zoom in and zoom out. So I'm going to go back to-- let me just save that.
I'm going to go back to Xcode and bring up some source code. Now this is a pretty simple class. Hello. Okay, let's try bringing that up in the next little window. So the first thing this class does is-- and it's awake from Nib method-- is it loads the template that we're going to display for that HTML document. And this just uses the normal Cocoa bundle and string functions. So then we go ahead and invoke the mainframe load HTML string to load that template.
Let me just show you the document really quickly that we're going to load. This is simple HTML that has some styling, has some script, a zoom in and a zoom out method. And this is the image element that we're going to reference. Backup in our JavaScript when we change the width and height.
To add the zoom in and zoom out actions, I'm going to scroll down to this code and just enable it. You can see it's pretty simple. I have the web view. String by evaluating JavaScript from string. Zoom image in, and I pass in the name of the image element that I want to find and invoke it. So let's go ahead and build.
And once it's linked, we'll run it. I guess I have to quit it first. There we have it. I forgot to set the resize flags again, but I can zoom in, zoom out. And of course, you can use the same technique to modify any aspect of the page. It's not just limited to this particular feature. So what I'd like to do now is to--let me just clean up a little bit and then go back to the slides.
So we've covered the important classes of the WebKit: the WebView, the WebFrame, the DataSource, the FrameView. The next really big set of important functionality are the delegates. And unlike most other Cocoa delegates, where there's one delegate per class, we actually have four delegates per class, per web view, I should say.
And this is how we control most aspects of the WebKit. Each delegate can implement methods that are defined by an informal protocol. And for those of you that aren't familiar with informal protocols, this is really just an interface with methods that may be optionally implemented on your class.
And again, I emphasize optional because you don't have to implement any delegates to make WebKit work. It's only if you want to customize behavior. And as I mentioned, all of the delegates are managed by the WebView. So going back to our previous diagram, these four delegates fit into the web view like this. And I'll come back to this diagram again, but this is where we're going.
Those four delegates are the WebFrame load delegate. It monitors the progress of a document load at the document level. The Web Resource Load Delegate, and it will let you look at each individual image and CSS file and JavaScript file as it loads. The Web Policy Delegate, which gives you a great amount of flexibility about how you want to manage link traversal.
So the user clicks on a link, what happens next? The Policy Delegate will let you handle that. And the Web UI Delegate. The Web UI Delegate is responsible for managing all of the Chrome related to a window, and also the window itself, as well as handling JavaScript interaction for things like status and alerts.
So when you load a document over the web, it's actually a relatively complicated process, or detailed process, I should say. And at the simple level, it's described by these four states. You start loading a document. We have this notion of a document being committed, and I'll come back to that in a second. The document finishing loading, or it's being done, and then finally the document going away, being closed.
Now what's this committed thing? Well, The web tends to be error-prone. So typically, if you initiate a load of a document, and for whatever reason the server doesn't respond, we don't get any data back, That document isn't committed. It's really a provisional load until you reach this committed stage. It's only once we receive some data back from the server that the load becomes really valid and you can progress to the next stages. So this notion of provisional and committed really is very important during the loading stages of a document.
Things get even more detailed, though. Before you can get to the committed stage, often a server may redirect you to an entirely different site. So you enter one URL, and the server redirects you to an entirely different location. And we'll give the frame load delegate an indication when this happens. And this can happen one or more times.
You can get redirected to several servers before you get to the final page that's going to be shown. There's yet more detail. So to provide good user feedback during a page load, what you'd often like to do is show perhaps the page title or the favorite icon. So we'll give you delegate callbacks when we receive that information.
And then finally, even after a document is loaded, the user might want to navigate to a link within a page, an anchor point within a page. So we'll tell you when that happens. And finally, the last notification that the frame load delegate receives is if a client redirect happens. For example, it might be a meta-redirect on a page. And that you might be redirected to another site entirely. Or perhaps JavaScript might change the location of a page. So all of these events are sent to the WebFrame load delegate.
Now, the Web Resource Load Delegate is, again, the delegate that receives messages about loads of images, CSS, JavaScript. And it has these four set of methods that are sent to the resource load delegate. When we send the initial request, and at this point you have an opportunity to look at the request, modify it in whatever way you choose, including canceling the request entirely. You can add headers, you can change the URL, you can do whatever you want.
Then you receive a callback telling you that the server has responded. And again, you have a chance to look at the response. And for those of you that are familiar with the NSURL response and request APIs, this should be very familiar to you. Then after the response, you get a number of callbacks for each data packet that we receive from the server. In fact, you may receive multiple of those, depending upon how the server responds. And then finally, when the resource is finished loading, you get a done message.
The policy delegate. This delegate's a little different than the other delegates. The other delegates mostly are just callbacks to tell you about things happening. The policy delegate actually asks you a question: "What should I do when navigation happens? Tell me how I should respond." And the response can be asynchronous.
So you can put up modal dialogues, wait for user response, and then tell WebKit how to continue. And for each of the methods that we send to the policy delegate, there are three possible choices. Go ahead and use it as you normally would, the default policy. Ignore it. Stop whatever you're doing. Drop this load on the floor. Or download. Download the URL to disk.
So the policy delegate is consulted at least three times during the document load. Initially, it's asked, "Should I open this URL in a new window?" And if so, the UI delegate comes into play. Remember, it's the thing responsible for managing windows. Should I go ahead and handle this request? This gives the policy delegate a chance to look at the request details, potentially present the user with a dialogue like, "This is an HTTPS request.
Do you really want to do that?" And then finally, based on the MIME type that we receive, and this happens after we send the request, we get the response back with the MIME type, what should I do with the MIME type? This may be the location, for example, that you hand off a request to launch services to handle opening the request externally.
UI delegate. The UI delegate is probably the fattest delegate in terms of the total number of methods. And is responsible for all of the Chrome. So in Safari this is the thing that opens up a new window. It manages the status bar at the bottom of the Safari window. It manages the toolbar at the top of the window. And it presents JavaScript alerts. And this allows you to modify the context menus. So if you control click or for those people with two mice, right click on an element, the UI delegate is referenced.
So back to this diagram. This is what we've covered so far: the classes, the core classes of WebKit, and the delegates of WebView. The WebFrame Load Delegate lets you monitor the load at a document level. The WebResource Load Delegate lets you monitor loading per resource. The WebPolicy Delegate, which lets you intervene to manage navigation actions. And the WebUI Delegate, which lets you manage the UI Chrome. So I'd like to go back to a demo.
Oh, are we back? Exciting. Oh, it's modem, it's just modem. Oh. Okay. Well, let me take a step on the wild side and try-- OK, just in Safari. I want to show you this page because I think it's really cool. I'll do it in Safari, but remember, that rectangle in Safari is the same rectangle that you would see in WebKit. So what you can do in Safari, you can do in WebKit. And this demo highlights some of the amazing things that you can do with modern web standards. This is just simple HTML and JavaScript.
Pretty cool, huh? Minimize windows, expand them, close them. So think about this when you're thinking about WebKit applications. It's not just for web browsing. You can use the power of HTML, CSS, and JavaScript in marvelous and creative ways that we can't even anticipate yet. I think that there will probably be 20 browsers on version tracker in the next few months. But we think Safari is pretty good, and I'm sure there are going to be other good browsers out there. But think about other ways to use WebKit.
Okay, back to the demo. So what I'd like to do is go back to the image zoomer demo and add a context menu. So I had buttons at the top of the screen to zoom in and zoom out. What about using a context menu to zoom in and out on that image, but only when I mouse over an image? Let's do that.
So I'm going to bring up the source again for the image zoomer. And the first thing I need to do is set up A delegate. And I'm going to just add that code. up in the wake from nib method. It's as simple as that. I'm setting self as the UI delegate.
And then the one method that I care about for this demo is the method that lets the UI delegate specify The context menu. So in this case, if you're familiar with Cocoa, you'll be familiar with this code here. And the expected response of this method, WebView context menu items for element, default menu items, is an array that contains the menu items that are going to be shown when you context click on an item. So in this case, I only care about Image URL Keys. So if the click is over an image URL, I'm going to go ahead and construct two menu items, zoom in and zoom out, and return that array.
Otherwise, I return nil. So we'll get no context menus unless the user right-clicks on an image. Let me go ahead and build this. Save all files, yes. Build. And then once it's linked, we'll go ahead and run it again. So, zoom in, zoom out, buttons, but now if I hold down the control key, I have a context menu. Zoom in, I get the same behavior. Zoom out. Simple as that.
So this is an interesting demo, but it's somewhat contrived. Would you ever really want to do this? Probably not. But the same technique can be used in an application that's actually on the SDK, which is useful actually as an application in its own right. I'm going to show you that application now.
And the entire source code for this application is available on the SDK. Let's go ahead and hide others. Richard Williamson And this is a browsing application that lets you browse pictures. And I often use this when I'm trolling for icons to use in my applications. So I'm going to open up the applications directory. And on the left side of the screen, we see a list of the applications, kind of like a finder. And I can drill down into -- let's take a look at iPhoto.
I can drill down into --
[Transcript missing]
It's really useful for looking at images. So if I can even zoom in, click back and forth, and you get a lot of the features which I'm not going to talk about today, like back and forward and history. These things are relevant for applications other than web browsers. So if I go back, you know, I really set up a nice little back-forward. Let me show you some pictures that I took this weekend at Oakland Zoo.
This demo actually makes use of a custom protocol, believe it or not. The URLs for these pages aren't HTTP or file URLs. They're a custom protocol, and that protocol is interpreted to generate on-the-fly HTML content. As I click on a link, this is actually what I call a picture browser protocol that lets me generate the wrapper HTML for this particular content. So I encourage you to take a look at that application for tips and techniques about how to use WebKit.
There's one more demo I'd like to show you. And this is, again, a demo that is available on the SDK. The full source of it is available on the SDK. And this is more of a traditional browser. It really tries to show you the capabilities from a browser perspective.
Let me fire up this. It's called the mini browser. That's the name on the SDK. Let me go ahead and run it for you now. And I guess I'm still on the modem, so speedy Safari isn't so speedy on a modem, but it's still pretty good on a modem. So I have a lot of the features that I normally expect. I can -- You know, make text bigger, if there is any text. On this page, there isn't too much text. Smaller.
Now, one thing you'll notice though is that I don't get a lot of feed--oh, this is actually good. A slow link, I can show progress feedback better because it takes so long to load. So if I go to another page, take a look at the title bar there.
This is loading. Loading, loading, loading. We've got the title, but I'd like to provide a bit more feedback, maybe a counter that shows me the number of resources that are loading. One of 40. That would progress as I load additional resources. And at least it would give me some idea that the page is still loading. That's actually pretty good on a modem. Okay. So let me go ahead and add those features.
So what I'm going to do to enable these features is extend the document for the mini browser to be a resource load delegate. Remember, the resource load delegate is the thing that gets notified as resources arrive over the net. And I think there'll be some code down here. Yeah, look at that. Okay. Let me cut and paste this code again. And I'm going to set up the document as the resource load delegate.
Now, there's actually more than just one method here to do this. You enable this code, and I'll just talk you through the code. We don't need that. That won't compile. So the first method is identifier for initial request. Now, why do we need an identifier? Why can't we just use the request? Well, requests can actually change. They can mutate. They can be redirected.
And what you often want to do is identify the notion of a resource independent of those redirects or modification of the request. So the identifier will remain constant throughout a resource load, even if the request changes. So you can use this kind of as your own tag to track a particular resource load. And in this case, we're just going to allocate an NSNumber. It can be an arbitrary object, whatever you want. WebKit doesn't care about the identifier. It just lets you specify it.
So then you get notified that we're about to send the request. We'll send request. And at this point, you can modify the request, change it in whatever way you choose. And there's a lot of flexibility here. Change the caching policy. You can add headers. You can disable cookie management. Whatever you want. You can really modify the request.
So what we're going to do is just update the resource status. And I'll show you this method in a second. But it really just modifies the title of the window. And then we return the same request. So we let WebKit go ahead and handle it as it normally would.
Next method, Git fail loading with error. It sent you, if there's an error, and you're free to do whatever you want with that error. And the error object, it's not just a code, it's a fully-fledged NSError object. It has a localized description. You can present that in a dialog box.
What we're going to do is just count, increment a counter to indicate that the resource failed. And again, we're going to update the title bar with that update resource status. You get this message, "Did finish loading from data source," when the load completes. So let me just show you the update resource status.
method. All it's going to do is, if there's a failed count, it's going to construct a string and tell you about those errors. If there isn't a fail count, it's going to just construct a string that says, "Loaded X of X," or "X of N." Let's go ahead and build this. Which build button should I click? This one or this one? Okay, save all.
So many options to build. Did it build? There we go. Okay. I'm still running. Okay, so now, take a look at the title bar. Loaded 41 of 41. It's amazing the number of resources on some of these pages. Let's just go to a couple -- oh, look, two resource errors.
So -- oh, and the other thing that was interesting, you might have noticed that the total changed. That's because the number of concurrent loads actually, you know, may change over time because the WebKit loads images as it encounters them as it passes a page. Okay. So that's the mini-browser demo.
So the last topic I'd like to cover in the remaining minutes is the C API. And the WebKit is an Objective-C COCA framework, no doubt about that. But we've gone to some effort to make the same technology available via Carbon applications. And the way we've done this is to create an HI view that actually really is backed by a WebView. So you can use the WebKit technology in your Carbon applications. But if you really want to drill down into some of the advanced features, you will have to write Objective-C or Objective-C++.
This is a little C snippet, code snippet, of how you would construct a web view using the C APIs. You simply create it, HIA web view create. And then the next few lines of code will just modify the frame of the web view to correspond to the content view of the main view of your window. And then finally, you add the web view as a sub-view of the root of your window.
So what I'd like to do now is to show you a demo of a few of these Carbon applications. Now, in the SDK, we have full source code for the Carbon web, browser, which is a Carbon application, and It isn't just a simple Carbon application. We've actually done a lot of code to provide adapters to Carbon events.
So you can use this as a model for how to interact with WebKit via Carbon events. And I encourage you to take a look at the source code for that.
[Transcript missing]
and Vsource. But the source actually gets logged to the console, not in a separate window. And the other demo that I'd like to show you is the Carbon Downloader. And this uses actually the foundation APIs to download a URL to the desktop.
[Transcript missing]
And one final note about the SDK. It does work on 10.2. In fact, the SDK is designed to be installed on 10.2. So you must first install Safari 1.0 and then the SDK on top of that. And I gather there are some problems installing the SDK on Panther. So what you can do is just copy the headers from -- no? The headers are okay. The headers are okay. Yeah, I was wrong. On Panther, you don't have to do anything. You get the SDK built in.
And as I mentioned, there are several examples that are quite comprehensive in the SDK, and there'll be more to come. And if there's anything in particular you'd like us to see or like us to write for you as examples, please let us know. It also includes conceptual and reference documentation that's pretty comprehensive, and it's available now, actually as of Monday, I believe, for download from ADC.
For more information, you can look at the ADC website. There's actually a number of topical tech notes on there. One of interest is, how do I detect whether or not the SDK is installed? So for example, if I want to build an application to depend on this technology, how can I know that my clients actually have WebKit installed? So there's actually a little code sample that shows you how to do that, which is, I think, pretty helpful.
The WebKit reference for Objective-C, the WebKit reference for C, and the URL loading material is also up there. The HTML, CSS, and JavaScript technologies are great for webkit. I encourage you to look at these great books for more information about those technologies. and contact John Glancy for any questions. So I think that's it for the slides. So Q&A.