File:  [mozdev] / books / www / articles / roll_your_own.html
Revision 1.6: download - view: text, annotated - select for diffs - revision graph
Sun Sep 15 22:50:55 2002 UTC (17 years, 2 months ago) by brian
Branches: MAIN
CVS tags: HEAD
update of article sent to Derrick

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
                                    
  <meta http-equiv="content-type"
 content="text/html; charset=ISO-8859-1">
  <title>Roll Your Own Browser</title>
</head>
<body>
     
<h1> Rolling Your Own Browser</h1>
    The browser is dead. It is a two dimensional piece of software that is
 slowing  the evolution of the Web. Are you shocked by these statements,
reading this article from the comfort of your browser of choice? Well you
  should be because no matter what some people lead you to believe, browsers
  will be around for a while longer. The purpose of this article is to introduce
  you to the concept of customisating, or creating your own browser, and
how   you can do it with the wonderful toolkit that is Mozilla.<br>
     
<h2> Why your own browser?</h2>
    Before proceeding, it must be noted that the rest of this article focuses
on the technical issues involved in getting a XUL browser up and running
in the application framework. This is distinct from embedding Gecko, which
was discussed in a previous article on the DevCenter, '<a
 href="http://www.oreillynet.com/pub/a/mozilla/2002/09/12/mozilla_browsers.html">Let
One Hundred Browsers Bloom</a>'.<a
 href="http://www.mozilla.org/newlayout/faq.html">Gecko </a>is the Mozilla
layout rendering engine. The merits of having multiple browser projects has
been touched on already, so lets look at some of the practical uses that
an integrated browser can bring to your application, apart form the traditional
usage for web navigation.<br>
    <br>
<ul>
  <li>    Create some HTML or XML help pages for your  application  and load
them up in a ready made help browser.</li>
  <li>    Previewer &#8211; test your XML, HTML or CSS layout   and styling in
Gecko, one of the most standards compliant browsers around.</li>
  <li>    A slight variation of the previous use, you  could  have mini &#8211;
versions inline in dialogs to load up examples that will  change  depending
on the slection of the user from a number of choices. For  example,  a font
previewer.</li>
  <li>    Pop-up&#8217;s contained in a window for display of  web content</li>
</ul>
<br>
Of course, when you have the raison d'etre for your browser, you have to
start putting the pieces in place to get it up and running. This will take
the form of a full blown Mozilla application, complete with the XPFE toolkit
for building your own UI, or perhaps just an add-on to the existing suite
that can be distributed in the form of an XPI. The term XPI refers to Cross-Platform
Install, the native installer for Mozilla.<br>
         
<h2> The Widgets</h2>
To get you started straight away, lets look at two if the most straightforward
content widgets available in the Mozilla toolkit, namely the <i>browser</i>
and the <i>iframe</i>. These are marked up with tags of the same name, <span
 style="font-style: italic;">&lt;browser&gt;</span>and <span
 style="font-style: italic;">&lt;iframe&gt;</span>, and placed within your
XUL window or binding. Both are essentially designed for holding web content,
which can be anything from HTML and XML to just text and images in formats
recognised by Gecko such as jpeg, png, gif and bmp. Here is a look at a browser
in its simplest form:<br>
<br>
<font face="Helvetica, Arial, sans-serif"><small>&lt;?xml version="1.0"?&gt;</small><br>
<small>&lt;?xml-stylesheet href="chrome://global/skin" type="text/css"?&gt;</small><br>
<small>&lt;window id="browser-window" title="Simple Browser Widget Display"</small><br>
<small>&nbsp;&nbsp;&nbsp; xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"</small><br>
<small>&nbsp;&nbsp;&nbsp; width="640"</small><br>
<small>&nbsp;&nbsp;&nbsp; height="480"&gt;</small><br>
<small>&lt;browser src="http://mozdev.org" flex="1"/&gt;</small><br>
<small>&lt;/window&gt;</small></font><br>
<br>
The code to look out for here is the line with the browser tag which creates
a content area. It is the sole markup in the XUL window. It takes up all the
available space because of the flex attribute, and into is loaded the index
page of mozdev.org. This is the result, a window with web content.<br>
<br>
<div align="center"><img
 src="http://books.mozdev.org/articles/simplebrowser.png"
 alt="SimpleBrowser" width="640" height="480"><br>
