Real World Mozilla First XPCOM Component

July 14, 2008

Introduction

Mozilla is a huge platform. In order to work in such a large system and have hundreds or thousands of developers working on the same code, it is necessary to break things into smaller pieces. In Mozilla these pieces are called components, and are shipped as .DLL files (on win32). When one of these .DLL files contains two or more components, it is called a module.

Mozilla developer specialize in one or more components/modules (modules are made up of components). Here is a list of the various modules and their owners and peers: http://www.mozilla.org/owners.html. Module owners are responsible for a module’s code, and have final say about how changes are made to it. The peers are people designated by the module owner to help them maintain the code. Owners and peers do code reviews of patches from the community.

By writing code in components/modules instead of one giant application, there are a number of benefits:

  • Modularization of code, so pieces of a system can be developed, built, replaced independently
  • Increased performance, because you only need to load the components/modules you are using instead of the whole thing
  • Reuse, as separate components become usable in different applications

This raises a question: what are ‘XPCOM components’ components of exactly? The answer is Gecko, Mozilla’s standards compliant, embeddable web browser and toolkit for creating web browsers and other applications. XPCOM is the means of accessing Gecko library functionality and embedding or extending Gecko.

Much has been written about XPCOM elsewhere, and you are encouraged to read more on the theory behind this technology in conjunction with this walkthrough.

Writing FirstXpcom

In this walkthrough we will be creating a simple binary XPCOM component using the build system, called FirstXpcom. While this component won’t do very much yet, it will provide a starting point for many other types of components you may wish to build down the road.

The functionality of this component will become part of a Gecko-enabled application (in this case, a Firefox binary extension). However, it is important to remember that this is only one of many possible uses for it.

NOTE: the following assumes you have used an objdir. Replace all occurrences of $(objdir) with your objdir name.

What is a Component?

Components define certain publicly available functionality. The public portion of a component is defined in an Interface. Interfaces are a kind of contract between implementors (those writing code to implement the interface) and clients (those writing code to use an interface’s implementation). By defining an interface for a component, we advertise to the world what we are willing and able to do. There are other advantages as well:

  • implementors can change their implementation without affecting clients
  • clients can choose between multiple implementations

It should also be noted that components can implement multiple interfaces. This is something we’ll return to later when we discuss interface querying.

Writing FirstXpcom

For this walkthrough we will use the Mozilla build system to create our component. It is also possible to us the Gecko SDK (instructions are here). NOTE: this assumes that you have already done a successful objdir-Firefox build.

Creating Directories

Start by creating a directory for your component, using all lowercase letters:

$ cd mozilla/extensions
$ mkdir firstxpcom

Next, create 2 more directories to hold your component’s public interface (i.e., public) and source code (i.e., src):

$ cd mozilla/extensions/firstxpcom
$ mkdir public
$ mkdir src

Defining an Interface

