Gecko Embedding Basics

  • Revision slug: Gecko/Gecko_Embedding_Basics
  • Revision title: Gecko Embedding Basics
  • Revision id: 108751
  • Created:
  • Creator: Anguis
  • Is current revision? No
  • Comment /* XUL/XBL */

Revision Content

Note: This document is in the process of being migrated. If you would like to help with this migration, please migrate from here.

Given the ever-growing importance of the Web as a source of information, entertainment, and personal connectedness, the ability to access and view data stored in HTML format is becoming more and more important for a wide variety of otherwise highly divergent software applications. Whether it's a matter of a simple HTML page viewer or of a full-fledged web browser, the ability to parse and render HTML-based documents is an increasingly significant function in many, many situations. For the application developer, the problem becomes how to implement this crucial functionality in a way that minimizes development time yet results in an agile and robust product. Embedding Gecko, the rendering engine at the heart of the Netscape and Mozilla browsers, is an outstanding solution to this problem.

Why Gecko

Gecko is the smart embedding choice. It is quick, robust, and highly standards compliant. In its Mozilla and Netscape incarnations, it has been widely distributed and very well reviewed.

It is Open Source. Unlike other embedding choices, all of Gecko's source code is freely available and fully customizable. You can tinker and tweak as much as you need. Yet, depending on the license chosen, it is quite possible to use Gecko as a component in what is otherwise a fully proprietary commercial product.

And because Gecko is associated with the Mozilla project, there are many resources available to assist the embedding effort. The Mozilla web site, mozilla.org, has an embedding project area at mozilla.org/projects/embedding/. There is a newsgroup, netscape.public.mozilla.embedding, focussed on exchanging information among embedders, as well as a number of other related newsgroups. A complete cross-reference for the codebase is available at lxr.mozilla.org/seamonkey/. And filing, following the progress of, and helping to fix any bugs is made simple through the Bugzilla bug database, bugzilla.mozilla.org/.

Gecko is also architected from the ground up to be cross-platform. Directly from mozilla.org, it runs on Wintel, Mac OS 9.0 and OS X, and Linux, and there are third-party ports to a number of other platforms.

Finally, licensing Gecko is royalty-free, even if the final application is an otherwise proprietary commercial product. Very generally, any modifications of the original Mozilla-supplied source code (but not the code in which it is embedded) must be returned to the community, that same original code must be made available to the application's users (often by a link to the mozilla.org website), and the application must indicate in some obvious way (for example, a logo on the box or on the About: page) that the product embeds Gecko. Exact descriptions of the possible licensing arrangements are presented at www.mozilla.org/MPL/, which is the only legally complete source for licensing information.

What You Need to Embed

Once you've decided to embed, there are three main steps that you must take. First you must get the code. Then you must understand some specific technologies used in the manipulation of the Gecko codebase. Finally, you must decide which additional functionalities you may wish to add. This section will guide you through these steps.

Getting the Code

At the moment, the best way to get the files you will need to embed Gecko is to download and build the entire Mozilla source tree. This is actually a fairly simple process. Full instructions and appropriate links are available at http://mozilla.org/source.html. A second, component by component, method is under development, but is still at a beta stage. Information on this project can be found at http://www.mozilla.org/projects/embedding/bootstrap.html. In addition, work is also being done on developing a Gecko Runtime Environment, or GRE, which would support multiple applications built on Mozilla components using a single set of core libraries. This project lives at http://www.mozilla.org/projects/embedding/GRE.html. (If you intend to work component by component you must be particularly aware of issues of versioning and binary compatibility. For help in this area, look at http://mozilla.org/projects/xpcom/glue/Component_Reuse.html.)

