Back to index

lightning-sunbird  0.9+nobinonly
nsXPComInit.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Benjamin Smedberg <benjamin@smedbergs.us>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsXPCOM.h"
00040 #include "nsXPCOMPrivate.h"
00041 #include "nscore.h"
00042 #include "nsStaticComponents.h"
00043 #include "prlink.h"
00044 #include "nsCOMPtr.h"
00045 #include "nsObserverList.h"
00046 #include "nsObserverService.h"
00047 #include "nsProperties.h"
00048 #include "nsIProperties.h"
00049 #include "nsPersistentProperties.h"
00050 #include "nsScriptableInputStream.h"
00051 #include "nsBinaryStream.h"
00052 #include "nsStorageStream.h"
00053 #include "nsPipe.h"
00054 
00055 #include "nsMemoryImpl.h"
00056 #include "nsDebugImpl.h"
00057 #include "nsTraceRefcntImpl.h"
00058 #include "nsErrorService.h"
00059 #include "nsByteBuffer.h"
00060 
00061 #include "nsSupportsArray.h"
00062 #include "nsArray.h"
00063 #include "nsSupportsPrimitives.h"
00064 #include "nsConsoleService.h"
00065 #include "nsExceptionService.h"
00066 
00067 #include "nsComponentManager.h"
00068 #include "nsCategoryManagerUtils.h"
00069 #include "nsIServiceManager.h"
00070 #include "nsGenericFactory.h"
00071 
00072 #include "nsEventQueueService.h"
00073 #include "nsEventQueue.h"
00074 
00075 #include "nsIProxyObjectManager.h"
00076 #include "nsProxyEventPrivate.h"  // access to the impl of nsProxyObjectManager for the generic factory registration.
00077 
00078 #include "xptinfo.h"
00079 #include "nsIInterfaceInfoManager.h"
00080 
00081 #include "nsTimerImpl.h"
00082 #include "TimerThread.h"
00083 
00084 #include "nsThread.h"
00085 #include "nsProcess.h"
00086 #include "nsEnvironment.h"
00087 #include "nsVersionComparatorImpl.h"
00088 
00089 #include "nsEmptyEnumerator.h"
00090 
00091 #include "nsILocalFile.h"
00092 #include "nsLocalFile.h"
00093 #if defined(XP_UNIX) || defined(XP_OS2)
00094 #include "nsNativeCharsetUtils.h"
00095 #endif
00096 #include "nsDirectoryService.h"
00097 #include "nsDirectoryServiceDefs.h"
00098 #include "nsCategoryManager.h"
00099 #include "nsICategoryManager.h"
00100 #include "nsStringStream.h"
00101 #include "nsMultiplexInputStream.h"
00102 
00103 #include "nsFastLoadService.h"
00104 
00105 #include "nsAtomService.h"
00106 #include "nsAtomTable.h"
00107 #include "nsTraceRefcnt.h"
00108 #include "nsTimelineService.h"
00109 
00110 #include "nsHashPropertyBag.h"
00111 
00112 #include "nsVariant.h"
00113 
00114 #include "nsUUIDGenerator.h"
00115 
00116 #ifdef GC_LEAK_DETECTOR
00117 #include "nsLeakDetector.h"
00118 #endif
00119 #include "nsRecyclingAllocator.h"
00120 
00121 #include "SpecialSystemDirectory.h"
00122 
00123 #if defined(XP_WIN) && !defined(WINCE)
00124 #include "nsWindowsRegKey.h"
00125 #endif
00126 
00127 #ifdef XP_MACOSX
00128 #include "nsMacUtilsImpl.h"
00129 #endif
00130 
00131 #include "nsSystemInfo.h"
00132 
00133 #include <locale.h>
00134 
00135 // Registry Factory creation function defined in nsRegistry.cpp
00136 // We hook into this function locally to create and register the registry
00137 // Since noone outside xpcom needs to know about this and nsRegistry.cpp
00138 // does not have a local include file, we are putting this definition
00139 // here rather than in nsIRegistry.h
00140 extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
00141 extern nsresult NS_CategoryManagerGetFactory( nsIFactory** );
00142 
00143 #ifdef DEBUG
00144 extern void _FreeAutoLockStatics();
00145 #endif
00146 
00147 static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
00148 static NS_DEFINE_CID(kMemoryCID, NS_MEMORY_CID);
00149 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00150 
00151 NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess)
00152 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEventQueueServiceImpl, Init)
00153 
00154 #define NS_ENVIRONMENT_CLASSNAME "Environment Service"
00155 
00156 #include "nsXPCOM.h"
00157 // ds/nsISupportsPrimitives
00158 #define NS_SUPPORTS_ID_CLASSNAME "Supports ID"
00159 #define NS_SUPPORTS_CSTRING_CLASSNAME "Supports String"
00160 #define NS_SUPPORTS_STRING_CLASSNAME "Supports WString"
00161 #define NS_SUPPORTS_PRBOOL_CLASSNAME "Supports PRBool"
00162 #define NS_SUPPORTS_PRUINT8_CLASSNAME "Supports PRUint8"
00163 #define NS_SUPPORTS_PRUINT16_CLASSNAME "Supports PRUint16"
00164 #define NS_SUPPORTS_PRUINT32_CLASSNAME "Supports PRUint32"
00165 #define NS_SUPPORTS_PRUINT64_CLASSNAME "Supports PRUint64"
00166 #define NS_SUPPORTS_PRTIME_CLASSNAME "Supports PRTime"
00167 #define NS_SUPPORTS_CHAR_CLASSNAME "Supports Char"
00168 #define NS_SUPPORTS_PRINT16_CLASSNAME "Supports PRInt16"
00169 #define NS_SUPPORTS_PRINT32_CLASSNAME "Supports PRInt32"
00170 #define NS_SUPPORTS_PRINT64_CLASSNAME "Supports PRInt64"
00171 #define NS_SUPPORTS_FLOAT_CLASSNAME "Supports float"
00172 #define NS_SUPPORTS_DOUBLE_CLASSNAME "Supports double"
00173 #define NS_SUPPORTS_VOID_CLASSNAME "Supports void"
00174 #define NS_SUPPORTS_INTERFACE_POINTER_CLASSNAME "Supports interface pointer"
00175 
00176 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsIDImpl)
00177 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsStringImpl)
00178 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCStringImpl)
00179 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRBoolImpl)
00180 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint8Impl)
00181 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint16Impl)
00182 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint32Impl)
00183 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint64Impl)
00184 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRTimeImpl)
00185 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCharImpl)
00186 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt16Impl)
00187 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt32Impl)
00188 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64Impl)
00189 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloatImpl)
00190 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDoubleImpl)
00191 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl)
00192 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
00193 
00194 NS_GENERIC_FACTORY_CONSTRUCTOR(nsArray)
00195 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsConsoleService, Init)
00196 NS_DECL_CLASSINFO(nsConsoleService)
00197 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
00198 NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService)
00199 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl)
00200 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerManager)
00201 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream)
00202 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream)
00203 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStorageStream)
00204 NS_GENERIC_FACTORY_CONSTRUCTOR(nsVersionComparatorImpl)
00205 
00206 NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant)
00207 
00208 NS_GENERIC_FACTORY_CONSTRUCTOR(nsRecyclingAllocatorImpl)
00209 
00210 #ifdef MOZ_TIMELINE
00211 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimelineService)
00212 #endif
00213 
00214 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHashPropertyBag, Init)
00215 
00216 #ifdef XP_MACOSX
00217 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUtilsImpl)
00218 #endif
00219 
00220 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUUIDGenerator, Init)
00221 
00222 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemInfo, Init)
00223 
00224 static NS_METHOD
00225 nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer,
00226                                        const nsIID& aIID,
00227                                        void* *aInstancePtr)
00228 {
00229     NS_ENSURE_ARG_POINTER(aInstancePtr);
00230     NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
00231 
00232     nsCOMPtr<nsIInterfaceInfoManager> iim(dont_AddRef(XPTI_GetInterfaceInfoManager()));
00233     if (!iim) {
00234         return NS_ERROR_FAILURE;
00235     }
00236 
00237     return iim->QueryInterface(aIID, aInstancePtr);
00238 }
00239 
00240 
00241 PR_STATIC_CALLBACK(nsresult)
00242 RegisterGenericFactory(nsIComponentRegistrar* registrar,
00243                        const nsModuleComponentInfo *info)
00244 {
00245     nsresult rv;
00246     nsIGenericFactory* fact;
00247     rv = NS_NewGenericFactory(&fact, info);
00248     if (NS_FAILED(rv)) return rv;
00249 
00250     rv = registrar->RegisterFactory(info->mCID, 
00251                                     info->mDescription,
00252                                     info->mContractID, 
00253                                     fact);
00254     NS_RELEASE(fact);
00255     return rv;
00256 }
00257 
00258 // In order to support the installer, we need
00259 // to be told out of band if we should cause
00260 // an autoregister.  If the file ".autoreg" exists in the binary
00261 // directory, we check its timestamp against the timestamp of the
00262 // compreg.dat file.  If the .autoreg file is newer, we autoregister.
00263 static PRBool CheckUpdateFile()
00264 {
00265     nsresult rv;
00266     nsCOMPtr<nsIFile> file;
00267     rv = nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, 
00268                                            NS_GET_IID(nsIFile), 
00269                                            getter_AddRefs(file));
00270 
00271     if (NS_FAILED(rv)) {
00272         NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
00273         return PR_FALSE;
00274     }
00275 
00276     file->AppendNative(nsDependentCString(".autoreg"));
00277     
00278     PRBool exists;
00279     file->Exists(&exists);
00280     if (!exists)
00281         return PR_FALSE;
00282 
00283     nsCOMPtr<nsIFile> compregFile;
00284     rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
00285                                            NS_GET_IID(nsIFile),
00286                                            getter_AddRefs(compregFile));
00287 
00288     
00289     if (NS_FAILED(rv)) {
00290         NS_WARNING("Getting NS_XPCOM_COMPONENT_REGISTRY_FILE failed");
00291         return PR_FALSE;
00292     }
00293 
00294     // Don't need to check whether compreg exists; if it doesn't
00295     // we won't even be here.
00296 
00297     PRInt64 compregModTime, autoregModTime;
00298     compregFile->GetLastModifiedTime(&compregModTime);
00299     file->GetLastModifiedTime(&autoregModTime);
00300 
00301     return LL_CMP(autoregModTime, >, compregModTime);
00302 }
00303 
00304 
00305 nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
00306 PRBool gXPCOMShuttingDown = PR_FALSE;
00307 
00308 // For each class that wishes to support nsIClassInfo, add a line like this
00309 // NS_DECL_CLASSINFO(nsMyClass)
00310 
00311 #define COMPONENT(NAME, Ctor)                                                  \
00312  { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
00313 
00314 #define COMPONENT_CI(NAME, Ctor, Class)                                        \
00315  { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor,       \
00316    NULL, NULL, NULL, NS_CI_INTERFACE_GETTER_NAME(Class), NULL,                 \
00317    &NS_CLASSINFO_NAME(Class) }
00318 
00319 #define COMPONENT_CI_FLAGS(NAME, Ctor, Class, Flags)                           \
00320  { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor,       \
00321    NULL, NULL, NULL, NS_CI_INTERFACE_GETTER_NAME(Class), NULL,                 \
00322    &NS_CLASSINFO_NAME(Class), Flags }
00323 
00324 static const nsModuleComponentInfo components[] = {
00325     COMPONENT(MEMORY, nsMemoryImpl::Create),
00326     COMPONENT(DEBUG,  nsDebugImpl::Create),
00327 #define NS_ERRORSERVICE_CLASSNAME NS_ERRORSERVICE_NAME
00328     COMPONENT(ERRORSERVICE, nsErrorService::Create),
00329 
00330     COMPONENT(BYTEBUFFER, ByteBufferImpl::Create),
00331     COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create),
00332     COMPONENT(BINARYINPUTSTREAM, nsBinaryInputStreamConstructor),
00333     COMPONENT(BINARYOUTPUTSTREAM, nsBinaryOutputStreamConstructor),
00334     COMPONENT(STORAGESTREAM, nsStorageStreamConstructor),
00335     COMPONENT(VERSIONCOMPARATOR, nsVersionComparatorImplConstructor),
00336     COMPONENT(PIPE, nsPipeConstructor),
00337 
00338 #define NS_PROPERTIES_CLASSNAME  "Properties"
00339     COMPONENT(PROPERTIES, nsProperties::Create),
00340 
00341 #define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */
00342     COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create),
00343 
00344     COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create),
00345     COMPONENT(ARRAY, nsArrayConstructor),
00346     COMPONENT_CI_FLAGS(CONSOLESERVICE, nsConsoleServiceConstructor,
00347                        nsConsoleService,
00348                        nsIClassInfo::THREADSAFE | nsIClassInfo::SINGLETON),
00349     COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor),
00350     COMPONENT(ATOMSERVICE, nsAtomServiceConstructor),
00351 #ifdef MOZ_TIMELINE
00352     COMPONENT(TIMELINESERVICE, nsTimelineServiceConstructor),
00353 #endif
00354     COMPONENT(OBSERVERSERVICE, nsObserverService::Create),
00355     COMPONENT(GENERICFACTORY, nsGenericFactory::Create),
00356     COMPONENT(EVENTQUEUESERVICE, nsEventQueueServiceImplConstructor),
00357     COMPONENT(EVENTQUEUE, nsEventQueueImpl::Create),
00358     COMPONENT(THREAD, nsThread::Create),
00359 
00360 #define NS_XPCOMPROXY_CID NS_PROXYEVENT_MANAGER_CID
00361     COMPONENT(XPCOMPROXY, nsProxyObjectManager::Create),
00362 
00363     COMPONENT(TIMER, nsTimerImplConstructor),
00364     COMPONENT(TIMERMANAGER, nsTimerManagerConstructor),
00365 
00366 #define COMPONENT_SUPPORTS(TYPE, Type)                                         \
00367   COMPONENT(SUPPORTS_##TYPE, nsSupports##Type##ImplConstructor)
00368 
00369     COMPONENT_SUPPORTS(ID, ID),
00370     COMPONENT_SUPPORTS(STRING, String),
00371     COMPONENT_SUPPORTS(CSTRING, CString),
00372     COMPONENT_SUPPORTS(PRBOOL, PRBool),
00373     COMPONENT_SUPPORTS(PRUINT8, PRUint8),
00374     COMPONENT_SUPPORTS(PRUINT16, PRUint16),
00375     COMPONENT_SUPPORTS(PRUINT32, PRUint32),
00376     COMPONENT_SUPPORTS(PRUINT64, PRUint64),
00377     COMPONENT_SUPPORTS(PRTIME, PRTime),
00378     COMPONENT_SUPPORTS(CHAR, Char),
00379     COMPONENT_SUPPORTS(PRINT16, PRInt16),
00380     COMPONENT_SUPPORTS(PRINT32, PRInt32),
00381     COMPONENT_SUPPORTS(PRINT64, PRInt64),
00382     COMPONENT_SUPPORTS(FLOAT, Float),
00383     COMPONENT_SUPPORTS(DOUBLE, Double),
00384     COMPONENT_SUPPORTS(VOID, Void),
00385     COMPONENT_SUPPORTS(INTERFACE_POINTER, InterfacePointer),
00386 
00387 #undef COMPONENT_SUPPORTS
00388 #define NS_LOCAL_FILE_CLASSNAME "Local File Specification"
00389     COMPONENT(LOCAL_FILE, nsLocalFile::nsLocalFileConstructor),
00390 #define NS_DIRECTORY_SERVICE_CLASSNAME  "nsIFile Directory Service"
00391     COMPONENT(DIRECTORY_SERVICE, nsDirectoryService::Create),
00392     COMPONENT(PROCESS, nsProcessConstructor),
00393     COMPONENT(ENVIRONMENT, nsEnvironment::Create),
00394 
00395     COMPONENT(STRINGINPUTSTREAM, nsStringInputStreamConstructor),
00396     COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor),
00397 
00398 #ifndef MOZ_NO_FAST_LOAD
00399     COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create),
00400 #endif
00401 
00402     COMPONENT(VARIANT, nsVariantConstructor),
00403     COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton),
00404 
00405     COMPONENT(RECYCLINGALLOCATOR, nsRecyclingAllocatorImplConstructor),
00406 
00407 #define NS_HASH_PROPERTY_BAG_CLASSNAME "Hashtable Property Bag"
00408     COMPONENT(HASH_PROPERTY_BAG, nsHashPropertyBagConstructor),
00409 
00410     COMPONENT(UUID_GENERATOR, nsUUIDGeneratorConstructor),
00411 
00412 #if defined(XP_WIN) && !defined(WINCE)
00413     COMPONENT(WINDOWSREGKEY, nsWindowsRegKeyConstructor),
00414 #endif
00415 
00416 #ifdef XP_MACOSX
00417     COMPONENT(MACUTILSIMPL, nsMacUtilsImplConstructor),
00418 #endif
00419 
00420     COMPONENT(SYSTEMINFO, nsSystemInfoConstructor),
00421 };
00422 
00423 #undef COMPONENT
00424 
00425 const int components_length = sizeof(components) / sizeof(components[0]);
00426 
00427 // gDebug will be freed during shutdown.
00428 static nsIDebug* gDebug = nsnull;
00429 nsresult NS_COM NS_GetDebug(nsIDebug** result)
00430 {
00431     nsresult rv = NS_OK;
00432     if (!gDebug)
00433     {
00434         rv = nsDebugImpl::Create(nsnull, 
00435                                  NS_GET_IID(nsIDebug), 
00436                                  (void**)&gDebug);
00437     }
00438     NS_IF_ADDREF(*result = gDebug);
00439     return rv;
00440 }
00441 
00442 #ifdef NS_BUILD_REFCNT_LOGGING
00443 // gTraceRefcnt will be freed during shutdown.
00444 static nsITraceRefcnt* gTraceRefcnt = nsnull;
00445 #endif
00446 
00447 nsresult NS_COM NS_GetTraceRefcnt(nsITraceRefcnt** result)
00448 {
00449 #ifdef NS_BUILD_REFCNT_LOGGING
00450     nsresult rv = NS_OK;
00451     if (!gTraceRefcnt)
00452     {
00453         rv = nsTraceRefcntImpl::Create(nsnull, 
00454                                        NS_GET_IID(nsITraceRefcnt), 
00455                                        (void**)&gTraceRefcnt);
00456     }
00457     NS_IF_ADDREF(*result = gTraceRefcnt);
00458     return rv;
00459 #else
00460     return NS_ERROR_NOT_INITIALIZED;
00461 #endif
00462 }
00463 
00464 nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
00465                              nsIFile* binDirectory)
00466 {
00467     return NS_InitXPCOM3(result, binDirectory, nsnull, nsnull, 0);
00468 }
00469 
00470 nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
00471                               nsIFile* binDirectory,
00472                               nsIDirectoryServiceProvider* appFileLocationProvider)
00473 {
00474     return NS_InitXPCOM3(result, binDirectory, appFileLocationProvider, nsnull, 0);
00475 }
00476 
00477 nsresult NS_COM NS_InitXPCOM3(nsIServiceManager* *result,
00478                               nsIFile* binDirectory,
00479                               nsIDirectoryServiceProvider* appFileLocationProvider,
00480                               nsStaticModuleInfo const *staticComponents,
00481                               PRUint32 componentCount)
00482 {
00483     nsresult rv = NS_OK;
00484 
00485 #ifdef MOZ_ENABLE_LIBXUL
00486     if (!staticComponents) {
00487         staticComponents = kPStaticModules;
00488         componentCount = kStaticModuleCount;
00489     }
00490 #endif
00491 
00492      // We are not shutting down
00493     gXPCOMShuttingDown = PR_FALSE;
00494 
00495 #ifdef NS_BUILD_REFCNT_LOGGING
00496     nsTraceRefcntImpl::Startup();
00497 #endif
00498 
00499     // Establish the main thread here.
00500     rv = nsIThread::SetMainThread();
00501     if (NS_FAILED(rv)) return rv;
00502 
00503     // Set up the timer globals/timer thread
00504     rv = nsTimerImpl::Startup();
00505     NS_ENSURE_SUCCESS(rv, rv);
00506 
00507     // Startup the memory manager
00508     rv = nsMemoryImpl::Startup();
00509     if (NS_FAILED(rv)) return rv;
00510 
00511 #ifndef WINCE
00512     // If the locale hasn't already been setup by our embedder,
00513     // get us out of the "C" locale and into the system 
00514     if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
00515         setlocale(LC_ALL, "");
00516 #endif
00517 
00518 #if defined(XP_UNIX) || defined(XP_OS2)
00519     NS_StartupNativeCharsetUtils();
00520 #endif
00521     NS_StartupLocalFile();
00522 
00523     StartupSpecialSystemDirectory();
00524 
00525     rv = nsDirectoryService::RealInit();
00526     if (NS_FAILED(rv))
00527         return rv;
00528 
00529     // Create the Component/Service Manager
00530     nsComponentManagerImpl *compMgr = NULL;
00531 
00532     if (nsComponentManagerImpl::gComponentManager == NULL)
00533     {
00534         compMgr = new nsComponentManagerImpl();
00535         if (compMgr == NULL)
00536             return NS_ERROR_OUT_OF_MEMORY;
00537         NS_ADDREF(compMgr);
00538         
00539         nsCOMPtr<nsIFile> xpcomLib;
00540                 
00541         PRBool value;
00542         if (binDirectory)
00543         {
00544             rv = binDirectory->IsDirectory(&value);
00545 
00546             if (NS_SUCCEEDED(rv) && value) {
00547                 nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory);
00548                 binDirectory->Clone(getter_AddRefs(xpcomLib));
00549             }
00550         }
00551         else {
00552             nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, 
00553                                               NS_GET_IID(nsIFile), 
00554                                               getter_AddRefs(xpcomLib));
00555         }
00556 
00557         if (xpcomLib) {
00558             xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
00559             nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
00560         }
00561         
00562         if (appFileLocationProvider) {
00563             rv = nsDirectoryService::gService->RegisterProvider(appFileLocationProvider);
00564             if (NS_FAILED(rv)) return rv;
00565         }
00566 
00567         rv = compMgr->Init(staticComponents, componentCount);
00568         if (NS_FAILED(rv))
00569         {
00570             NS_RELEASE(compMgr);
00571             return rv;
00572         }
00573 
00574         nsComponentManagerImpl::gComponentManager = compMgr;
00575 
00576         if (result) {
00577             nsIServiceManager *serviceManager =
00578                 NS_STATIC_CAST(nsIServiceManager*, compMgr);
00579 
00580             NS_ADDREF(*result = serviceManager);
00581         }
00582     }
00583 
00584     nsCOMPtr<nsIMemory> memory;
00585     NS_GetMemoryManager(getter_AddRefs(memory));
00586     // dougt - these calls will be moved into a new interface when nsIComponentManager is frozen.
00587     rv = compMgr->RegisterService(kMemoryCID, memory);
00588     if (NS_FAILED(rv)) return rv;
00589 
00590     rv = compMgr->RegisterService(kComponentManagerCID, NS_STATIC_CAST(nsIComponentManager*, compMgr));
00591     if (NS_FAILED(rv)) return rv;
00592 
00593 #ifdef GC_LEAK_DETECTOR
00594   rv = NS_InitLeakDetector();
00595     if (NS_FAILED(rv)) return rv;
00596 #endif
00597 
00598     // 2. Register the global services with the component manager so that
00599     //    clients can create new objects.
00600 
00601     // Category Manager
00602     {
00603       nsCOMPtr<nsIFactory> categoryManagerFactory;
00604       if ( NS_FAILED(rv = NS_CategoryManagerGetFactory(getter_AddRefs(categoryManagerFactory))) )
00605         return rv;
00606 
00607       NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
00608 
00609       rv = compMgr->RegisterFactory(kCategoryManagerCID,
00610                                     NS_CATEGORYMANAGER_CLASSNAME,
00611                                     NS_CATEGORYMANAGER_CONTRACTID,
00612                                     categoryManagerFactory,
00613                                     PR_TRUE);
00614       if ( NS_FAILED(rv) ) return rv;
00615     }
00616 
00617     // what I want to do here is QI for a Component Registration Manager.  Since this
00618     // has not been invented yet, QI to the obsolete manager.  Kids, don't do this at home.
00619     nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(
00620         NS_STATIC_CAST(nsIComponentManager*,compMgr), &rv);
00621     if (registrar) {
00622         for (int i = 0; i < components_length; i++)
00623             RegisterGenericFactory(registrar, &components[i]);
00624     }
00625     rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
00626 #ifdef DEBUG    
00627     if (NS_FAILED(rv)) {
00628         printf("No Persistent Registry Found.\n");        
00629     }
00630 #endif
00631 
00632     if ( NS_FAILED(rv) || CheckUpdateFile()) {
00633         // if we find no persistent registry, we will try to autoregister
00634         // the default components directory.
00635         nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
00636 
00637         // If the application is using a GRE, then, 
00638         // auto register components in the GRE directory as well.
00639         //
00640         // The application indicates that it's using an GRE by
00641         // returning a valid nsIFile when queried (via appFileLocProvider)
00642         // for the NS_GRE_DIR atom as shown below
00643         //
00644 
00645         if ( appFileLocationProvider ) {
00646             nsCOMPtr<nsIFile> greDir;
00647             PRBool persistent = PR_TRUE;
00648 
00649             appFileLocationProvider->GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(greDir));
00650 
00651             if (greDir) {
00652 #ifdef DEBUG_dougt
00653                 printf("start - Registering GRE components\n");
00654 #endif
00655                 rv = nsDirectoryService::gService->Get(NS_GRE_COMPONENT_DIR,
00656                                                        NS_GET_IID(nsIFile),
00657                                                        getter_AddRefs(greDir));
00658                 if (NS_FAILED(rv)) {
00659                     NS_ERROR("Could not get GRE components directory!");
00660                     return rv;
00661                 }
00662 
00663                 // If the GRE contains any loaders, we want to know about it so that we can cause another
00664                 // autoregistration of the applications component directory.
00665                 int loaderCount = nsComponentManagerImpl::gComponentManager->GetLoaderCount();
00666                 rv = nsComponentManagerImpl::gComponentManager->AutoRegister(greDir);
00667                 
00668                 if (loaderCount != nsComponentManagerImpl::gComponentManager->GetLoaderCount()) 
00669                     nsComponentManagerImpl::gComponentManager->AutoRegisterNonNativeComponents(nsnull);        
00670 
00671 #ifdef DEBUG_dougt
00672                 printf("end - Registering GRE components\n");
00673 #endif          
00674                 if (NS_FAILED(rv)) {
00675                     NS_ERROR("Could not AutoRegister GRE components");
00676                     return rv;
00677                 }
00678             }
00679         }
00680 
00681         //
00682         // If additional component directories have been specified, then
00683         // register them as well.
00684         //
00685 
00686         nsCOMPtr<nsISimpleEnumerator> dirList;
00687         nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
00688                                           NS_GET_IID(nsISimpleEnumerator),
00689                                           getter_AddRefs(dirList));
00690         if (dirList) {
00691             PRBool hasMore;
00692             while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
00693                 nsCOMPtr<nsISupports> elem;
00694                 dirList->GetNext(getter_AddRefs(elem));
00695                 if (elem) {
00696                     nsCOMPtr<nsIFile> dir = do_QueryInterface(elem);
00697                     if (dir)
00698                         nsComponentManagerImpl::gComponentManager->AutoRegister(dir);
00699 
00700                     // XXX should we worry about new component loaders being
00701                     // XXX defined by this process?
00702                 }
00703             }
00704         }
00705 
00706 
00707         // Make sure the compreg file's mod time is current.
00708         nsCOMPtr<nsIFile> compregFile;
00709         rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
00710                                                NS_GET_IID(nsIFile),
00711                                                getter_AddRefs(compregFile));
00712         compregFile->SetLastModifiedTime(PR_Now() / 1000);
00713     }
00714     
00715     // Pay the cost at startup time of starting this singleton.
00716     nsIInterfaceInfoManager* iim = XPTI_GetInterfaceInfoManager();
00717     NS_IF_RELEASE(iim);
00718 
00719     // After autoreg, but before we actually instantiate any components,
00720     // add any services listed in the "xpcom-directory-providers" category
00721     // to the directory service.
00722     nsDirectoryService::gService->RegisterCategoryProviders();
00723 
00724     // Notify observers of xpcom autoregistration start
00725     NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_OBSERVER_ID, 
00726                                   nsnull,
00727                                   NS_XPCOM_STARTUP_OBSERVER_ID);
00728     
00729     return NS_OK;
00730 }
00731 
00732 
00733 static nsVoidArray* gExitRoutines;
00734 
00735 static void CallExitRoutines()
00736 {
00737     if (!gExitRoutines)
00738         return;
00739 
00740     PRInt32 count = gExitRoutines->Count();
00741     for (PRInt32 i = 0; i < count; i++) {
00742         XPCOMExitRoutine func = (XPCOMExitRoutine) gExitRoutines->ElementAt(i);
00743         func();
00744     }
00745     gExitRoutines->Clear();
00746     delete gExitRoutines;
00747     gExitRoutines = nsnull;
00748 }
00749 
00750 nsresult NS_COM
00751 NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
00752 {
00753     // priority are not used right now.  It will need to be implemented as more
00754     // classes are moved into the glue library --dougt
00755     if (!gExitRoutines) {
00756         gExitRoutines = new nsVoidArray();
00757         if (!gExitRoutines) {
00758             NS_WARNING("Failed to allocate gExitRoutines");
00759             return NS_ERROR_FAILURE;
00760         }
00761     }
00762 
00763     PRBool okay = gExitRoutines->AppendElement((void*)exitRoutine);
00764     return okay ? NS_OK : NS_ERROR_FAILURE;
00765 }
00766 
00767 nsresult NS_COM
00768 NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
00769 {
00770     if (!gExitRoutines)
00771         return NS_ERROR_FAILURE;
00772 
00773     PRBool okay = gExitRoutines->RemoveElement((void*)exitRoutine);
00774     return okay ? NS_OK : NS_ERROR_FAILURE;
00775 }
00776 
00777 
00778 //
00779 // NS_ShutdownXPCOM()
00780 //
00781 // The shutdown sequence for xpcom would be
00782 //
00783 // - Release the Global Service Manager
00784 //   - Release all service instances held by the global service manager
00785 //   - Release the Global Service Manager itself
00786 // - Release the Component Manager
00787 //   - Release all factories cached by the Component Manager
00788 //   - Unload Libraries
00789 //   - Release Contractid Cache held by Component Manager
00790 //   - Release dll abstraction held by Component Manager
00791 //   - Release the Registry held by Component Manager
00792 //   - Finally, release the component manager itself
00793 //
00794 nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
00795 {
00796 
00797     // Notify observers of xpcom shutting down
00798     nsresult rv = NS_OK;
00799     {
00800         // Block it so that the COMPtr will get deleted before we hit
00801         // servicemanager shutdown
00802         nsCOMPtr<nsIObserverService> observerService =
00803                  do_GetService("@mozilla.org/observer-service;1", &rv);
00804         if (NS_SUCCEEDED(rv))
00805         {
00806             nsCOMPtr<nsIServiceManager> mgr;
00807             rv = NS_GetServiceManager(getter_AddRefs(mgr));
00808             if (NS_SUCCEEDED(rv))
00809             {
00810                 (void) observerService->NotifyObservers(mgr,
00811                                                         NS_XPCOM_SHUTDOWN_OBSERVER_ID,
00812                                                         nsnull);
00813             }
00814         }
00815     }
00816 
00817     // grab the event queue so that we can process events one last time before exiting
00818     nsCOMPtr <nsIEventQueue> currentQ;
00819     {
00820         nsCOMPtr<nsIEventQueueService> eventQService =
00821                  do_GetService(kEventQueueServiceCID, &rv);
00822 
00823         if (eventQService) {
00824             eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentQ));
00825         }
00826     }
00827     // XPCOM is officially in shutdown mode NOW
00828     // Set this only after the observers have been notified as this
00829     // will cause servicemanager to become inaccessible.
00830     gXPCOMShuttingDown = PR_TRUE;
00831 
00832 #ifdef DEBUG_dougt
00833     fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n");
00834 #endif
00835     // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
00836     // here again:
00837     NS_IF_RELEASE(servMgr);
00838 
00839     // Shutdown global servicemanager
00840     if (nsComponentManagerImpl::gComponentManager) {
00841         nsComponentManagerImpl::gComponentManager->FreeServices();
00842     }
00843 
00844     if (currentQ) {
00845         currentQ->ProcessPendingEvents();
00846         currentQ = 0;
00847     }
00848     
00849     nsProxyObjectManager::Shutdown();
00850 
00851     // Release the directory service
00852     NS_IF_RELEASE(nsDirectoryService::gService);
00853 
00854     // Shutdown nsLocalFile string conversion
00855     NS_ShutdownLocalFile();
00856 #ifdef XP_UNIX
00857     NS_ShutdownNativeCharsetUtils();
00858 #endif
00859 
00860     // Shutdown the timer thread and all timers that might still be alive before
00861     // shutting down the component manager
00862     nsTimerImpl::Shutdown();
00863 
00864     CallExitRoutines();
00865 
00866     // Shutdown xpcom. This will release all loaders and cause others holding
00867     // a refcount to the component manager to release it.
00868     if (nsComponentManagerImpl::gComponentManager) {
00869         rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();
00870         NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
00871     } else
00872         NS_WARNING("Component Manager was never created ...");
00873 
00874     // Release our own singletons
00875     // Do this _after_ shutting down the component manager, because the
00876     // JS component loader will use XPConnect to call nsIModule::canUnload,
00877     // and that will spin up the InterfaceInfoManager again -- bad mojo
00878     XPTI_FreeInterfaceInfoManager();
00879 
00880     // Finally, release the component manager last because it unloads the
00881     // libraries:
00882     if (nsComponentManagerImpl::gComponentManager) {
00883       nsrefcnt cnt;
00884       NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
00885       NS_WARN_IF_FALSE(cnt == 0, "Component Manager being held past XPCOM shutdown.");
00886     }
00887     nsComponentManagerImpl::gComponentManager = nsnull;
00888 
00889 #ifdef DEBUG
00890     _FreeAutoLockStatics();
00891 #endif
00892 
00893     ShutdownSpecialSystemDirectory();
00894 
00895     EmptyEnumeratorImpl::Shutdown();
00896     nsMemoryImpl::Shutdown();
00897 
00898     nsThread::Shutdown();
00899     NS_PurgeAtomTable();
00900 
00901     NS_IF_RELEASE(gDebug);
00902 
00903 #ifdef NS_BUILD_REFCNT_LOGGING
00904     nsTraceRefcntImpl::DumpStatistics();
00905     nsTraceRefcntImpl::ResetStatistics();
00906     nsTraceRefcntImpl::Shutdown();
00907 #endif
00908 
00909 #ifdef GC_LEAK_DETECTOR
00910     // Shutdown the Leak detector.
00911     NS_ShutdownLeakDetector();
00912 #endif
00913 
00914     return NS_OK;
00915 }