Now we need to define the component’s public interface. To do this you must create an IDL file (see http://developer.mozilla.org/en/docs/XPIDL). The IDL file defines the component’s public interface in a language neutral way. Mozilla uses the XPIDL format (Cross Platform Interface Definition Language) to define a component’s public interface rather than doing it in C++ header files directly. Using IDL, these interfaces can be defined in a language- and machine-independent way. IDLs make it possible to define interfaces which can then be processed by tools to autogenerate language-dependent interface specifications. The IDL files are used to generate C++ header files.

Create an IDL file for the component in the public directory:

$ cd mozilla/extensions/firstxpcom/public
$ touch IFirstXpcom.idl

Here are the contents of IFirstXpcom.idl

#include "nsISupports.idl"

[scriptable, uuid(...see below...)]
interface IFirstXpcom : nsISupports
{
	attribute AString name;

	long add(in long a, in long b);
};

What does this interface say? To begin, notice the use of nsISupports. This is the fundamental interface that all XPCOM components must implement. What does it do? How is it defined?

nsISupports

nsISupports is the base interface for all XPCOM components (i.e., it is possible to pass any XPCOM component around as an nsISupports object). The methods in nsISupports define basic bookkeeping for an interface’s lifetime (they also defines a way to check at runtime if a component implements a given interface, but more on that later).

Components need to keep track of how many clients hold references to them via an interface. This is known as reference counting on an interface, and it is used to determine when a component can be safely unloaded so that it doesn’t leak (i.e., no one holds a reference any more, but the interface is still in memory).

The members of nsISupports (i.e., QueryInterface, AddRef, and Release) provide the basic means for getting the right interface from an object, incrementing the reference count, and releasing objects once they are not being used.

One point worth mentioning is that pointers in XPCOM are to interfaces. Interface pointers are known to implement nsISupports, so you can access all of the object lifetime and discovery functionality described above.

So the first line above says, “include the interface for nsISupports (defined in nsISupports.idl) because I’ll need it”, and the fourth line says, “I’m a new interface called IFirstXpcom, but I’m also nsISupports because I inherit from it.”

UUID

[scriptable, uuid(...see below...)]

What does line 3 mean? This says that our component is scriptable, and can be used or implemented in scripting languages, JavaScript for example (see http://developer.mozilla.org/en/docs/Interfaces:About_Scriptable_Interfaces).

Each interface needs to be uniquely identifiable, and Mozilla uses a 128-bit number called a UUID (Universally Unique Identifier) for this purpose. You can generate one in a number of ways:

  • at the command prompt using the command uuidgen:
$ uuidgen
78af1749-014a-47aa-baec-2669670b7601
  • in IRC ask firebot:
/msg firebot uuid

You need to get a UUID and put it in the brackets, for example:

[scriptable, uuid(78af1749-014a-47aa-baec-2669670b7601)]

Attributes and Methods

attribute AString name;

long add(in long a, in long b);

Next comes the body of your interface. Our interface defines one attribute and one method. An attribute is a value you can Get and Set (NOTE: you can specify attributes that are Get only, that is read-only). We have an attribute called name of type AString (a unicode, or two-byte string class. For more details about strings in Mozilla, see the XPCOM String Guide).

Our interface also defines a single method called add, which takes two long integers as input, adds them, and returns the result as a long integer; we’ll write that code below.

Because we are using the Mozilla build system to help us create our component, we can get it to translate our IDL into .h and .cpp stub files automatically. To do this we first have to generate some makefiles.

Build system changes

The first step in making the build system aware of our component is to generate an input file for autoconf to use during the configure step, which will build the necessary Makefile automatically.

mozilla/extensions/firstxpcom/Makefile.in

The Makefile.in should contain the following (NOTE: you can read more about what these files actually mean here):

DEPTH		= ../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(DEPTH)/config/autoconf.mk

MODULE 	= firstxpcom

DIRS		= public \
		  src \
		  $(NULL)

XPI_NAME 	= firstxpcom

# A Unique ID for your extension
INSTALL_EXTENSION_ID	= firstxpcom@senecac.on.ca

# Will create a .xpi in /mozilla/$(MOZ_OBJDIR)/dist/xpi-stage/
XPI_PKGNAME	= firstxpcom

# install.rdf will tell Firefox how to install our extension and 
# this says, "copy install.rdf into our extension dir and xpi"
DIST_FILES = install.rdf

include $(topsrcdir)/config/rules.mk

Note the DIRS variable. It says that the two directories, public and src, will be entered during the build. Because Mozilla’s build system uses recursive make, we also need Makefile.in files in each of these.

mozilla/extensions/firstxpcom/public/Makefile.in

Next we need a Makefile.in the public directory

DEPTH		= ../../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(DEPTH)/config/autoconf.mk

MODULE		= firstxpcom
XPIDL_MODULE	= firstxpcom

XPI_NAME 	= firstxpcom

# The files under EXPORTS are copied directly to
# /mozilla/$(MOZ_OBJDIR)/dist/include/firstxpcom
# and are thus accessible from other modules
#EXPORTS       = \
#		myHeader.h \
#		$(NULL)

XPIDLSRCS	= IFirstXpcom.idl

include $(topsrcdir)/config/rules.mk

Here we tell the build system about our component’s name and where its XPIDL file can be found.

mozilla/extensions/firstxpcom/src/Makefile.in

Now a Makefile.in in the src directory:

DEPTH		= ../../..
topsrcdir	= @top_srcdir@
srcdir		= @srcdir@
VPATH		= @srcdir@

include $(DEPTH)/config/autoconf.mk

IS_COMPONENT 	= 1
MODULE 	= firstxpcom
LIBRARY_NAME 	= firstxpcom

XPI_NAME 	= firstxpcom

# The REQUIRES section tells make which modules your 
# components uses. This causes the relevant subdirectories
# of /mozilla/$(MOZ_OBJDIR)/dist/include/ to be added to the
# C++ compiler's include path. If you're including Mozilla
# headers and the compiler isn't finding them, it could well
# mean that you haven't listed all of the necessary modules here.
REQUIRES	= xpcom \
		  string \
		  $(NULL)

# The .cpp source files to be compiled
CPPSRCS	= FirstXpcom.cpp \
		  $(NULL)
include $(topsrcdir)/config/rules.mk

EXTRA_DSO_LDOPTS += \
  $(XPCOM_GLUE_LDOPTS) \
  $(NSPR_LIBS) \
  $(NULL)

mozilla/extensions/firstxpcom/install.rdf

The last build-related file we need to write is a file telling Firefox’s addon manager about our extension and how to install it–install.rdf (see http://developer.mozilla.org/en/docs/Install_Manifests for details):

 
 
   
     firstxpcom@senecac.on.ca
     firstxpcom
     0.1
     David Humphrey
     A Simple XPCOM Extension.
     http://zenit.senecac.on.ca/wiki
     
       
         {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 
         2.0
         3.0b2pre 
       
     
   
 

Building FirstXpcom

Now we’re ready to build our component. Add the following line to your .mozconfig file in order to include firstxpcom during the build process:

ac_add_options --enable-extensions=default,firstxpcom

Now you can (BUT DON’T, see below for quick way!!)re-build your tree (also known as “rebuilding world”) by doing:

$ cd mozilla
$ make -f client.mk build

BUT…this takes forever for it to actually reach your code, since it has to traverse the entire tree checking for changes. So, you can bypass the rest of the tree and go directly to your component’s build.

$ cd $(objdir)
$ ../build/autoconf/make-makefile extensions/firstxpcom

Now call make in $(objdir)/extensions/firstxpcom

$ cd $(objdir)/extensions/firstxpcom
$ make

This will create the public and src directories, as well as generate the Makefiles necessary in each. Go into the public directory and call make again, in order to have your .h and .cpp stubs generated (NOTE: this will cause errors, see below):

$ cd $(objdir)/extensions/firstxpcom/public
$ make

If all goes well, you’ll see a hundred lines or so of output from make, ending in an error (NOTE: make will error out, since we have no source files yet). We can safely ignore most of it, but a few lines are significant at this point:

IFirstXpcom.idl
../../../dist/bin/xpidl.exe -m header -w -I../../../../extensions/firstxpcom/public -I../../../dist/idl -o _xpidlgen/IFirstXpcom

Here we can see the build processing our IDL file. As a result of this first (partially) successful run of make, exported and generated header files (i.e.,from our IDL) will be placed in $(objdir)/dist/include/firstxpcom.

Within $(objdir)/dist/include/firstxpcom/IFirstXpcom.h you’ll see the following block of code:

#if 0
/* Use the code below as a template for the implementation class for this interface. */
...
/* End of implementation class template. */
#endif

The code in the middle of this block is what you want to use as the basis for implementing your .cpp file (and .h if you choose to split it out, which we won’t). Copy and paste this implementation stub into the following file: mozilla/extensions/firstxpcom/src/FirstXpcom.cpp

You’ll need to do a search/replace on _MYCLASS_ and change it to the name of your class, in our case, FirstXpcom.

Now you can try and re-run make for your extension:

$ cd $(objdir)/extensions/firstxpcom
$ make

This will produce a host of errors, mostly related to the fact that we don’t have proper includes set-up and it can’t find declarations it needs. You need to add an include for your interface’s generated .h file:

#include "IFirstXpcom.h"

Re-run make.

As an aside, and while you are thinking about Makefiles, you might take a moment to read bug 371201. This is a bug that was identified while the author was trying to debug his Makefile.in files. Ted Mielczarek (ted on IRC) was finally able to spot the problem–a trailing space on XPI_NAME. I share this anecdote as a way to introduce https://bugzilla.mozilla.org, to emphasize the necessity of the community, and to show the kind of problems that one can have writing files for the build system.–UPDATE: this bug has now been fixed by Ted (March 26, 2007).

Examining IFirstXpcom.h

Let’s examine the code more closely and try to make sense of things. Here is the code in $(objdir)/dist/include/firstxpcom/IFirstXpcom.h:

/*
 * DO NOT EDIT.  THIS FILE IS GENERATED FROM c:/temp/proj/ff-trunk/mozilla/obj-fftrunk/extensions/firstxpcom/public/../../../../extensions/firstxpcom/public/IFirstXpcom.idl
 */

#ifndef __gen_IFirstXpcom_h__
#define __gen_IFirstXpcom_h__

#ifndef __gen_nsISupports_h__
#include "nsISupports.h"
#endif

/* For IDL files that don't want to include root IDL files. */
#ifndef NS_NO_VTABLE
#define NS_NO_VTABLE
#endif

/* starting interface:    IFirstXpcom */
#define IFIRSTXPCOM_IID_STR "78af1749-014a-47aa-baec-2669670b7601"

#define IFIRSTXPCOM_IID \
  {0x78af1749, 0x014a, 0x47aa, \
    { 0xba, 0xec, 0x26, 0x69, 0x67, 0x0b, 0x76, 0x01 }}

class NS_NO_VTABLE IFirstXpcom : public nsISupports {
 public: 

  NS_DECLARE_STATIC_IID_ACCESSOR(IFIRSTXPCOM_IID)

  /* attribute AString name; */
  NS_IMETHOD GetName(nsAString & aName) = 0;
  NS_IMETHOD SetName(const nsAString & aName) = 0;

  /* long add (in long a, in long b); */
  NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) = 0;

};

  NS_DEFINE_STATIC_IID_ACCESSOR(IFirstXpcom, IFIRSTXPCOM_IID)

/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_IFIRSTXPCOM \
  NS_IMETHOD GetName(nsAString & aName); \
  NS_IMETHOD SetName(const nsAString & aName); \
  NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval); 

/* Use this macro to declare functions that forward the behavior of this interface to  another object. */
#define NS_FORWARD_IFIRSTXPCOM(_to) \
  NS_IMETHOD GetName(nsAString & aName) { return _to GetName(aName); } \
  NS_IMETHOD SetName(const nsAString & aName) { return _to SetName(aName); } \
  NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) { return _to Add(a, b, _retval); } 

/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
#define NS_FORWARD_SAFE_IFIRSTXPCOM(_to) \
  NS_IMETHOD GetName(nsAString & aName) { return !_to ? NS_ERROR_NULL_POINTER :  _to->GetName(aName); } \
  NS_IMETHOD SetName(const nsAString & aName) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetName(aName); } \
  NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) { return !_to ?  NS_ERROR_NULL_POINTER : _to->Add(a, b, _retval); } 