First you must acquire some tools (basically a supported compiler, a Perl distribution, and some general purpose utilities). Then you must set up your computer environment. Next you must download the source. Assuming you are going to download the entire tree, there are two ways to do this: you can FTP a tarball of the entire tree (this is the simplest way, and it's guaranteed to compile, but it may not include the most recent additions to the code) or you can use CVS to get the absolutely most recent code or to do incremental updates. Once you have the tree and the tools and your environment is properly set up, all you have to do is run the appropriate provided makefile. There are detailed instructions for each of the supported platforms.

When the build is done, navigate to the mozilla/embedding/config directory. There you will find sample manifest files (all the names begin with "basebrowser") for embedding on each of the different platforms. These are samples only and they may not fit your needs completely, but they are a good place to start. There are also sample embedding projects for each platform that you can use as models. See http://mozilla.org/projects/embedding/examples/index.html

Understanding the Coding Environment

Mozilla was set up from the beginning to support design and development across multiple platforms and programming languages. To this end, a number of in-house programming technologies were developed, all based around an ideal of object encapsulation. Embedding Gecko necessarily implies acquiring a working knowledge of these technologies, including XPCOM, XPIDL, XPConnect, special string classes, and, optionally, XUL. The following provides a brief introduction to them. More information can be found at the mozilla.org site.

XPCOM

The most important of the Mozilla technologies is XPCOM, the Cross-Platform Component Object Model. XPCOM provides a framework which manages the creation, ownership, and deletion of objects and other data throughout Mozilla. If you have used MSCOM, you will recognize certain basic similarities. But there are also significant differences - XPCOM is cross-platform and designed to run largely in a single thread - and the two are not at this time compatible.

The interface

At the core of XPCOM is the concept of the interface. An interface is simply a description of a set of methods, attributes, and related constants all associated with a particular functionality: it is completely distinct from the class that implements those things. The interface serves as a kind of contract: any object that supports a particular interface guarantees that it will perform the services described in it. To keep the interface as language neutral as possible, it is written in a special language, the Interface Definition Language, or IDL. Interface files are often referred to as .idl files. In addition to specifying the functionality of the interface, these files also carry the interface's IID, its globally unique identifying number.

Much of the communication within Gecko takes place in terms of these abstract structures (by convention, their names follow the form nsISomething).

//this
void ProcessSample(nsISample* aSample) {
	aSample->Poke("Hello"); 
//not this
void ProcessSample(nsSampleImpl* aSample) {
	aSample->Poke("hello"); 
@status FROZEN

XPCOM's level of abstraction produces great flexibility in the system. Implementations are free to change as needed. But, to work, the interfaces themselves must remain fixed. Throughout Mozilla's initial design and development period, interfaces have been somewhat fluid, but as the project has matured, more and more of the interfaces have been marked FROZEN. Any interface so marked is guaranteed not to change in the future.

Most of the main interfaces key to the embedding effort are now frozen, but it's always a good idea to check before using any interface. An interface's status is listed in the .idl file's comments. A frozen interface is marked @status FROZEN. You can search for frozen interfaces by using the mozilla cross referencing tool at http://lxr.mozilla.org/seamonkey/search?string=%40status+FROZEN. Until it is frozen, an interface may change at any time. For more information on the freezing process, see the embedding project page at: http://mozilla.org/projects/embedding/.

Once an interface has been frozen, it is added to the Gecko Embedding API Reference at http://mozilla.org/projects/embedding/embedapiref/embedapi.html.

nsISupports

A single object can support more than one interface. In fact, essentially all objects support at least two interfaces - a minimum of one that does something specifically useful and one, nsISupports, that serves a more general purpose. In a sense, nsISupports is the progenitor of all XPCOM interfaces. All interfaces inherit from it, most directly so. It serves two main functions - runtime type discovery and object lifetime management. It is functionally identical to IUnknown in MSCOM.

Since an object can support multiple interfaces, it is perfectly possible to have a pointer to one interface and want to know whether that same object also supports a different interface whose functionality you might also need. The first nsISupports method, QueryInterface, does exactly that: it asks, in effect, I know that this object is of type A (supports interface A) but is it also of type B (supports interface B)? If it is (or does), QueryInterface returns to the caller a pointer bound to the newly requested interface.

void ProcessSample(nsISample* aSample) {
	nsIExample *example;
	nsresult rv;
	rv = aSample->QueryInterface(NS_GET_IID(nsIExample),(void **)&example); 
	if (NS_SUCCEEDED(rv)) {
		example->DoSomeOperation();
		NS_RELEASE(example); // using a macro to call Release 
	} 
} 

Because XPCOM uses an indirect method, the Component Manager, to actually instantiate objects, and because multiple pointers to the same object - often bound to different interfaces - can exist, it can quickly become very difficult for callers to keep accurate track of all of the objects to which those pointers point. Objects could be kept around in memory longer than they need to be, causing leaks, or objects could be deleted prematurely, causing dangling pointers. The other two methods in nsISupports, AddRef and Release, are designed to deal with this issue. Every time a pointer is given out AddRef must be called on the object, incrementing an internal counter. Every time a pointer is released, Release must be called, decrementing that same counter. When the counter reaches zero, there are no pointers to the object remaining and the object can safely delete itself. Control of the object's lifetime stays within the object itself. See below for information on XPCOM's "smart" pointer, nsCOMPtr, a utility which helps automate this process.

Object creation

The instantiation of objects is also an indirect process in XPCOM. Just as interfaces have a globally unique ID number (the IID), XPCOM classes are assigned their own GUIDs, the CID. In addition, they are also often given a text-based ID, called a contract ID. One or the other of these IDs is passed to a method on a persistent XPCOM component, the Component Manager, which actually creates the object. When a new library of classes (called a module in XPCOM) is first introduced into the system, it must register itself with the Component Manager, which maintains a registry that maps classes (with their IDs) to the libraries in which they reside.

A limited number of persistent services, supplied by singleton objects, are created and controlled by a companion to the Component Manager, the Service Manager. The Component Manager itself is an example of such a persistent service.

Summing up

Functionality in XPCOM is described by abstract interfaces, and most communication among parts of the system takes place in terms of those interfaces. The underlying objects that implement the interfaces, on the other hand, are created indirectly by the Component Manager based on a cross-indexed registry that it maintains.

One functionality shared by all interfaces is the ability to query the underlying object at runtime to see if also implements other interfaces. In theory an interface is fixed and unchangeable, but at this stage in the Mozilla codebase, only interfaces that have been declared FROZEN are guaranteed not to change significantly. Object lifetime management takes place inside the object itself through an internal counter that keeps track of the number of pointers to the object that have been added or released. The client's only responsibility is to increment and decrement the counter. When the internal counter reaches zero, the object deletes itself.

nsCOMPtr

Sometimes, however, even remembering to call AddRef and Release at the right times can be difficult. To make this process easier and more reliable, XPCOM has a built-in "smart" pointer, nsCOMPtr. This pointer takes care of calling AddRef and Release for you. Using nsCOMPtr whenever possible will make your code cleaner and more efficient. For more information on the smart pointer, see "The Complete nsCOMPtr User's Manual" at http://www.mozilla.org/projects/xpcom/nsCOMPtr.html.

Mozilla actually provides a large number of built-in macros (by convention, written in all caps in the code) and utilities like nsCOMPtr that can make the entire process of coding with XPCOM easier. Many of these can be found in the following files: nsCom.h, nsDebug.h, nsError.h, nsIServiceManager.h, and nsISupportsUtils.h Mozilla also supplies other development tools for tracking memory usage and the like. More information on these can be found at http://www.mozilla.org/performance/

For more information

More information on XPCOM in general can be found at http://mozilla.org/projects/xpcom/. For an overview of creating XPCOM components, see Chapter 8 of O'Reilly's Creating Applications with Mozilla, an open source version of which is available at http://books.mozdev.org/chapters/ch08.html. There is also a new book completely devoted to this topic, Creating XPCOM Components, available at http://mozilla.org/projects/xpcom/book/cxc/. A fuller explanation of some of the underlying logic to COM systems can be found in the early chapters of Essential COM by Don Box. While it focusses on MSCOM in particular, the book does provide an excellent background on some of the core rationales for using such an object model.

XPIDL

Interfaces are abstract classes written in XPIDL, the Cross Platform Interface Definition Language. Yet to be useful the functionality promised in those interfaces must be implemented in some regular programming language. Facilitating this is the job of the XPIDL compiler. Once an interface is defined in an .idl file, it can be processed by the XPIDL compiler.

The compiler can be set to output a number of things, but generally the output is two-fold: a C++ .h file that includes a commented out template for a full C++ implementation of the interface and an XPT file that contains type library information which works with XPConnect to make the interface available to JavaScript. More information on the syntax of XPIDL (a simple C-like language) and the use of the compiler can be found at http://mozilla.org/scriptable/xpidl/index.html.

XPConnect and XPT files

XPConnect is an XPCOM module that allows code written in JavaScript to access and manipulate XPCOM components written in C++ and vice versa. By means of XPConnect, components on either side of an XPCOM interface do not, in general, need to know or care about which of these languages the object on the other side is implemented in.

When an interface is run through the XPIDL compiler, it produces an XPT or type library file. Because XPconnect uses the information in this file to implement transparent communication between C++ objects and JavaScript objects across XPCOM interfaces, it is important to make sure they are generated and included with your code even if you are developing exclusively in C++. Not only is a substantial part of the browser, in fact, implemented in JS, it is possible that in the future someone may wish to use JS-based code to interact with whatever components you create .

As is from Mozilla, XPConnect currently facilitates interoperability between C++ and JS. Modules to extend it to allow access from other languages (including Python) are under independent development. Further information can be found at http://mozilla.org/scriptable/index.html.

String classes

Web browsing typically involves a large amount of string manipulation. Mozilla has developed a hierarchy of C++ classes to facilitate such manipulation and to render it efficient and quick. To make communication among objects simpler and more error free, Mozilla uses interfaces, which are, in essence, abstract classes. The string hierarchy is also headed up by a set of abstract classes, nsAString, nsASingleFragmentString, and nsAFlatString, and for the same reasons. (These refer to double-byte strings. There is a parallel hierarchy topped with nsACString, etc., that refers to single-byte strings.) nsAString guarantees only a string of characters. nsASingleFragmentString guarantees that the characters will be stored in a single buffer. nsAFlatString guarantees that the characters will be stored in a single null-terminated buffer. While there are underlying concrete classes, in general it is best to use the most abstract type possible in a given situation. For example, concantenation can be done virtually, through the use of pointers, resulting in an nsAString that can be used like any other string. This saves the allocating and copying that would otherwise have to be done. For more information, see "Guide to the Mozilla string classes" at http://www.mozilla.org/projects/xpcom/string-guide.html.

XUL/XBL

Use of this final Mozilla technology is optional, depending on how you decide to create the user interface for your application. XUL is Mozilla's highly flexible XML UI Language. It provides a number of largely platform independent widgets from which to construct a UI. Netscape and Mozilla both use XUL for their interfaces, but not all embedders chose to use it. XBL or the eXtensible Binding Language allows you to attach behaviors to XUL's XML elements. More information on XUL can be found at http://www.mozilla.org/xpfe/xulref/ and on XBL at http://www.mozilla.org/projects/xbl/xbl.html. There is also a wealth of good information on XUL at XulPlanet, http://www.xulplanet.com/.

Choosing Additional Functionalities

What Gecko Provides

What You Provide

Common Embedding Tasks

Resources

Appendix: Data Flow Inside Gecko

Revision Source

<div class="note"><b>Note</b>: This document is in the process of being migrated.  If you would like to help with this migration, please migrate from <a class="external" href="http://www.mozilla.org/projects/embedding/embedoverview/EmbeddingBasicsTOC.html">here</a>.
</div>
<p>Given the ever-growing importance of the Web as a source of information, entertainment, and personal connectedness, the ability to access and view data stored in HTML format is becoming more and more important for a wide variety of otherwise highly divergent software applications. Whether it's a matter of a simple HTML page viewer or of a full-fledged web browser, the ability to parse and render HTML-based documents is an increasingly significant function in many, many situations. For the application developer, the problem becomes how to implement this crucial functionality in a way that minimizes development time yet results in an agile and robust product. Embedding Gecko, the rendering engine at the heart of the Netscape and Mozilla browsers, is an outstanding solution to this problem.
</p>
<h2 name="Why_Gecko"> Why Gecko </h2>
<p>Gecko is the smart embedding choice. It is quick, robust, and highly standards compliant. In its Mozilla and Netscape incarnations, it has been widely distributed and very well reviewed.
</p><p>It is Open Source. Unlike other embedding choices, all of Gecko's source code is freely available and fully customizable. You can tinker and tweak as much as you need. Yet, depending on the license chosen, it is quite possible to use Gecko as a component in what is otherwise a fully proprietary commercial product.
</p><p>And because Gecko is associated with the Mozilla project, there are many resources available to assist the embedding effort. The Mozilla web site, <a class="external" href="http://www.mozilla.org">mozilla.org</a>, has an embedding project area at <a class="external" href="http://mozilla.org/projects/embedding/">mozilla.org/projects/embedding/</a>. There is a newsgroup, netscape.public.mozilla.embedding, focussed on exchanging information among embedders, as well as a number of other related newsgroups. A complete cross-reference for the codebase is available at <a class="external" href="http://lxr.mozilla.org/seamonkey/">lxr.mozilla.org/seamonkey/</a>. And filing, following the progress of, and helping to fix any bugs is made simple through the Bugzilla bug database, <a class="external" href="http://bugzilla.mozilla.org/">bugzilla.mozilla.org/</a>.
</p><p>Gecko is also architected from the ground up to be cross-platform. Directly from mozilla.org, it runs on Wintel, Mac OS 9.0 and OS X, and Linux, and there are third-party ports to a number of other platforms.
</p><p>Finally, licensing Gecko is royalty-free, even if the final application is an otherwise proprietary commercial product. <i>Very</i> generally, any modifications of the original Mozilla-supplied source code (but not the code in which it is embedded) must be returned to the community, that same original code must be made available to the application's users (often by a link to the mozilla.org website), and the application must indicate in some obvious way (for example, a logo on the box or on the About: page) that the product embeds Gecko. Exact descriptions of the possible licensing arrangements are presented at <a class="external" href="http://www.mozilla.org/MPL/">www.mozilla.org/MPL/</a>, which is the only legally complete source for licensing information.
</p>
<h2 name="What_You_Need_to_Embed"> What You Need to Embed </h2>
<p>Once you've decided to embed, there are three main steps that you must take. First you must get the code. Then you must understand some specific technologies used in the manipulation of the Gecko codebase. Finally, you must decide which additional functionalities you may wish to add. This section will guide you through these steps.
</p>
<h3 name="Getting_the_Code"> Getting the Code </h3>
<p>At the moment, the best way to get the files you will need to embed Gecko is to download and build the entire Mozilla source tree. This is actually a fairly simple process. Full instructions and appropriate links are available at http://mozilla.org/source.html. A second, component by component, method is under development, but is still at a beta stage. Information on this project can be found at http://www.mozilla.org/projects/embedding/bootstrap.html. In addition, work is also being done on developing a Gecko Runtime Environment, or GRE, which would support multiple applications built on Mozilla components using a single set of core libraries. This project lives at http://www.mozilla.org/projects/embedding/GRE.html. (If you intend to work component by component you must be particularly aware of issues of versioning and binary compatibility. For help in this area, look at http://mozilla.org/projects/xpcom/glue/Component_Reuse.html.)
</p><p>First you must acquire some tools (basically a supported compiler, a Perl distribution, and some general purpose utilities). Then you must set up your computer environment. Next you must download the source. Assuming you are going to download the entire tree, there are two ways to do this: you can FTP a tarball of the entire tree (this is the simplest way, and it's guaranteed to compile, but it may not include the most recent additions to the code) or you can use CVS to get the absolutely most recent code or to do incremental updates. Once you have the tree and the tools and your environment is properly set up, all you have to do is run the appropriate provided makefile. There are detailed instructions for each of the supported platforms.
</p><p>When the build is done, navigate to the mozilla/embedding/config directory. There you will find sample manifest files (all the names begin with "basebrowser") for embedding on each of the different platforms. These are samples only and they may not fit your needs completely, but they are a good place to start. There are also sample embedding projects for each platform that you can use as models. See http://mozilla.org/projects/embedding/examples/index.html
</p>
<h3 name="Understanding_the_Coding_Environment"> Understanding the Coding Environment </h3>
<p>Mozilla was set up from the beginning to support design and development across multiple platforms and programming languages. To this end, a number of in-house programming technologies were developed, all based around an ideal of object encapsulation. Embedding Gecko necessarily implies acquiring a working knowledge of these technologies, including XPCOM, XPIDL, XPConnect, special string classes, and, optionally, XUL. The following provides a brief introduction to them. More information can be found at the mozilla.org site.
</p>
<h4 name="XPCOM"> XPCOM </h4>
<p>The most important of the Mozilla technologies is XPCOM, the Cross-Platform Component Object Model. XPCOM provides a framework which manages the creation, ownership, and deletion of objects and other data throughout Mozilla. If you have used MSCOM, you will recognize certain basic similarities. But there are also significant differences - XPCOM is cross-platform and designed to run largely in a single thread - and the two are not at this time compatible.
</p>
<h5 name="The_interface"> The interface </h5>
<p>At the core of XPCOM is the concept of the interface. An interface is simply a description of a set of methods, attributes, and related constants all associated with a particular functionality: it is completely distinct from the class that implements those things. The interface serves as a kind of contract: any object that supports a particular interface guarantees that it will perform the services described in it. To keep the interface as language neutral as possible, it is written in a special language, the Interface Definition Language, or IDL. Interface files are often referred to as .idl files. In addition to specifying the functionality of the interface, these files also carry the interface's IID, its globally unique identifying number.
</p><p>Much of the communication within Gecko takes place in terms of these abstract structures (by convention, their names follow the form <code>nsISomething</code>).
</p>
<pre>//this
void ProcessSample(nsISample* aSample) {
	aSample-&gt;Poke("Hello"); 
//not this
void ProcessSample(nsSampleImpl* aSample) {
	aSample-&gt;Poke("hello"); 
</pre>
<h5 name=".40status_FROZEN"> @status FROZEN </h5>
<p>XPCOM's level of abstraction produces great flexibility in the system. Implementations are free to change as needed. But, to work, the interfaces themselves must remain fixed. Throughout Mozilla's initial design and development period, interfaces have been somewhat fluid, but as the project has matured, more and more of the interfaces have been marked FROZEN. Any interface so marked is guaranteed not to change in the future.
</p><p>Most of the main interfaces key to the embedding effort are now frozen, but it's always a good idea to check before using any interface. An interface's status is listed in the .idl file's comments. A frozen interface is marked @status FROZEN. You can search for frozen interfaces by using the mozilla cross referencing tool at http://lxr.mozilla.org/seamonkey/search?string=%40status+FROZEN. Until it is frozen, an interface may change at any time. For more information on the freezing process, see the embedding project page at: http://mozilla.org/projects/embedding/.
</p><p>Once an interface has been frozen, it is added to the Gecko Embedding API Reference at http://mozilla.org/projects/embedding/embedapiref/embedapi.html.
</p>
<h5 name="nsISupports"> nsISupports </h5>
<p>A single object can support more than one interface. In fact, essentially all objects support at least two interfaces - a minimum of one that does something specifically useful and one, nsISupports, that serves a more general purpose. In a sense, nsISupports is the progenitor of all XPCOM interfaces. All interfaces inherit from it, most directly so. It serves two main functions - runtime type discovery and object lifetime management. It is functionally identical to IUnknown in MSCOM.
</p><p>Since an object can support multiple interfaces, it is perfectly possible to have a pointer to one interface and want to know whether that same object also supports a different interface whose functionality you might also need. The first nsISupports method, QueryInterface, does exactly that: it asks, in effect, I know that this object is of type A (supports interface A) but is it also of type B (supports interface B)? If it is (or does), QueryInterface returns to the caller a pointer bound to the newly requested interface.
</p>
<pre>void ProcessSample(nsISample* aSample) {
	nsIExample *example;
	nsresult rv;
	rv = aSample-&gt;QueryInterface(NS_GET_IID(nsIExample),(void **)&amp;example); 
	if (NS_SUCCEEDED(rv)) {
		example-&gt;DoSomeOperation();
		NS_RELEASE(example); // using a macro to call Release 
	} 
} 
</pre>
<p>Because XPCOM uses an indirect method, the Component Manager, to actually instantiate objects, and because multiple pointers to the same object - often bound to different interfaces - can exist, it can quickly become very difficult for callers to keep accurate track of all of the objects to which those pointers point. Objects could be kept around in memory longer than they need to be, causing leaks, or objects could be deleted prematurely, causing dangling pointers. The other two methods in nsISupports, AddRef and Release, are designed to deal with this issue. Every time a pointer is given out AddRef must be called on the object, incrementing an internal counter. Every time a pointer is released, Release must be called, decrementing that same counter. When the counter reaches zero, there are no pointers to the object remaining and the object can safely delete itself. Control of the object's lifetime stays within the object itself. See below for information on XPCOM's "smart" pointer, <a href="#nsCOMPtr">nsCOMPtr</a>, a utility which helps automate this process.
</p>
<h5 name="Object_creation"> Object creation </h5>
<p>The instantiation of objects is also an indirect process in XPCOM. Just as interfaces have a globally unique ID number (the IID), XPCOM classes are assigned their own GUIDs, the CID. In addition, they are also often given a text-based ID, called a contract ID. One or the other of these IDs is passed to a method on a persistent XPCOM component, the Component Manager, which actually creates the object. When a new library of classes (called a module in XPCOM) is first introduced into the system, it must register itself with the Component Manager, which maintains a registry that maps classes (with their IDs) to the libraries in which they reside.
</p><p>A limited number of persistent services, supplied by singleton objects, are created and controlled by a companion to the Component Manager, the Service Manager. The Component Manager itself is an example of such a persistent service.
</p>
<h5 name="Summing_up"> Summing up </h5>
<p>Functionality in XPCOM is described by abstract interfaces, and most communication among parts of the system takes place in terms of those interfaces. The underlying objects that implement the interfaces, on the other hand, are created indirectly by the Component Manager based on a cross-indexed registry that it maintains.
</p><p>One functionality shared by all interfaces is the ability to query the underlying object at runtime to see if also implements other interfaces. In theory an interface is fixed and unchangeable, but at this stage in the Mozilla codebase, only interfaces that have been declared FROZEN are guaranteed not to change significantly. Object lifetime management takes place inside the object itself through an internal counter that keeps track of the number of pointers to the object that have been added or released. The client's only responsibility is to increment and decrement the counter. When the internal counter reaches zero, the object deletes itself.
</p>
<h5 name="nsCOMPtr"> nsCOMPtr </h5>
<p>Sometimes, however, even remembering to call AddRef and Release at the right times can be difficult. To make this process easier and more reliable, XPCOM has a built-in "smart" pointer, nsCOMPtr. This pointer takes care of calling AddRef and Release for you. Using nsCOMPtr whenever possible will make your code cleaner and more efficient. For more information on the smart pointer, see "The Complete nsCOMPtr User's Manual" at http://www.mozilla.org/projects/xpcom/nsCOMPtr.html.
</p><p>Mozilla actually provides a large number of built-in macros (by convention, written in all caps in the code) and utilities like nsCOMPtr that can make the entire process of coding with XPCOM easier. Many of these can be found in the following files: nsCom.h, nsDebug.h, nsError.h, nsIServiceManager.h, and nsISupportsUtils.h Mozilla also supplies other development tools for tracking memory usage and the like. More information on these can be found at http://www.mozilla.org/performance/
</p>
<h5 name="For_more_information"> For more information </h5>
<p>More information on XPCOM in general can be found at http://mozilla.org/projects/xpcom/. For an overview of creating XPCOM components, see Chapter 8 of O'Reilly's <i>Creating Applications with Mozilla</i>, an open source version of which is available at http://books.mozdev.org/chapters/ch08.html. There is also a new book completely devoted to this topic, <i>Creating XPCOM Components</i>, available at http://mozilla.org/projects/xpcom/book/cxc/. A fuller explanation of some of the underlying logic to COM systems can be found in the early chapters of <i>Essential COM</i> by Don Box. While it focusses on MSCOM in particular, the book does provide an excellent background on some of the core rationales for using such an object model.
</p>
<h4 name="XPIDL"> XPIDL </h4>
<p>Interfaces are abstract classes written in XPIDL, the Cross Platform Interface Definition Language. Yet to be useful the functionality promised in those interfaces must be implemented in some regular programming language. Facilitating this is the job of the XPIDL compiler. Once an interface is defined in an .idl file, it can be processed by the XPIDL compiler.
</p><p>The compiler can be set to output a number of things, but generally the output is two-fold: a C++ .h file that includes a commented out template for a full C++ implementation of the interface and an XPT file that contains type library information which works with XPConnect to make the interface available to JavaScript. More information on the syntax of XPIDL (a simple C-like language) and the use of the compiler can be found at http://mozilla.org/scriptable/xpidl/index.html.
</p>
<h4 name="XPConnect_and_XPT_files"> XPConnect and XPT files </h4>
<p>XPConnect is an XPCOM module that allows code written in JavaScript to access and manipulate XPCOM components written in C++ and vice versa. By means of XPConnect, components on either side of an XPCOM interface do not, in general, need to know or care about which of these languages the object on the other side is implemented in.
</p><p>When an interface is run through the XPIDL compiler, it produces an XPT or type library file. Because XPconnect uses the information in this file to implement transparent communication between C++ objects and JavaScript objects across XPCOM interfaces, it is important to make sure they are generated and included with your code even if you are developing exclusively in C++. Not only is a substantial part of the browser, in fact, implemented in JS, it is possible that in the future someone may wish to use JS-based code to interact with whatever components you create .
</p><p>As is from Mozilla, XPConnect currently facilitates interoperability between C++ and JS. Modules to extend it to allow access from other languages (including Python) are under independent development. Further information can be found at http://mozilla.org/scriptable/index.html.
</p>
<h4 name="String_classes"> String classes </h4>
<p>Web browsing typically involves a large amount of string manipulation. Mozilla has developed a hierarchy of C++ classes to facilitate such manipulation and to render it efficient and quick. To make communication among objects simpler and more error free, Mozilla uses interfaces, which are, in essence, abstract classes. The string hierarchy is also headed up by a set of abstract classes, nsAString, nsASingleFragmentString, and nsAFlatString, and for the same reasons. (These refer to double-byte strings. There is a parallel hierarchy topped with nsACString, etc., that refers to single-byte strings.) nsAString guarantees only a string of characters. nsASingleFragmentString guarantees that the characters will be stored in a single buffer. nsAFlatString guarantees that the characters will be stored in a single null-terminated buffer. While there are underlying concrete classes, in general it is best to use the most abstract type possible in a given situation. For example, concantenation can be done virtually, through the use of pointers, resulting in an nsAString that can be used like any other string. This saves the allocating and copying that would otherwise have to be done. For more information, see "Guide to the Mozilla string classes" at http://www.mozilla.org/projects/xpcom/string-guide.html.
</p>
<h4 name="XUL.2FXBL"> XUL/XBL </h4>
<p>Use of this final Mozilla technology is optional, depending on how you decide to create the user interface for your application. XUL is Mozilla's highly flexible XML UI Language. It provides a number of largely platform independent widgets from which to construct a UI. Netscape and Mozilla both use XUL for their interfaces, but not all embedders chose to use it. XBL or the eXtensible Binding Language allows you to attach behaviors to XUL's XML elements. More information on XUL can be found at http://www.mozilla.org/xpfe/xulref/ and on XBL at http://www.mozilla.org/projects/xbl/xbl.html. There is also a wealth of good information on XUL at XulPlanet, http://www.xulplanet.com/.
</p>
<h3 name="Choosing_Additional_Functionalities"> Choosing Additional Functionalities </h3>
<h2 name="What_Gecko_Provides"> What Gecko Provides </h2>
<h2 name="What_You_Provide"> What You Provide </h2>
<h2 name="Common_Embedding_Tasks"> Common Embedding Tasks </h2>
<h2 name="Resources"> Resources </h2>
<h2 name="Appendix:_Data_Flow_Inside_Gecko"> Appendix: Data Flow Inside Gecko </h2>
Revert to this revision