XPCOM Brown Bag I

Suresh Duddi <dp@netscape.com>
August 17, 1999 

Terminology

 
Interface Contract betwen the implementation and usage. A pure virtual abstract base class with no data members. eg. nsIZip
IID Interface ID {xxxxx-xxx-xxx-xxxxxx} a unique number that identifies the Interface being talked about
nsISupports The mother of all interfaces. All interfaces ultimately inherit from this. Provides refcounting. The IID and definition has been carefully choosen so as to be binary compatible with COM.
Component An implementation of a set of interfaces identified by a CLSID
Object An instance of a Component
CLSID Component ID  {xxxxx-xxx-xxx-xxxxxx} a unique number that identifies a component
Module A packaging of a set of Components (ie) a DLL
Factory An object whose sole purpose is creation of objects of a particular component. There exists only one factory for every Component (CLSID). The IID and definition has been carefully choosen so as to be binary compatible with COM. nsIFactory
ClassObject Same object as factory.
ProgID A String name for a Component.
ComponentManager Central Object of XPCOM that provides API for object creation and management.
ServiceManager A singleton manager. Holds and manages singleton references to objects for application. Going to be merged with the componentmanager.
Service A singleton object within an application.
Registry A hierarchical attribute-value pair storage.
XPIDL Cross Platform Interface Definition Language. Language for expressing interfaces.
Typelib A storage for meta information about interfaces. Interfaces expressed in IDL have their meta information maintained in Typelib automatically.
XPConnect Ability to call c++ implementations of interfaces expressed in IDL from javascript and viceversa.

An Interface

The Component

Object Creation

Object Release

NS_IF_RELEASE(obj);

It should be noted that release and addref are directly talking to the object with no intermediaries. The macro NS_*_RELEASE() set the object to NULL.

Component Registration Process

Module Unloading

Every module implements a CanUnload() function that returns a boolean of whether the module can be unloaded. This implies that the module needs to be counting all outstanding object and return PR_TRUE only if there are no outstanding objects served from within the module.

Unloading happens either on a Timer or on an explicit call to nsComponentManager::FreeLibraries(). The general logic is:

No assumptions can be made that the module will be unloaded if nsIModule::CanUnload() returns PR_TRUE. It is guaranteed that if nsIModule::CanUnload() returns PR_FALSE, the module will not be unloaded.

The Component Registry

Nothing but a persistent hiearchical store of attribute value pairs. It is the use of the registry by XPCOM that is very interesting. Physical location of the registry is in the <exedir>/component.reg

The xpcom hierarchy of the registry is considered to be opaque to components. Use the nsIComponentManager Api to register as opposed to meddling with the xpcom hierarchy in the registry directly.

mozregistry.dat is NOT the component registry. It is the application (apprunner) registry.

Old Method for Module definition

Previously module definition was scattered across many exported functions from a dll.
 NSGetFactory( ), NSCanUnload( ), NSRegisterSelf( ), NSUnregisterSelf( )
Now these are combined into a nsIModule

Please continue to use the old method until sample code using nsIModule is available.

ComponentManager vs ServiceManager

ServiceManager is a an object that holds instances to objects in a cache and manages them. It uses the ComponentManager to create an instance the first time an object is queried for. Lifetime of the instance is currently the lifetime of the app. We are working on what is required here and how to control the lifetime. Possbily merging ServiceManager with the ComponentManager.

From the components perspective there is nothing it does special to behave as a service. The application controls the creation of services by its usage or call to nsServiceManager::GetService() .Some components that want to enforce being a service return cached instances on nsComponentManager::CreateInstance() . We are working on a more elegant syntax and semantics for this. Post suggestions to newsgroup netscape.public.mozilla.xpcom (or Email mozilla-xpcom@mozilla.org) with suggestions.

ProgID vs CLSID

CLSID is a number identifying a specific implementation.

ProgID is a like a pointer to a CLSID. It is an opaque string to xpcom.It is used for two purposes.

  1. Implementation independence for clients: component://netscape/registry

  2. The CLSID associating itself to a ProgID can be changed. Hence if a new implementation with a new CLSID superceeds an older implementation, the client wont be tied to the older implementation if it uses the ProgID.
  3. CLSID switching: component://netscape/image/decoder&type=image/gif

  4. A client wants to create different objects based on a switch (the mimetype for the case of imagedecoders). A Progid is formed with a concatenation of a BASE_PROGID and the switch (mimetype) and an instance of that created. Components, when registering, associate their CLSID to specific progids.
NOTE: Only Clients that are adamant about the use of a specific implementation need to create instances using CLSID.

We encourage use of ProgID. This works well in the scriptable world too.

We are working on a ProgID syntax.

Steps for XPCOM Review

  1. Know your interfaces and objects.

  2. List the objects your component is serving. List the interfaces that it implements.
  3. List the objects that your component uses.
  4. http://www.mozilla.org/scriptable/interface-rules-we-break.html
  5. Do not switch over to using nsIModule yet. We will publish sample code in a week with guidelines.
  6. Use the above stated macros.
  7. http://www.mozilla.org/projects/xpcom/ - Watch for more documents here