#if 0
/* Use the code below as a template for the implementation class for this interface. */

/* Header file */
class _MYCLASS_ : public IFirstXpcom
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_IFIRSTXPCOM

  _MYCLASS_();

private:
  ~_MYCLASS_();

protected:
  /* additional members */
};

/* Implementation file */
NS_IMPL_ISUPPORTS1(_MYCLASS_, IFirstXpcom)

_MYCLASS_::_MYCLASS_()
{
  /* member initializers and constructor code */
}

_MYCLASS_::~_MYCLASS_()
{
  /* destructor code */
}

/* attribute AString name; */
NS_IMETHODIMP _MYCLASS_::GetName(nsAString & aName)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP _MYCLASS_::SetName(const nsAString & aName)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* long add (in long a, in long b); */
NS_IMETHODIMP _MYCLASS_::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* End of implementation class template. */
#endif

#endif /* __gen_IFirstXpcom_h__ */

What things do you notice? What strikes you?

Use of header guards

Header guards (see Include Guards) are a portable technique for ensuring that includes or defines are only done once, for example, that nsISupports.h only be included once:

#ifndef __gen_nsISupports_h__
#include "nsISupports.h"
#endif

Another way of doing this, especially with the Microsoft compiler, is to use

#pragma once

But this is not portable, and therefore Mozilla doesn’t use it.

Use of macros

Mozilla provides many convenience macros to help C++ developers do common tasks more efficiently. Much of the code involved in making a module/component is generic, and has to be repeated every time. You can spot macros in the code by the fact that they are all capitals, and often begin with NS_*. Examples include:

NS_DECL_ appended with any interface name in all caps will declare all of the methods of that interface for you (nsIFoo –> NS_DECL_NSIFOO). Looking at the code above shows you how this is possible. For example, NS_DECL_NSIFOO will declare all of the methods of nsIFoo, provided that it exists and that nsIFoo.h was generated by the XPIDL compiler. Consider the following real class:

class myClass : public nsISomeClass
{
  public:
    NS_DECL_ISUPPORTS		// declares AddRef, Release, and QueryInterface
    NS_DECL_NSISOMECLASS	// declares all methods of nsISomeClass 

    myClass();
    virtual ~myClass() {}
};

The declaration of nsISomeClass doesn’t include any methods other than the constructor and destructor. Instead, the class uses the NS_DECL_ macro

Also note the use of NS_METHOD and NS_METHODIMP for return type signatures. All XPCOM functions are required to return a result code (nsresult, a integer), which indicates whether or not the function worked (e.g., NS_OK).

Next there is NS_IMPL_ISUPPORTS1. This macro implements the nsISupports interface for you, specifically the implementation of AddRef, Release, and QueryInterface for any object.

NS_IMPL_ISUPPORTS1(classname, interface1)

If your class implements more than one interface, you can simply change the number 1 in the macro to the number of interfaces you support and list the interfaces, separated by commas. For example:

NS_IMPL_ISUPPORTS2(classname, interface1, interface2)
NS_IMPL_ISUPPORTSn(classname, interface1, ..., interfacen)

These macros automatically add the nsISupports entry for you, so you don’t need to do the following:

NS_IMPL_ISUPPORTS2(classname, interface1, nsISupports)

As an example, consider mozilla/xpcom/io/nsBinaryStream.cpp:

NS_IMPL_ISUPPORTS3(nsBinaryOutputStream, nsIObjectOutputStream, nsIBinaryOutputStream, nsIOutputStream)

Use of never before-seen types

A quick scan of the code also reveals types that will be unfamiliar, including: nsAString, nsresult, and PRInt32. What are these?

