diff --git a/mozilla/xpcom/sample/nsSampleFactory.cpp b/mozilla/xpcom/sample/nsSampleFactory.cpp index 55972f628fb..f07483cf691 100644 --- a/mozilla/xpcom/sample/nsSampleFactory.cpp +++ b/mozilla/xpcom/sample/nsSampleFactory.cpp @@ -30,16 +30,53 @@ #include "nsIServiceManager.h" #include "nsXPComFactory.h" +/** + * IIDs and CIDs (aka CLSIDs) are 32 digit hexadecimal numbers, called Globally + * Unique IDs (GUIDs) as a whole. They should only be generated by a trusted + * guid generator. GUID generatoration algorithms rely on parameters such as + * the MAC address of your NIC, and the date/time of GUID creation to ensure + * that no two GUIDs are ever the same. The Windows program 'uuidgen' is one + * way to create these numbers. The Unix alternative is probably out there + * somewhere. + * + * NS_DEFINE_IID and NS_DEFINE_CID expand to define static IID/CID objects + * that will be used later. IID and CID objects are of the same type, the + * distinction between InterfaceID and ClassID is made strictly by what the + * ID represents, and not by any binary differences. + */ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); -static NS_DEFINE_CID(kSampleCID, NS_SAMPLE_CID); +static NS_DEFINE_CID(kSampleCID, NS_SAMPLE_CID); +/** + * SampleFactoryImpl is a factory capable of creating nsSampleImpl objects. + * It is the factory, as opposed to the class, which actually registers itself + * with the XPCOM runtime, in a conversation that goes something like, + * XPCOM: "Hello factory at , what can you do for me?", + * FACTORY: "Hello XPCOM, I can create the classes named :, + * and : and ...". This conversation is initiated when XPCOM calls + * into the static NSRegisterSelf function of the shared library that houses this + * factory. Once this factory is properly registered, XPCOM can work it's magic. + * After registration, any call into the Service Manager or Component Manager's + * CreateInstance method requesting a progID or CID that this factory has + * registered will cause XPCOM to call the static NSGetFactory function in + * the .so, .dll, .whatever associated with this factory (if it hasn't already + * done so), and then invoke the CreateInstance method of the resulting factory. + */ class SampleFactoryImpl : public nsIFactory { public: - SampleFactoryImpl(const nsCID &aClass, const char* className, const char* progID); + SampleFactoryImpl(const nsCID &aClass, const char* className, + const char* progID); + /** + * This macro expands into a declaration of the nsISupports interface. + * Every XPCOM component needs to implement nsISupports, as it acts + * as the gateway to other interfaces this component implements. You + * could manually declare QueryInterface, AddRef, and Release instead + * of using this macro, but why? + */ // nsISupports methods NS_DECL_ISUPPORTS @@ -54,6 +91,12 @@ protected: virtual ~SampleFactoryImpl(); protected: + /** + * When XPCOM calls into NSGetFactory, it informs us what kind of class + * it intends to create with this factory. CreateInstance does NOT get + * this information, so we need to record what kind of class CreateInstance + * should return for later reference. + */ nsCID mClassID; const char* mClassName; const char* mProgID; @@ -61,9 +104,17 @@ protected: //////////////////////////////////////////////////////////////////////// +/** + * All the constructor needs does is initailize reference counting and + * record the CID/ progID it should return when CreateInstance is called. + * Convention dictates a one-to-one mapping between progIDs and CIDs. Think + * of a CID as an IP address, and a progID as the canonical name. The + * class name is a more descriptive representation of the progID. Classnames + * do not have to be unique. + */ SampleFactoryImpl::SampleFactoryImpl(const nsCID &aClass, - const char* className, - const char* progID) + const char* className, + const char* progID) : mClassID(aClass), mClassName(className), mProgID(progID) { NS_INIT_REFCNT(); @@ -74,6 +125,16 @@ SampleFactoryImpl::~SampleFactoryImpl() NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction"); } +/** + * This is what a normal implementation of QueryInterface (sometimes + * abbreviated QI) actually looks like. Because this QI only supports + * nsISupports and nsIFactory, it, and the two NS_IMPL_* macros + * that follow it could actually be replaced with the macro + * NS_IMPL_ISUPPORTS(nsIFactory, nsIFactory::GetIID) as nsSample does + * in nsSample.cpp. + * The XPCOM homepage (www.mozilla.org/projects/xpcom) has another reference + * implementation of QueryInterface. + */ NS_IMETHODIMP SampleFactoryImpl::QueryInterface(const nsIID &aIID, void **aResult) { @@ -98,10 +159,22 @@ SampleFactoryImpl::QueryInterface(const nsIID &aIID, void **aResult) NS_IMPL_ADDREF(SampleFactoryImpl); NS_IMPL_RELEASE(SampleFactoryImpl); +/** + * The IID passed in here is for COM Aggregation. Aggregation deals with + * classes contained within other classes, a topic out of the scope of + * this sample. + * Notice that this CreateInstance is very methodical... It verifies that it + * has been asked to create a supported class, even though we only registered + * for one, and it calls QI on the newly created object, verifying that the + * created class can actually support the interface we thought it could. This + * is (probably) regarded as a good thing in CreateInstance, and even if you + * think you know whats going to happen in your CreateInstance, it's a good + * idea to follow this same formula. + */ NS_IMETHODIMP SampleFactoryImpl::CreateInstance(nsISupports *aOuter, - const nsIID &aIID, - void **aResult) + const nsIID &aIID, + void **aResult) { if (! aResult) return NS_ERROR_NULL_POINTER; @@ -134,6 +207,9 @@ SampleFactoryImpl::CreateInstance(nsISupports *aOuter, return rv; } +/** + * I'm really not sure what LockFactory would do if it were implemented :( + */ nsresult SampleFactoryImpl::LockFactory(PRBool aLock) { // Not implemented in simplest case. @@ -142,8 +218,11 @@ nsresult SampleFactoryImpl::LockFactory(PRBool aLock) //////////////////////////////////////////////////////////////////////// - - +/** + * The XPCOM runtime will call this to get a new factory object for the + * CID/progID it passes in. XPCOM is responsible for caching the resulting + * factory. + */ // return the proper factory to the caller extern "C" PR_IMPLEMENT(nsresult) NSGetFactory(nsISupports* aServMgr, @@ -155,7 +234,8 @@ NSGetFactory(nsISupports* aServMgr, if (! aFactory) return NS_ERROR_NULL_POINTER; - SampleFactoryImpl* factory = new SampleFactoryImpl(aClass, aClassName, aProgID); + SampleFactoryImpl* factory = new SampleFactoryImpl(aClass, aClassName, + aProgID); if (factory == nsnull) return NS_ERROR_OUT_OF_MEMORY; @@ -164,8 +244,21 @@ NSGetFactory(nsISupports* aServMgr, return NS_OK; } - - +/** + * When the XPCOM runtime is initialized, it searches the component directory + * for shared objects, and attempts to call NSRegisterSelf for each one it + * encounters. You are expected to register each component the factory can + * create as either a Service or a Component. By convention, Services are + * singletons, while Components are not. Services are managed by the + * Service Manager, and Components are managed by (what else?) the Component + * Manager. The Component Manager itself is a Service, and so you can + * retrieve it via the ServiceManager, as this function does. + * + * If you've gto some spare time, and _really_ want to see whats going on + * behind the scenes at registration time, soak up PlatformPrePopulateRegistry + * (and all the functions it calls) in + * mozilla/xpcom/components/nsComponentManager.cpp + */ extern "C" PR_IMPLEMENT(nsresult) NSRegisterSelf(nsISupports* aServMgr , const char* aPath) { @@ -187,7 +280,11 @@ NSRegisterSelf(nsISupports* aServMgr , const char* aPath) return NS_OK; } - +/** + * NSUnregisterSelf is responsible for undoing anything NSRegisterSelf does + * to the registry. It would presumably be called if your component is + * uninstalled or upgraded. + */ extern "C" PR_IMPLEMENT(nsresult) NSUnregisterSelf(nsISupports* aServMgr, const char* aPath) { @@ -204,3 +301,5 @@ NSUnregisterSelf(nsISupports* aServMgr, const char* aPath) return NS_OK; } + +