oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

BYOB: Build Your Own Browser, Part 2

by Andrew Anderson

Editor's note: Back in a distant time and galaxy, we ran a nifty article titled Build Your Own Browser where Andrew Anderson showed you the basics of WebKit. It was an introduction to a multipart series (some of the TalkBacks in that first article bemoaned its simplicity, wanting to get to the more advanced stuff). Then, to add fuel to the conversation, Andrew got hit with a big project and the second installment was delayed. Now I have both Parts 2 and 3 in hand. Today's installment picks up where we left off previously, plus includes a discussion about Safari and WebKit security. Next Friday I'll run Part 3, where Andrew shows you how to create a preference window and content eliminator.

The wait is over and the second installment of "Build Your Own Browser" (BYOB) is finally here. The first installment focused on using Interface Builder to build a simple browser without using any code. The browser was functional but lacked many of the features that are available in modern web browsers. The next two installments will make our browser more powerful by using some of the more advanced aspects of WebKit to integrate three new features into our browser:

  • Multi-window capabilities
  • Preference window
  • Content eliminator

This week's installment will cover multi-window capabilities. Both installments differ from the previous article in one significant way. While they do run through tutorials for all three new features similarly to the first article, each leaves hints and tips on how to add additional features, instead of explicitly defining them. This is both to keep the series to a readable length and also to allow readers the ability to develop their own unique features. I've also included some information on WebKit security issues and other sites, which might be of interest for browser developers. I'm going to start with that because it's topical at the moment, then get back to adding features to our fledgling browser.

Safari and WebKit Security

Ask any users of Mac OS X and they will say that "OS X is way more secure than Windows," and then they will tell you that they've never had a virus, Trojan horse, or other security problem with their OS X machine. While OS X is more secure than Windows (Richard Forno has an in-depth article on it ), it is naive to assume that "more secure" is the same as secure, or even worse "more secure" is sufficient to protect your computer. In today's networked world, where your Mac OS X machine is connected 24/7 to the Internet, security is the exception, not the rule.

Web browsers are notorious for having security vulnerabilities that can wreck havoc on your system. The problem is that browser users want whiz-bang features like JavaScript, MIME handlers, Plugins, and Java, but these features have the potential to open up any number of security holes and vulnerabilities. Sometimes the vulnerabilities are because of stupid design or implementation; more often than not though, they are the result of some sort of complex interaction between scripting languages, helper applications, and browsers that even the best developer could be excused for not anticipating.

Our simple browser is more secure than most browsers because it does not implement a lot of functionality that can break. As we add more features to our browser though, we need to keep track of not only our own code, but also any security issues in WebKit. Sounds easy enough, right? Nope, the problem is that users, not developers, find most security problems and users don't know what WebKit is. Since Safari is based on WebKit, the easiest way to keep track of WebKit security issues is to stay informed of Safari security advisories.

Safari security advisories in the past have been few and far between, but a few have surfaced lately, including a recent serious issue involving Safari's interaction with Apple's Help system. It ends up that, given the correct parameters, you can get Safari to open Help and then Help will open any specified application. It is easy to think that this bug is a problem with Safari and Help, but really this affects any browser setup that supports AppleScript and the Help system, including anything based on WebKit.

In its current state, our browser does not suffer from this problem because we have not added support for Help (via its MIME type and/or the Download delegate), but if you plan on expanding the browser, you need to watch out for issues like this one. Fortunately, once Apple caught wind of this bug, it fixed it quickly (although there is some debate on how quickly), and the fix is available in the latest security updates.

Apple's fixes are available for 10.2 and 10.3.

For more information on the bug and a simple script that exploits it, check out the overview at François Nonnenmacher's site.

OK, now with that bit of business out of the way, let's get back to enhancing our basic browser.

Multi Windows

Our application is pretty limited at this point; basically, it's a single window in a single frame. And while it can load complex pages and lay them out correctly, it leaves plenty to be desired in terms of functionality. One important piece of functionality that's missing is the ability to open multiple windows at the same time.