Because Mozilla is cross-platform almost all of the standard types you are used to have Mozilla-specific versions. For example, PRInt32, which is defined as part of the Netscape Portable Runtime (hence the PR prefix), is a signed 32-bit integer, no matter the OS you are using (see http://developer.mozilla.org/en/docs/PRInt32). Depending on the platform you use this could mean a regular int or a long. The same is true of strings (Mozilla has it’s own string classes — see http://developer.mozilla.org/en/docs/XPCOM_string_guide) because of the need for multi-language support and other things necessary to make Mozilla’s products work around the world.

At first there are so many of these to learn. But you quickly get accustomed to them, and looking at how other people code (via lxr) can help you in this process.

Strange return types

You’ll also notice differences between the original IDL and the autogenerated C++ signatures. In our IDL file, the IFirstXpcom::Add method took two longs and returned a long. However in the C++ code stub it says something different:

 /* XPIDL -- long add (in long a, in long b); */
 NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) = 0;

The return value of XPCOM methods generated from XPIDL is always of the type nsresult, and the small macro used in these expansions, NS_IMETHOD, actually represents nsresult. nsresult is returned even when in XPIDL you specify that the method return a void. If your IDL requires a return type, as ours does, that value will be added as a final parameter to the call list–in this case PRInt32 *_retval.

There are other things you should know about making your code compatible on all of the supported Mozilla platforms. You can read about them here: http://www.mozilla.org/hacking/portable-cpp.html.

Module Code

We now need to write a bit of code to get our component registered. Components reside in modules, and those modules are defined in shared library files (i.e., DLLs or DSOs) that typically sit in the components directory of an XPCOM application.

When you build a component or module and compile it into a library, it must export a single method named NSGetModule. This NSGetModule function is the entry point for accessing the library. It gets called during registration and unregistration of the component, and when XPCOM wants to discover what interfaces or classes the module/library implements.

In addition to implementing the module code (i.e., nsIModule), we also have to write code to allow our component to be created at runtime based on an interface rather than concrete types–essentially, abstracting the process of creation so that clients don’t have to know about real classes underneath the interfaces. This means implementing the nsIFactory interface.

Together, these two interfaces will require us to write hundreds lines of code, the majority of which is generic boilerplate code. In order to simplify the work component developers must do, a number of macros help us with this task:

  • NS_GENERIC_FACTORY_CONSTRUCTOR
  • NS_IMPL_NSGETMODULE
#include "nsIGenericFactory.h"
...
// This will result in a function named FirstXpcomConstructor.
NS_GENERIC_FACTORY_CONSTRUCTOR(FirstXpcom)

// 19f3ef5e-759f-49a4-88e3-ed27f9c83011 
#define FIRSTXPCOM_CID \
  {0x19f3ef5e, 0x759f, 0x49a4, \
      { 0x88, 0xe3, 0xed, 0x27, 0xf9, 0xc8, 0x30, 0x11} }

static const nsModuleComponentInfo components[] =
{
  { "FirstXpcom",
    FIRSTXPCOM_CID,
    "@senecac.on.ca/firstxpcom;1",
    FirstXpcomConstructor
  }
};

NS_IMPL_NSGETMODULE(FirstXpcomModule, components)

First, we have to include nsIGenericFactory.h in order to get NS_GENERIC_FACTORY_CONSTRUCTOR. Now we can add the following line, which will generate a function called FirstXpcomConstructor:

NS_GENERIC_FACTORY_CONSTRUCTOR(FirstXpcom)

Note: we also could have provided an initialization function to be called after our object gets allocated (i.e., FirstXpcom->Init()):

NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsYourConcreteClassName, Init)

Next, we need to create proper identification for our component’s module so that it can be passed to the module implementation macro, NS_IMPL_NSGETMODULE. This macro takes an array of nsModuleComponentInfo so that you can define more than one component per module (remember that a module is a collection of components, and every component belongs to a module so it can get loaded by the system).

Start by generating another uuid, which will be used for identifying our component/class (i.e., we can’t re-use our interface’s uuid), for example:

19f3ef5e-759f-49a4-88e3-ed27f9c83011

Now write a define to make it easier to pass this Class ID around:

#define FIRSTXPCOM_CID \
  {0x19f3ef5e, 0x759f, 0x49a4, \
      { 0x88, 0xe3, 0xed, 0x27, 0xf9, 0xc8, 0x30, 0x11} }

Then we can populate our array with a single entry for the FirstXpcom component:

static const nsModuleComponentInfo components[] =
{
  { "FirstXpcom",			// descriptive name
    FIRSTXPCOM_CID,			// CID from above
    "@senecac.on.ca/firstxpcom;1",	// Contract ID
    FirstXpcomConstructor		// Factory Constructor
  }
};

The last two entries need some explanation. The Component ID is a human-readable string that clients can use to get/create an instance of your class. We’ll see how to do this later on. Here is an example Component ID and what it means:

"@mozilla.org/network/ldap-operation;1"
  • domain = @mozilla.org
  • module = network
  • component = ldap-operation
  • version = 1

The final line, the constructor, is the name of the constructor automatically generated by NS_GENERIC_FACTORY_CONSTRUCTOR. It will be the name of your concrete class followed by “Constructor,” in our case FirstXpcomConstructor.

And that’s it for the module/factory code.

FirstXpcom.cpp

All that remains is our implementation. Here is the final version of FirstXpcom.cpp (emphasis added to highlight changes):

#include  // for printf()
#include "IFirstXpcom.h" // the CPP .h generated from our .idl
#include "nsIGenericFactory.h" // for NS_GENERIC_FACTORY_CONSTRUCTOR()
#include "nsStringAPI.h" // for nsString

class FirstXpcom : public IFirstXpcom
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_IFIRSTXPCOM

  FirstXpcom();

private:
  ~FirstXpcom();

protected:
  nsString mName;
};

NS_IMPL_ISUPPORTS1(FirstXpcom, IFirstXpcom)

FirstXpcom::FirstXpcom()
{
  /* member initializers and constructor code */
  mName.Assign(NS_LITERAL_STRING("FirstXpcom Component"));
}

FirstXpcom::~FirstXpcom()
{
  /* destructor code */
}

/* attribute AString name; */
NS_IMETHODIMP FirstXpcom::GetName(nsAString & aName)
{
  aName.Assign(mName);
  printf("FirstXpcom::GetName\n");
  return NS_OK;
}

NS_IMETHODIMP FirstXpcom::SetName(const nsAString & aName)
{
  mName.Assign(aName);
  printf("FirstXpcom::SetName\n");
  return NS_OK;
}