</div>
<br>
<div align="center"><i>Simple Browser Window</i><br>
</div>
<br>
What is missing in the picture and the example code for it is some sort of
context. It is lacking an application space, and has no accompanying widgets
to carry out any complimentary functionality for the browser. In traditional
browsers, including the Mozilla browser that comes with the application suite,
there is a menubar and a toolbar, each containing easy access to functionality
such as Back, Forward, Reload, View Source, and so on. <br>
<br>
The <span style="font-style: italic;">&lt;iframe&gt;</span> widget is a more
lightweight version of the <span style="font-style: italic;">&lt;browser&gt;</span>,
yet is just as useful if your needs are just to display some somple we content.
It was designed to act much like the HTML iframe widget, to be an inner frame
within a document. It too has a <i>src</i> atribute to specify the content.
It is useful mainly for dislaying one-off content such as a preview of content,
or a results page.<br>
<br>
<small><font face="Helvetica, Arial, sans-serif">&lt;iframe class="results"
id="resultsframe" type="content" src="results.xul" flex="1"/&gt;</font></small><br>
<br>
Remember that XUL content can be loaded into the content areas, as for example
is the case in the Mozilla suite global preferences which has a right frame
into which the various preferences panels are loaded into when selected.<br>
<h2>The Script</h2>
    Let's look now at the source code that enables the initialization of the
browser. These are the basics to get some browser functionality working. I
find the best way to find out how Mozilla works is to look at the code. The
perfect way to do this is via <a href="http://lxr.mozilla.org">LXR</a>, the
Mozilla Cross Reference. The particular files you should be looking  at are
<a
 href="http://lxr.mozilla.org/seamonkey/source/xpfe/browser/resources/content/navigator.js">navigator.js</a>
and <a
 href="http://lxr.mozilla.org/seamonkey/source/extensions/help/resources/content/help.js">help.js</a>,
the main JavaScript files associated with the Browser and Help  windows respectively.
The following code is a generic way of setting things up but is based loosely
around the starting up of these windows and setting up of the browser. This
script is best placed in the function associated with the load handler of
the XUL window.<br>
<br>
The first step is to give the browser widget in the XUL file a couple more
attributes added to it.<br>
<font face="Helvetica, Arial, sans-serif" size="-1"><br>
&lt;browser </font><font face="Helvetica, Arial, sans-serif" size="-1">id="browser-content"
</font><font face="Helvetica, Arial, sans-serif" size="-1">type="content-primary"
<br>
&nbsp; &nbsp; &nbsp; &nbsp; src="about:blank" flex="1"/&gt;</font><br>
<br>
The <i>type</i> attribute is optional but in this instance is important because
it affects the way the content is treated in the application. The value of
"content-primary" means that this is the main browser content area (e.g.<small><font
 face="Helvetica, Arial, sans-serif">content.focus()</font></small>), and
should gain precedence over other areas. When you use the <i>content</i>
keyword in your script, it is the content in this browser that will be accessed.
The<i> id</i> attribute gives the browser a unique identifier within the
XUL content.This allows you to easily get a handle on the browser widget
from your script:<br>
<pre><font face="Helvetica, Arial, sans-serif">var myBrowser    // declare globally for re-use<br>myBrowser = document.getElementById("browser-content");<br></font></pre>
Next is to create the browser instance and set up browser window:<br>
<br>
<small><font face="Helvetica, Arial, sans-serif">var appCore = null; &nbsp;
&nbsp;// declare globally for re-use<br>
appCore = Components.classes["@mozilla.org/appshell/component/browser/instance;1"]<br>
            .createInstance(Components.interfaces.nsIBrowserInstance);<br>
appCore.setWebShellWindow(window);<br>
</font></small><br>
The browser is initially blank (the use of &nbsp;"about:blank" as the <i>src</i>
attribute), so you have to load some content into the browser. Here a http
URL is used:<br>
<pre><font face="Helvetica, Arial, sans-serif">const nsIWebNavigation = Components.interfaces.nsIWebNavigation;<br>myBrowser.webNavigation.loadURI("http://www.mozdev.org", nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);</font></pre>
This creates an instance of the <i>nsIWebNavigation</i> XPCOM interface, which
exposes a number if handy utilities for changing and navigating through the
content displayed in the browser. In this instance, to load a page, the<i>loadURI</i>
method is being used. Other methods of this interface include<span
 style="font-style: italic;">goBack()</span>, <span
 style="font-style: italic;">goForward()</span>, and <span
 style="font-style: italic;">reload()</span>. <i>nsIWebNaviagtion</i> is
just one of the interfaces available when you use the browser widget. Other
include:<br>
<ul>
  <li>preferences</li>
  <li>webBrowserFind</li>
  <li>contentViewer</li>
  <li>documentCharsetInfo<br>
  </li>