In order to achieve this feat, our browser is going to have to be a Cocoa Document-based application. Currently our project is a simple Cocoa Application, which means that we will have to convert our old project into a Cocoa Document-based application. The easiest and most elegant way to do this is to create a new project that is Document-based and copy the relevant parts of the old project to it.

Start by launching Xcode and creating a new "Cocoa Document-based application" project. When Xcode is finished creating the project, the next step is to add the WebKit framework. To do this, go to the Other Frameworks folder under Frameworks folder in the main project section of the new application. Go to the Projects menu bar and choose Add Framework. In the dialog that pops up, find the WebKit framework and add it to the project. The WebKit framework generally resides in "/System/Library/Frameworks/WebKit" and is surprisingly named "WebKit.framework". If you can't find it, check out the original article for instructions on downloading and installing the framework.

Changing the UI

Now it's time to add the original user interface from the old project to the new project. Since our original project was not a document-based application, the user interface was built in MainMenu.nib. In the new project, the user interface for the browser functionality will be built in MyDocument.nib. MyDocument.nib is the file that Cocoa uses to create a new user interface each time a request is made for one. To get the new browser to function like the previous version we need to copy the UI elements in MainMenu.nib to MyDocument.nib.

Copying the UI elements between MainMenu.nib and MyDocument.nib is fairly easy, load both files in Interface Builder and copy the contents from MainMenu.nib to MyDocument.nib. The easiest way to do this is to load both the original and the new project in XCode. Once they are both loaded, double click MainMenu.nib from the original project and then MyDocument.nib from the new project, which will load both NIB files in Interface Builder. Once in Interface Builder, go to MainMenu.nib, select all the UI elements, copy them, then switch windows to MyDocument.nib, and paste the new elements into the window. The last step is to save MyDocument.nib and close MainMenu.nib.

After the UI is built, we need to add connections so the code that we'll develop later will be able to access the UI pieces. When dealing with Cocoa Document-based applications, the connections are made between the "MyDocument" window instance and the "File's Owner" instance. "File's Owner" is a proxy for the "MyDocument" object that corresponds to individual instances of the class. The need to make a total of three connections between "File's Owner" and "MyDocument": two outlets, one for the webView and one for the URL text line; and one action from the URL text line to alter the document for when the value is changed.

To start, we need to choose the MyDocument class in the Classes panel of the Interface Builder control panel (it is a subclass of NSObject). Once MyDocument is chosen, go to the "Classes" pulldown menu and choose "Add Outlet to MyDocument." An information window will pop up; make sure that it is on the "Outlets" tab and add two outlets: "webView" with type "WebView" and "urlString" with type "id." Next switch to the actions tab and add an action named "connectURL."

Now that the outlets and actions are set up, it's time to connect them to the "File's Owner" instance. To connect the outlets, go to the "Instances" tab of MyDocuments.nib, choose the "File's Owner" instance and Ctrl-drag a line to the text field on the user interface. The info window will appear on the connections page, where you should select "urlString" under the "Outlets" tab and click connect. Next, do the same thing to connect the WebView instance to the webView outlet.

The last step is to disconnect the WebView's takeStringURLFrom action from the edit field and reconnect the edit field to the connectURL action that we created before in "File's Owner". To disconnect from takeStringURLFrom, choose the text input field and Ctrl-drag a line to the WebView on "MyDocument"; when information window pops up, choose the "Target/Actions" tab, then click on "takeStringFromURL" and click on the disconnect button. To reconnect the text input field to the "File's Owner" instance, Ctrl-drag a line from the text input field to the "File's Owner" instance, choose the "Targets/Actions" tab, and click on connect.

Once that is all hooked up, save the NIB file and quit Interface Builder. It's time to edit some code!

Pages: 1, 2, 3

Next Pagearrow