/* long add (in long a, in long b); */
NS_IMETHODIMP FirstXpcom::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)
{
  printf("FirstXpcom::Add(%d, %d)", a, b);
  *_retval = a + b;
  return NS_OK;
}

// This will result in a function named FirstXpcomConstructor.
NS_GENERIC_FACTORY_CONSTRUCTOR(FirstXpcom)

// 19f3ef5e-759f-49a4-88e3-ed27f9c83011 
#define FIRSTXPCOM_CID \
  {0x19f3ef5e, 0x759f, 0x49a4, \
      { 0x88, 0xe3, 0xed, 0x27, 0xf9, 0xc8, 0x30, 0x11} }

static const nsModuleComponentInfo components[] =
{
  { "FirstXpcom",
    FIRSTXPCOM_CID,
    "@senecac.on.ca/firstxpcom;1",
    FirstXpcomConstructor
  }
};

NS_IMPL_NSGETMODULE(FirstXpcomModule, components)

Time to call make again:

$ cd $(objdir)/extensions/firstxpcom
$ make

Assuming this works without errors, here’s what has happened:

  • Generated makefiles for your project were created in extensions/firstxpcom/ (remember, we’re under /mozilla/$(MOZ_OBJDIR)/.
  • Exported header files and generated header files (from IDL) in dist/include/firstxpcom/
  • Static libraries for your modules in dist/lib/ (in case other modules want to link statically instead of using XPCOM).
  • XPI file in dist/xpi-stage/firstxpcom.xpi.
  • Everything else in dist/bin/extensions/firstxpcom@senecac.on.ca

Testing FirstXpcom

Checking the Add-on Manager

We’ll write formal tests and code to use our component later. For now, make sure it gets loaded into Firefox and is visible in the Addon Manager. Run Firefox and make sure you can see your extension in the addon manager:

$ cd $(objdir)/dist/bin
$ export MOZ_DEBUG_BREAK=warn
$ firefox.exe -Profilemanager -no-remote

Accessing FirstXpcom from the JavaScript Shell

Now let’s try and access this from JavaScript in the browser. If you haven’t done so already, download and install the Extension Developer’s extension. This will allow you to use the JavaScript Shell inside the browser, making it easy to try out the firstxpcom component.

Launch the JS Shell (Tools > Extension Developer > Javascript Shell) and write some code to access your XPCOM component. You can work interactively without having to define functions, write a complete extension, etc.:

  • Define our component’s ID so we can create an instance of it below.
const cid = "@senecac.on.ca/firstxpcom;1"
print(cid)
  • Now create an instance of our component. The value of obj will be nsISupports at this point (i.e., we can’t call IFirstXpcom’s methods yet).
var obj = Components.classes[cid].createInstance()
  • Next, take the the nsISupports object returned above and query it (i.e., see if it supports your interface type and if so, change to that interface) to IFirstXpcom, often referred to as QI (e.g., “…you need to QI it to IFirstXpcom…”).
obj = obj.QueryInterface(Components.interfaces.IFirstXpcom)
  • At this point we have the ability to use the IFirstXpcom methods and attributes:
var sum
sum = obj.add(4,5)

var name
name = "FirstXpcom!"

obj.name = name
print(obj.name)
alert(obj.name)

When you run this code, also notice how your C++ printf statements are causing messages to stdout in your console window (you may need to scrollback through all the other messages to find them).


An introduction to XPCOM

July 14, 2008

What’s XPCOM, you ask? XPCOM, which stands for Cross Platform Component Object Model, is a framework for writing cross-platform, modular software. As an application, XPCOM uses a set of core XPCOM libraries to selectively load and manipulate XPCOM components. XPCOM components can be written in C, C++, and JavaScript, and they can be used from C, C++, and JavaScript with extensions for Perl and Python that are under development (.

In addition to modularity, XPCOM offers agility across platforms. It supports just about any platform that hosts a decent C++ compiler, including:

  • Microsoft Windows (all flavors)
  • Linux
  • HP-UX
  • AIX
  • Solaris
  • OpenVMS
  • MacOS
  • BSD

The tools you need to write XPCOM software are: a C++ compiler, a Perl interpreter, and some GNU tools.

Some applications that use XPCOM include:

Although it isn’t an XPCOM application, Adobe Acrobat uses a modified version of the same JavaScript engine bundled with XPCOM. The point here is that the code base for XPCOM is well tested and widely used.

Microsoft COM and XPCOM

You might be wondering whether XPCOM is like Microsoft COM. The short answer is yes, and no. Component proxy support is one area of distinction. A component proxy is a fake component whose purpose is to impersonate another component that, for some reason, cannot be accessed directly by the code that wishes to use it. For example, the code may not be able to access a component directly because the component exists in another process, or on another machine.

Microsoft COM supports an elaborate proxy mechanism for coordinating how different types of applications talk to components, including those that run as separate programs or even on different machines. MSCOM allows you to create components with different threading models or restrict a component to a specific threading model. Components can be created as in process (running inside the application) or out of process (runs as a separate application). A single threaded component must have its own thread, and other threads must use a proxy mechanism to access it. Apartment threaded components can share a thread but still need a proxy. Free threaded components need no proxy mechanism inside the same process. It’s this built-in proxy mechanism in MSCOM that provides the appropriate amount of thread safety for components that have their own threading constraints.

XPCOM is tailored toward providing modular component support at the application level, so proxy services only support multiple threads sharing an otherwise non-reentrant component. If you wish to access a component remotely, you will have to write your own proxy to marshal data back and forth to the remote object. There are some existing components that can help you do this, so it isn’t actually as tough as it sounds.

At the microscopic level, XPCOM and MSCOM appear identical: Both are interface based and require every interface to derive from the same base interface. This base interface defines the three methods QueryInterface, AddRef, and Release. Despite this common ideological heritage, MSCOM and XPCOM components are not compatible or interchangeable — some sort of wrapper or glue code is required for the two to operate together. The embedding wrapper for Mozilla is a good example. It allows the browser engine to appear as an MSCOM ActiveX control while the browser engine internally operates on XPCOM components.

The biggest contrast between XPCOM and MSCOM is that XPCOM technology is open source. If you are developing MSCOM software and you are having trouble trying to understand the differences in how the MSCOM libraries load and create your components, you are at the mercy of whatever documentation is available. Fortunately, Microsoft has gone to great pains to evangelize their architecture and provide good documentation. However, if Microsoft changes the behavior of these system-level libraries, it can affect the behavior of your components, and the behavior of the applications that use them.

In contrast, the source code for the libraries that make up the XPCOM architecture are fully available for you to inspect, trace, and debug alongside your own application code. You can even modify the code base to extend the architecture yourself, as opposed to waiting for Microsoft to extend it for you (as they did when they evolved MSCOM from plain COM, to DCOM, and then COM+).

If you are not already familiar with open-source software, you may want to investigate some other notable open-source projects, such as: the Free Software Foundation’s family of GNU projects, OpenBSD, Linux, OpenLDAP, OpenSSL, Apache, and others (see Resources).

XPCOM, threads, CORBA, and more

You will also need to understand how XPCOM handles remote objects, threads, and scripting. Some XPCOM technology is inherited from OMG CORBA. CORBA is a platform- and language-neutral component technology standardized by the Object Management Group. It includes an overall architecture for procedure calls to remote objects, an Interface Definition Language (similar to that of COM and XPCOM), and a broad set of common object services.

Strictly speaking, XPCOM does not support remote objects like CORBA, but neither does XPCOM prevent you from writing a component that uses a socket or other means to talk to another component. Many XPCOM applications make use of HTTP as a means of issuing remote procedure calls to other components hosted on a Web server. There are even some components available for supporting SOAP. Another link to CORBA is XPCOM’s IDL (Interface Definition Language) compiler. Called XPIDL, it was derived from an open-source CORBA IDL compiler.

XPCOM does support threads. However, thread-safe components are the exception rather than the norm as most components are written to coexist inside the same main application thread. Components can be coded thread safe, and XPCOM uses a simple scheme to determine whether a component advertises itself as thread safe.

Thread support is well represented in XPCOM even on platforms that offer little or no direct thread support. XPCOM supports scripting through an additional layer (called XPConnect) that includes a JavaScript engine and a type library mechanism. This allows JavaScript code to manipulate XPCOM components and even allows components to be implemented in JavaScript, and accessible to C++ code.

Getting started with XPCOM

Suppose the company’s CTO asks you to be lead developer on your own XPCOM project. Here’s what you and any prospective team members will need to know to be competent for such a project. The programmers in your group will need to know C and C++ well. XPCOM makes use of C-style macros and C++ templates for smart pointers. Someone unfamiliar with these will have a hard time understanding the existing Mozilla code base, which serves as a giant living body of sample source code.

Anyone with any flavor of COM experience is a big plus — but even so, there will be a learning curve both in the coding infrastructure (templates and macros) and in the actual development tools. The body of code is robust enough that there is bound to be something the average programmer hasn’t seen before. If you are lucky, you can find someone — even an outside consultant — with some XPCOM experience to serve as a mentor to help new project members along and expedite their proficiency.

Barring that, the mozilla.org Web site is an excellent resource for information, as are the Mozilla newsgroups where developers like you and I can post technical questions, submit code fragments for review, and voice opinions on the future direction of XPCOM. Beware that a reorganization of the newsgroups is imminent — but you can expect a timely announcement on the Web site that will describe the changeover.

Here are some of the most helpful sites:

In addition to C++, you and your fellow developers need to know how to use an IDL compiler and understand the core XPCOM interface. You should also be able to describe the purpose of the interface methods QueryInterface, AddRef, and Release (in your sleep, and backwards and forwards).

You’ll need to understand the difficult component topic of aggregation. Aggregation is a means for placing a component inside another larger component where the larger component delegates the responsibility of some of its interfaces to the internal component. This is nothing more than information hiding, which is one of the tenets of object-oriented programming. The issue of aggregation arises from the fact that all XPCOM interfaces must include the QueryInterface method. This means that your code, when using a component, has the ability to switch from one interface to another. This creates a problem when trying to write a new component that extends another, existing component. The QueryInterface method on the pre-existing component must somehow be able to respond to requests for new, additional interfaces introduced by the new derived component without any prior knowledge of the new code. If that sounds a bit wicked, it is.

Finally, your project’s testing and QA team members will need to know how to write shell scripts and JavaScript. They will also need a working knowledge of the operating systems your cross-platform project intends to support. Their scripting knowledge will help expedite the writing of test scripts, and automate regression testing.

Although it doesn’t guarantee success, having these skills will allow your team — whether one person or many — to be productive in leveraging what XPCOM has to offer.


Creating Universal Build of XULRunner

October 2, 2007

It is possible to build XULRunner as a universal binary that runs natively on both PowerPC and Intel processors running Mac OS X.

Prerequisites

 **  XULRunner 1.8.0.9 (developer preview release) Source Code

 **  Mac OS X 10.4.9 (Tiger)

 **  XCode Tools 2.4.1

 **  Fink ,  libIDL , gLib.

Note : In my previous blog i’ve given detailed documentation on installing fink.  Once you have setup the fink , issue the following command in the terminal to install the libIDl , gLib ( if you don’t have already).libIDL is included in the ORBit installation

$ sudo apt-get install orbit orbit-dev glib

Configuration

When preparing your own .mozconfig file, you must source the $topsrcdir/build/macosx/universal/mozconfig fragment. It should be sourced after any product-specific mozconfig, in case it needs to override any options.

Universal binaries must be built as objdir builds, so MOZ_OBJDIR must be set. The location of your objdir is unimportant, so long as you provide one.

Here is a sample .mozconfig suitable for building a universal binary of XULRunner in a release configuration:

. $topsrcdir/xulrunner/config/mozconfig
. $topsrcdir/build/macosx/universal/mozconfig
ac_add_options --enable-optimize=-O2
ac_add_options --disable-shared
ac_add_options --enable-shared
ac_add_options --disable-tests
ac_add_app_options ppc --enable-prebinding
ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.4u.sdk
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/../build


Building

Once the configuration is in place, building Mozilla as a universal binary is as easy as performing an ordinary build. Type:

$ make -w -f client.mk build

The source code required for your build will be checked out and
compiled. Two build passes are made: one to compile Mozilla for
PowerPC, and another for Intel processors. Understandably, this process
takes approximately twice as long as compiling for a single processor.
After both passes are complete, the results are automatically merged
into a single universal binary.

Results of a Build

Two subdirectories are created in your objdir: ppc and i386.
Each of these directories contains a complete processor-specific build.
The merged universal binary is placed in your objdir, at ppc/dist/universal with a symbolic link at i386/dist/universal.

Packaging

Create a chown_root.c file with following content.( This file can be created in any directory )

#include <unistd.h>
   
   int main(int argc, char **argv)
   {
      if (argc != 2)
        return 1;
   
      return execl(“/usr/sbin/chown”,
                   “/usr/sbin/chown”, “-R”, “-h”, “root:admin”, argv[1], (char*) 0);
   }

Create a chown_revert.c file with following content.( This file can also  be created in any directory )

 #include <unistd.h>
 #include <stdio.h>
 int main(int argc, char **argv)
 {
    if (argc != 2)
       return 1;
  
     uid_t realuser = getuid();
     char uidstring[20];
     snprintf(uidstring, 19, “%i”, realuser);
     uidstring[19] = ”;
  
     return execl(“/usr/sbin/chown”,
                  “/usr/sbin/chown”, “-R”, “-h”, uidstring, argv[1], (char*) 0);
   }

Use gcc to compile the above files

$ gcc -o chown_root chown_root.c

$ gcc -o chown_revert chown_revert.c

Export the above executable as …

$ export CHOWN_ROOT=”absolute_path_to_your_chown_root_binary”
$ export CHOWN_REVERT=”absolute_path_to_your_chown_revert_binary”

When configured as a universal binary, the
packaging phase will produce a disk image containing the merged
universal binary. In order to perform the packaging phase, you must
keep the new objdir structure in mind. If you had used the sample .mozconfig above, you would build a universal disk image of XULRunner by typing:

$ make -C ../build/ppc/xulrunner/installer

The disk image will be produced in ../build/ppc/dist. You could just as easily substitute i386 for ppc, this only affects the location that the disk image is produced in.

To bypass universal packaging, and create a disk image
containing the application for a single processor only, you can
override the UNIVERSAL_BINARY variable, setting it to
empty. This will package Firefox for Intel processors into a disk
image, the result will not launch at all on PowerPC:

$ make -C ../build/i386/browser/installer UNIVERSAL_BINARY=

Thats it we have created the Universal build of XULRunner ( 1.8.0.9 version ) .

Blogged with Flock

Tags:


First XULRunner Application

March 11, 2007

This article explores the Mozilla platform by building a basic
desktop application using XULRunner. Given that Firefox, Thunderbird
and the rest of the Mozilla suite is written using the platform, it a
safe bet that it can be used to build a basic application.

I want to build a simple XUL-based desktop application. If
you’re going to build a XUL-based desktop application, you’ll probably
need to install XULRunner. Let’s start by installing XULRunner
installed and making sure it runs a bare-bones application.

Step 1: Download XULRunner

You can find a download link on the main XULRunner page here on MDC.

The XULRunner download for Windows is a zip file, not a true
install. As a developer, I like the idea that XULRunner only needs to
be unzipped onto my machine. I am assuming that it doesn’t need to hook
into my Windows system and that’s a good thing.

The Mac version of XULRunner is distributed as a standard Mac OS X installer.

Step 2: Install XULRunner

On Windows, unzip the archive someplace reasonable. I unzipped it to a new C:\program files\xulrunner folder. Pretty simple so far. On the Mac, just run the installer, which installs XULRunner as XUL.Framework in the /Library/Frameworks directory.

Time to start a simple, bare bones application shell. Call it a XUL “Hello World” if you want.
It is definitely worth reading. Using the tutorial, I created a simple
bootstrap application.

Step 3: Create the application folder struture

On Windows, I created the root in a new c:\program files\xulapp folder, but you can create it wherever you like. Here is the subfolder structure:

/xulapp

   /chrome

     /content

       main.xul

     chrome.manifest

   /defaults

     /preferences

       prefs.js

   application.ini

Notice that there are 4 files in the folder structure: application.ini, chrome.manifest, prefs.js, and main.xul.

Step 4: Set up application.ini

The application.ini
file acts as the XULRunner entry point for your application. It seems
to be used to configure how your application intends to use the
XULRunner platform as well as configure some information that XULRunner
uses to run your application. Here is mine:

[App]

 Vendor=Finkle

 Name=Test App

 Version=1.0

 BuildID=20060101

 Copyright=Copyright (c) 2006 Mark Finkle

 ID=xulapp@starkravingfinkle.org[Gecko]

 MinVersion=1.8

 MaxVersion=1.8

You can find more information about the application.ini file in the article XULRunner:Deploying XULRunner 1.8.

Step 5: Set up the chrome manifest

The chrome manifest
file is used by XULRunner to define specific URI’s which in turn are
used to locate application resources. This will become clearer when we
see how the “chrome://” URI is used. Applications can be distributed
compressed in a JAR file or uncompressed as folders and files. I am
using the uncompressed method for now. Here is my manifest:

 content myapp file:content/

Note: Make sure your application name is lowercase and larger than 3 characters

Step 6: Set up preferences

The prefs.js file tells XULRunner the name of the XUL file to use as the main window. Here is mine:

 pref("toolkit.defaultChromeURI", "chrome://myapp/content/main.xul");

XULRunner preferences include:

toolkit.defaultChromeURI
Specifies the default window to open when the application is launched.
toolkit.defaultChromeFeatures
Specifies the features passed to window.open() when the main application window is opened.
toolkit.singletonWindowType
Allows configuring the application to allow only one instance at a time.

This is described in further detail in XULRunner:Specifying Startup Chrome Window.

Step 7: Create some XUL

Finally, we need to create a simple XUL window, which is described in the file main.xul. Nothing fancy here, just the minimum we need to make a window. No menus or anything:

<?xml version="1.0"?>

 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?><window id="main" title="My App" width="300" height="300"

 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

   <caption label="Hello World"/>

 </window>

Step 8: Run the application

The moment of truth. We need to get XULRunner to launch the bare-bones application. From a Windows command prompt opened to the C:\program files\myapp folder, we should be able to execute this:

            xulrunner.exe application.ini

Of course, xulrunner.exe must be in the PATH. Because of where I unzipped XULRunner, I could also try this if xulrunner.exe is not in the PATH:

       ..xulrunnerxulrunner.exe application.ini

On the Mac, you can run the application by opening a Terminal window, navigating to the myapp directory, and typing:

 /Library/Frameworks/XUL.framework/xulrunner-bin application.ini

You should now see a window that looks something like this. This particular screenshot is from Windows 2000.

XULSampleMyapp.png


XULRunner Installation & Uninstallation

March 11, 2007

Installing XULRunner

Mozilla provides XULRunner for Windows, Mac OS X, and Linux, in English:

Windows

  • Unpack the ZIP file to a new directory using an archive tool (7zip) is recommended. The following directory is recommended: C:\Program Files\Mozilla XULRunner\1.8.0.4 .
  • To register XULRunner with the system, open a command prompt and run xulrunner.exe --register-global (to register for all users) or xulrunner.exe --register-user (to register for one user only).

Mac OS X

  • Open the .pkg file within the installer and follow the directions.

Linux

  • Unpack the tarball to a new directory using tar -xzf xulrunner-1.8.0.4.en-US.linux-i686.tar.gz. The following directory is recommended: /opt/xulrunner/1.8.0.4 .
  • Register XULRunner with the system by running xulrunner --register-global (to install for all users, must be run as root) or xulrunner --register-user (to install for one user only).

Uninstalling XULRunner

Windows/Linux

  • From a command prompt, run xulrunner --unregister-global or xulrunner --unregister-user to unregister XULRunner just as you registered it during installation.
  • Remove the XULRunner directory.

Mac OS X

If you have multiple versions of XULRunner installed on Mac OS X, it is not possible to uninstall only one version.

  • To remove all installed versions of XULRunner, remove the /Library/Frameworks/XUL.framework directory.

XULRunner System Requirement

March 11, 2007

Windows

Minimum System Requirements

  • 233 Mhz processor
  • 64 MB of RAM
  • 50 MB of free disk space
  • Microsoft Windows 98

Mozilla Recommends

  • 500 Mhz processor
  • 256 MB of RAM
  • 100 MB of free disk space
  • Microsoft Windows XP

Mac

Minimum System Requirements

  • PowerPC G3 processor
  • 128 MB of RAM
  • 75 MB of free disk space
  • Mac OS X 10.2.x

Mozilla Recommends

  • PowerPC G4 or Intel processor
  • 512 MB of RAM
  • 150 MB of free disk space

Linux

Minimum System Requirements

  • 233 Mhz processor
  • 64 MB of RAM
  • 50 MB of free disk space
  • Linux kernel 2.2.14 (with glibc 2.3.2, XFree86-3.3.6, gtk+2.0, fontconfig/xft and libstdc++5)

Mozilla Recommends

  • 500 Mhz processor
  • 256 MB of RAM
  • 100 MB of free disk space
  • a modern Linux distribution

Introduction to XULRunner

March 11, 2007

XULRunner is a product in development which will serve as a runtime environment for XUL applications. It replaced or renamed the Gecko Runtime Environment. All XUL-based applications like Mozilla Firefox, Mozilla Thunderbird, Democracy Player and Songbird

will be able to run on XULRunner. It will provide mechanisms for
installing, deploying, upgrading, and uninstalling these applications.

The first stable developer preview of XULRunner was released in February 2006.

XULRunner 1.9 will be the first production release of XULRunner, and will be used and shipped by Firefox 3
(Q4 2007). The full planned featureset of XULRunner including
application management and embedding APIs will be available in this
release.

What is XULRunner

XULRunner is a Mozilla runtime package that can be used to bootstrap
XUL+XPCOM applications that are as rich as Firefox or Thunderbird. It
is similar to other existing runtime applications such as J2SE Java
Runtime Environment (JRE). It provides an innovative technology that
developers can use to enrich and integrate their desktop applications.

This runtime package provides a way for installing, upgrading,
and uninstalling XULRunner applications. XULRunner will also provide
libxul, a solution which allows the embedding of Mozilla technologies
in other projects and products. These applications can be written in
any Mozilla supported technologies. Some of these technologies are the
following:

  • HTML
  • XHTML
  • SVG
  • XUL

XULRunner application is an alternative to avoid the use of Firefox.
The following are the trade offs of using a XULRunner application:

Pros

  • Runs on its own independent process
  • Does not require Firefox to run
  • Markup based UI (like XAML)
  • Allows applications to be cross platform

Cons

  • Auto-update code would need to be written
  • Installation files are larger to download when including XULRunner binaries (+13MB)

Note: The listed pros and cons are not all the trade offs of
using XULRunner. Instead these are the trade offs of using XULRunner
application as oppose to Firefox.

What XULRunner Provides

The goal of XULRunner is to provide a solution for deploying XUL applications (primarily
Firefox and Thunderbird), as well as providing an embedding mechanism.
The following features are either already implemented or planned:

Contents

  • 1 Gecko Features
  • 2 User Interface Features
  • 3 Embedding APIs
  • 4 The “Maybe” List
  • Gecko Features

    • XPCOM
    • Networking
    • Gecko rendering engine
    • DOM editing and transaction support (no UI)
    • Cryptography
    • XBL (XBL2 planned)
    • XUL
    • SVG
    • XSLT
    • XML Extras (XMLHttpRequest, DOMParser, etc.)
    • Web Services (SOAP)
    • Auto-update support (not yet complete)
    • Type ahead find toolbar
    • History implementation (the places implementation in the 1.9 cycle)
    • Accessibility support
    • IPC services for communication between gecko-based apps (not yet complete)
    • Storage/sqlite interfaces (not yet turned on by default)

    User Interface Features

    The following user interface is supplied by XULRunner, and may be overridden by embedders under certain circumstances:

    • APIs and user interface for installing, uninstalling, and upgrading XUL applications. See the wikimo:XUL:Installation Story.
    • Extension Manager
    • File picker (uses native OS filepicker as appropriate)
    • Find toolbar
    • Helper app dialog/UI
    • Security UI (maintenance of SSL keychains, etc)

    Embedding APIs

    The following embedding APIs are provided by XULRunner:

    • Cross-platform embedding (XRE_InitEmbedding)
    • JavaXPCOM embedding
    • gtkmozembed (Linux only)
    • ActiveX control (Windows only) (not yet complete)
    • NSView-based-widget (Mac OS X only) (not yet complete

    The “Maybe” List

    The following features have been discussed and may be included if developer time permits and code size is controlled:

    • LDAP support
    • Spellchecking support (with or without dictionaries provided) see bug 285977
    • Core support for profile roaming (with application-specific extensibility)
    • PyXPCOM embedding (not yet complete)

    XULRunner will not supply:

    • Bookmarks or History UI (must be managed by the application/embedder)
    • XForms (XForms will be available as an extension)