</ul>
A full list can be found in the <a
 href="http://lxr.mozilla.org/seamonkey/source/xpfe/global/resources/content/bindings/browser.xml">bindings
file</a> for the widget. These few steps provided in this section will send
you well on your way to getting a rich content browser set up in your Mozilla
application and act as a foundation for adding some of the other bells and
whistles associated with a browser.<br>
 
<h3>The Art of Navigation</h3>
What follows is a brief description of adding Back and Forward widgets and
functionality to your window. This is after all the basis of any reasonable
browser, but is used here to illustrate the process for hooking up functionality
to your browser. The XUL file is the place to define your UI buttons. If
you are proficient at XUL and CSS, you can make them into the style and appearance
that you wish, but in this example the current navigator styles (using the
Modern theme) are used.<br>
<br>
<div align="center"><img
 src="http://books.mozdev.org/articles/buttons.png"
 alt="Back and Forward Buttons" width="134" height="84"><br>
</div>
<div align="center"><i>Back and Forward Buttons</i><br>
</div>
<br>
These are simple toolbar buttons. The back and forward buttons used in the
Mozilla browser have an integrated menu that creates a list of pages that
are available for each one. Appearance is achieved by including the <i>communicator</i>
CSS file and using a class specific to buttons (toolbarbutton-1). Here is
the XUL code for the buttons. <br>
<br>
<small><font face="Helvetica, Arial, sans-serif">...<br>
&lt;?xml-stylesheet href="chrome://navigator/skin" type="text/css"?&gt;<br>
...<br>
&lt;toolbarbutton id="back-button" class="toolbarbutton-1"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
tooltiptext="Go Back"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
oncommand="goBack();"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
observes="canGoBack"&gt;<br>
&lt;/toolbarbutton&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&lt;toolbarbutton id="forward-button" class="toolbarbutton-1"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></small><small><font
 face="Helvetica, Arial, sans-serif">tooltiptext</font></small><small><font
 face="Helvetica, Arial, sans-serif">="Go Forward"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
oncommand="goForward();"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
observes="canGoForward"&gt;<br>
&lt;/toolbarbutton&gt;</font></small><br>
<br>
Apart from the <i>class</i> attribute on the buttons, the other main ones
to watch for are <i>oncommand</i>, which bridges the functionality, and <i>observes</i>.
The <i>observes</i> atribute determines if the button is active. There is
a little bit more trickery involved to get the buttons to move to and from
a disabled state depending on whether navigation can occur either forward
and back. We will not go into that here, but the full source code for the
<a href="http://books.mozdev.org/articles/browser.xul.txt">XUL file</a> and
the <a href="http://books.mozdev.org/articles/browser.js.txt">JavaScript
file</a>used in this article are available for reference. Lets look at the
code for the <i>goBack()</i> and <i>goForward()</i> functions.<br>
<br>
<small><font face="Helvetica, Arial, sans-serif">function goBack()<br>
{<br>
&nbsp;&nbsp;&nbsp; var webNavigation = myBrowser.webNavigation;<br>
&nbsp;&nbsp;&nbsp; if (webNavigation.canGoBack)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; webNavigation.goBack();<br>
}<br>
<br>
function goForward()<br>
{<br>
&nbsp;&nbsp;&nbsp; var webNavigation = myBrowser.webNavigation;<br>
&nbsp;&nbsp;&nbsp; if (webNavigation.canGoForward)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; webNavigation.goForward();<br>
}</font></small><br>
<br>
Once again the <i>webNavigation</i> interface is accessed through the browser
widget. After an efficiency check on the observer to see if the it is possible,
the <span style="font-style: italic;">goBack()</span> or <span
 style="font-style: italic;">goForward()</span> routine from the interface
is called. And that is all there is to it -- 3 lines of code. The foundations
were laid in the initialization code, and now the benefits are reaped.<br>
   
<h2>Up to You</h2>
The rest, as is said, is up to you. You can choose to make your browser as
simple or as complex as possible. Mozilla provides the widgets to hold your
content, and as was illustated in this article, it also gives you the source
code to add rich functionality. The surface was only touched here. Other features
you can hook in are context menus, events such as drag&amp;drop and onclick
on the content area, and the viewing of page source. If you are truly ambitious
you can even go one step further and use the tabbed browser. Integrated into
the Mozilla browser and turned on by default, this has been a popular addition
to the browsing experience, and has won many new users. Looking at the <i>&lt;tabbrowser&gt;</i>
widget is more complex that the basic browser, but could bring more rewards.
And don't forget, if it doesn't exactly meet your needs, you can change the
source code!<br>
<br>
</body>
</html>

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>