The following describes how to create XPCOM components and provides a brief overview of how to use them.
var file = Components.classes["@mozilla.org/file/local;1"].createInstance();
The text in quotes is the contract ID, and the createInstance method creates a new instance of this component, in this case, a component representing a local file.
Some components are services, which should only be created once. Thus, you shouldn't use createInstance to create one, since that will create a new component every time. Instead, you should use the getService method which will ensure that only one object is created. If you try to get the same service again, the same object will be returned. There is currently no way to determine whether an object is a service or not -- the only way to tell is by the name. Services generally have the word Service or Manager in their name. Here is an example of creating a service, this time for the RDF service:
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService();
Each component implements a number of interfaces, each of which provides functionality. All components implement the base interface nsISupports, however they often support other interfaces as well. In order to call methods of an interface, you must first indicate which interface you want to use by calling QueryInterface on the component:
This line converts the RDF service to the nsIRDFService. interface. You can then call any of the methods that are supported by that interface. Since calling QueryInterface is usually called right after the component is created, a shortcut is available:
var file = Components.classes["@mozilla.org/file/local;1"]. createInstance(Components.interfaces.nsILocalFile);
This form of createInstance creates a component and converts it to the desired interface in one step.
Creating Components in C++
Components can be created in C++ using the do_CreateInstance function.
nsCOMPtr<nsILocalFile> theFile; theFile = do_CreateInstance("@mozilla.org/file/local;1");
This function creates a new component with the corresponding contract ID. The magic of nsCOMPtrs will handle QueryInterface for you. There is also a corresponding getService function as well:
nsCOMPtr<nsIRDFService> rdfService; rdfService = do_GetService("@mozilla.org/rdf/rdf-service;1");
If you are working with Mozilla source code, most components have a macro defined which can be used in place of the corresponding contract ID string. For example, NS_LOCAL_FILE_CONTRACTID may be used instead of "@mozilla.org/file/local;1".
In native code, function names always begin with a capital letter, even if the interface was defined with the name in lowercase. Attributes are retrieved and modified using methods of the form Get<attribute name> and Set<attribute name>. For example, to get an attribute called 'count' use the GetCount method.
The result of a interface's function is returned as the last argument to the function. The returned value of an interface function is an nsresult which is an integer error code. For instance to get a datasource from the RDF service:
nsCOMPtr<nsIRDFDataSource> dsource; nsresult rv = rdfService->GetDataSource("rdf:bookmarks", getter_AddRefs(dsource));
Although the GetDataSource interface is defined as returning a nsIRDFDataSource, it is returned as the last argument, and an success or error code is returned from the function. Note that some methods don't follow this convention, these are marked with [notxpcom] in the reference.