mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-30 05:35:31 +00:00
849d297364
a) create a new nsIComponentManager with only four functions on it: CreateInstance CreateInstanceByContractID GetClassInfo GetClassInfoByContractID. b) rename the old nsIComponentManager to nsIComponentManagerObsolete. c) fixes callers which use to access the nsIComponentManager for component registration functionality. These callers will temporary use the nsIComponentManagerObsolete interface. d) Create a new API NS_GetComponentManager() which mirrors the NS_GetServiceManager() e) Perserves the old NS_GetGlobalComponentManager(). Note the cast usage. r/sr = rpotts@netscape.com alecf@netscape.com brendan@mozilla.org
619 lines
21 KiB
C++
619 lines
21 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the NPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "nsXPCOM.h"
|
|
#include "nsXPCOMPrivate.h"
|
|
#include "nsIRegistry.h"
|
|
#include "nscore.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsObserverList.h"
|
|
#include "nsObserver.h"
|
|
#include "nsObserverService.h"
|
|
#include "nsProperties.h"
|
|
#include "nsIProperties.h"
|
|
#include "nsPersistentProperties.h"
|
|
#include "nsScriptableInputStream.h"
|
|
|
|
#include "nsMemoryImpl.h"
|
|
#include "nsErrorService.h"
|
|
#include "nsArena.h"
|
|
#include "nsByteBuffer.h"
|
|
|
|
#include "nsSupportsArray.h"
|
|
#include "nsSupportsPrimitives.h"
|
|
#include "nsConsoleService.h"
|
|
#include "nsExceptionService.h"
|
|
|
|
#include "nsComponentManager.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsGenericFactory.h"
|
|
|
|
#include "nsEventQueueService.h"
|
|
#include "nsEventQueue.h"
|
|
|
|
#include "nsIProxyObjectManager.h"
|
|
#include "nsProxyEventPrivate.h" // access to the impl of nsProxyObjectManager for the generic factory registration.
|
|
|
|
#include "xptinfo.h"
|
|
#include "nsIInterfaceInfoManager.h"
|
|
|
|
#include "nsTimerImpl.h"
|
|
#include "TimerThread.h"
|
|
|
|
#include "nsThread.h"
|
|
#include "nsProcess.h"
|
|
|
|
#include "nsFileSpecImpl.h"
|
|
#include "nsSpecialSystemDirectory.h"
|
|
#include "nsEmptyEnumerator.h"
|
|
|
|
#include "nsILocalFile.h"
|
|
#include "nsLocalFile.h"
|
|
#include "nsDirectoryService.h"
|
|
#include "nsDirectoryServiceDefs.h"
|
|
#include "nsAppFileLocationProvider.h"
|
|
#include "nsICategoryManager.h"
|
|
#include "nsStringStream.h"
|
|
|
|
#include "nsFastLoadService.h"
|
|
|
|
#include "nsAtomService.h"
|
|
#include "nsAtomTable.h"
|
|
#include "nsTraceRefcnt.h"
|
|
#include "nsTimelineService.h"
|
|
|
|
#include "nsVariant.h"
|
|
|
|
#ifdef GC_LEAK_DETECTOR
|
|
#include "nsLeakDetector.h"
|
|
#endif
|
|
|
|
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
|
|
static NS_DEFINE_CID(kMemoryCID, NS_MEMORY_CID);
|
|
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
|
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess);
|
|
|
|
// ds/nsISupportsPrimitives
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsIDImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsStringImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsWStringImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRBoolImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint8Impl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint16Impl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint32Impl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint64Impl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRTimeImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCharImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt16Impl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt32Impl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64Impl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloatImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDoubleImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl)
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
|
|
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsConsoleService);
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService);
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService);
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl);
|
|
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant);
|
|
|
|
#ifdef MOZ_TIMELINE
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimelineService);
|
|
#endif
|
|
|
|
static NS_METHOD
|
|
nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer,
|
|
const nsIID& aIID,
|
|
void* *aInstancePtr)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aInstancePtr);
|
|
NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
|
|
|
|
nsCOMPtr<nsIInterfaceInfoManager> iim(dont_AddRef(XPTI_GetInterfaceInfoManager()));
|
|
if (!iim) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return iim->QueryInterface(aIID, aInstancePtr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// XPCOM initialization
|
|
//
|
|
// To Control the order of initialization of these key components I am putting
|
|
// this function.
|
|
//
|
|
// - nsServiceManager
|
|
// - nsComponentManager
|
|
// - nsRegistry
|
|
//
|
|
// Here are key points to remember:
|
|
// - A global of all these need to exist. nsServiceManager is an independent object.
|
|
// nsComponentManager uses both the globalServiceManager and its own registry.
|
|
//
|
|
// - A static object of both the nsComponentManager and nsServiceManager
|
|
// are in use. Hence InitXPCOM() gets triggered from both
|
|
// NS_GetGlobale{Service/Component}Manager() calls.
|
|
//
|
|
// - There exists no global Registry. Registry can be created from the component manager.
|
|
//
|
|
|
|
static nsresult
|
|
RegisterGenericFactory(nsIComponentManager* compMgr,
|
|
nsModuleComponentInfo *info)
|
|
{
|
|
nsresult rv;
|
|
nsIGenericFactory* fact;
|
|
rv = NS_NewGenericFactory(&fact, info);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// what I want to do here is QI for a Component Registration Manager. Since this
|
|
// has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
|
|
nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(compMgr, &rv);
|
|
if (obsoleteManager)
|
|
rv = obsoleteManager->RegisterFactory(info->mCID, info->mDescription,
|
|
info->mContractID, fact, PR_TRUE);
|
|
NS_RELEASE(fact);
|
|
return rv;
|
|
}
|
|
|
|
|
|
nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
|
|
nsIProperties *gDirectoryService = NULL;
|
|
PRBool gXPCOMShuttingDown = PR_FALSE;
|
|
|
|
// For each class that wishes to support nsIClassInfo, add a line like this
|
|
// NS_DECL_CLASSINFO(nsMyClass)
|
|
|
|
#define COMPONENT(NAME, Ctor) \
|
|
{ NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
|
|
|
|
#define COMPONENT_CI(NAME, Ctor, Class) \
|
|
{ NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor, \
|
|
NULL, NULL, NULL, NS_CI_INTERFACE_GETTER_NAME(Class), NULL, \
|
|
&NS_CLASSINFO_NAME(Class) }
|
|
|
|
static nsModuleComponentInfo components[] = {
|
|
// ugh
|
|
#define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
|
|
#define NS_MEMORY_CLASSNAME "Global Memory Service"
|
|
COMPONENT(MEMORY, nsMemoryImpl::Create),
|
|
#define NS_ERRORSERVICE_CLASSNAME NS_ERRORSERVICE_NAME
|
|
COMPONENT(ERRORSERVICE, nsErrorService::Create),
|
|
|
|
COMPONENT(ARENA, ArenaImpl::Create),
|
|
COMPONENT(BYTEBUFFER, ByteBufferImpl::Create),
|
|
COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create),
|
|
|
|
COMPONENT(PROPERTIES, nsProperties::Create),
|
|
|
|
#define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */
|
|
COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create),
|
|
|
|
COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create),
|
|
COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor),
|
|
COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor),
|
|
COMPONENT(ATOMSERVICE, nsAtomServiceConstructor),
|
|
#ifdef MOZ_TIMELINE
|
|
COMPONENT(TIMELINESERVICE, nsTimelineServiceConstructor),
|
|
#endif
|
|
COMPONENT(OBSERVER, nsObserver::Create),
|
|
COMPONENT(OBSERVERSERVICE, nsObserverService::Create),
|
|
COMPONENT(GENERICFACTORY, nsGenericFactory::Create),
|
|
COMPONENT(EVENTQUEUESERVICE, nsEventQueueServiceImpl::Create),
|
|
COMPONENT(EVENTQUEUE, nsEventQueueImpl::Create),
|
|
COMPONENT(THREAD, nsThread::Create),
|
|
COMPONENT(THREADPOOL, nsThreadPool::Create),
|
|
|
|
#define NS_XPCOMPROXY_CID NS_PROXYEVENT_MANAGER_CID
|
|
COMPONENT(XPCOMPROXY, nsProxyObjectManager::Create),
|
|
|
|
COMPONENT(TIMER, nsTimerImplConstructor),
|
|
|
|
#define COMPONENT_SUPPORTS(TYPE, Type) \
|
|
COMPONENT(SUPPORTS_##TYPE, nsSupports##Type##ImplConstructor)
|
|
|
|
COMPONENT_SUPPORTS(ID, ID),
|
|
COMPONENT_SUPPORTS(STRING, String),
|
|
COMPONENT_SUPPORTS(WSTRING, WString),
|
|
COMPONENT_SUPPORTS(PRBOOL, PRBool),
|
|
COMPONENT_SUPPORTS(PRUINT8, PRUint8),
|
|
COMPONENT_SUPPORTS(PRUINT16, PRUint16),
|
|
COMPONENT_SUPPORTS(PRUINT32, PRUint32),
|
|
COMPONENT_SUPPORTS(PRUINT64, PRUint64),
|
|
COMPONENT_SUPPORTS(PRTIME, PRTime),
|
|
COMPONENT_SUPPORTS(CHAR, Char),
|
|
COMPONENT_SUPPORTS(PRINT16, PRInt16),
|
|
COMPONENT_SUPPORTS(PRINT32, PRInt32),
|
|
COMPONENT_SUPPORTS(PRINT64, PRInt64),
|
|
COMPONENT_SUPPORTS(FLOAT, Float),
|
|
COMPONENT_SUPPORTS(DOUBLE, Double),
|
|
COMPONENT_SUPPORTS(VOID, Void),
|
|
COMPONENT_SUPPORTS(INTERFACE_POINTER, InterfacePointer),
|
|
|
|
#undef COMPONENT_SUPPORTS
|
|
|
|
COMPONENT(LOCAL_FILE, nsLocalFile::nsLocalFileConstructor),
|
|
COMPONENT(DIRECTORY_SERVICE, nsDirectoryService::Create),
|
|
COMPONENT(PROCESS, nsProcessConstructor),
|
|
COMPONENT(FILESPEC, nsFileSpecImpl::Create),
|
|
COMPONENT(DIRECTORYITERATOR, nsDirectoryIteratorImpl::Create),
|
|
|
|
COMPONENT(STRINGINPUTSTREAM, nsStringInputStreamConstructor),
|
|
|
|
COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create),
|
|
COMPONENT(VARIANT, nsVariantConstructor),
|
|
COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton)
|
|
};
|
|
|
|
#undef COMPONENT
|
|
|
|
const int components_length = sizeof(components) / sizeof(components[0]);
|
|
|
|
// gMemory will be freed during shutdown.
|
|
static nsIMemory* gMemory = nsnull;
|
|
nsresult NS_COM NS_GetMemoryManager(nsIMemory* *result)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (!gMemory)
|
|
{
|
|
rv = nsMemoryImpl::Create(nsnull,
|
|
NS_GET_IID(nsIMemory),
|
|
(void**)&gMemory);
|
|
}
|
|
NS_IF_ADDREF(*result = gMemory);
|
|
return rv;
|
|
}
|
|
|
|
nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
|
|
nsIFile* binDirectory)
|
|
{
|
|
return NS_InitXPCOM2(result, binDirectory, nsnull);
|
|
}
|
|
|
|
|
|
nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
|
|
nsIFile* binDirectory,
|
|
nsIDirectoryServiceProvider* appFileLocationProvider)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
nsTraceRefcnt::Startup();
|
|
#endif
|
|
|
|
// Establish the main thread here.
|
|
rv = nsIThread::SetMainThread();
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Startup the memory manager
|
|
rv = nsMemoryImpl::Startup();
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
NS_StartupLocalFile();
|
|
|
|
StartupSpecialSystemDirectory();
|
|
|
|
// Start the directory service so that the component manager init can use it.
|
|
rv = nsDirectoryService::Create(nsnull,
|
|
NS_GET_IID(nsIProperties),
|
|
(void**)&gDirectoryService);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIDirectoryService> dirService = do_QueryInterface(gDirectoryService, &rv);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
rv = dirService->Init();
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
// Create the Component/Service Manager
|
|
nsComponentManagerImpl *compMgr = NULL;
|
|
|
|
if (nsComponentManagerImpl::gComponentManager == NULL)
|
|
{
|
|
compMgr = new nsComponentManagerImpl();
|
|
if (compMgr == NULL)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
NS_ADDREF(compMgr);
|
|
|
|
PRBool value;
|
|
if (binDirectory)
|
|
{
|
|
rv = binDirectory->IsDirectory(&value);
|
|
|
|
if (NS_SUCCEEDED(rv) && value)
|
|
gDirectoryService->Define(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory);
|
|
|
|
//Since people are still using the nsSpecialSystemDirectory, we should init it.
|
|
char* path;
|
|
binDirectory->GetPath(&path);
|
|
nsFileSpec spec(path);
|
|
nsMemory::Free(path);
|
|
|
|
nsSpecialSystemDirectory::Set(nsSpecialSystemDirectory::Moz_BinDirectory, &spec);
|
|
|
|
}
|
|
if (!appFileLocationProvider) {
|
|
appFileLocationProvider = new nsAppFileLocationProvider;
|
|
if (!appFileLocationProvider)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
rv = dirService->RegisterProvider(appFileLocationProvider);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
rv = compMgr->Init();
|
|
if (NS_FAILED(rv))
|
|
{
|
|
NS_RELEASE(compMgr);
|
|
return rv;
|
|
}
|
|
|
|
nsIServiceManager *serviceManager = NS_STATIC_CAST(nsIServiceManager*, compMgr);
|
|
nsComponentManagerImpl::gComponentManager = compMgr;
|
|
|
|
if (result) {
|
|
NS_ADDREF(*result = serviceManager);
|
|
}
|
|
}
|
|
|
|
nsIServiceManager *serviceManager = NS_STATIC_CAST(nsIServiceManager*, compMgr);
|
|
|
|
|
|
nsCOMPtr<nsIMemory> memory;
|
|
NS_GetMemoryManager(getter_AddRefs(memory));
|
|
// dougt - these calls will be moved into a new interface when nsIComponentManager is frozen.
|
|
rv = compMgr->RegisterService(kMemoryCID, memory);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = compMgr->RegisterService(kComponentManagerCID, NS_STATIC_CAST(nsIComponentManager*, compMgr));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
#ifdef GC_LEAK_DETECTOR
|
|
rv = NS_InitLeakDetector();
|
|
if (NS_FAILED(rv)) return rv;
|
|
#endif
|
|
|
|
// 2. Register the global services with the component manager so that
|
|
// clients can create new objects.
|
|
|
|
// Registry
|
|
nsIFactory *registryFactory = NULL;
|
|
rv = NS_RegistryGetFactory(®istryFactory);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
NS_DEFINE_CID(kRegistryCID, NS_REGISTRY_CID);
|
|
|
|
rv = compMgr->RegisterFactory(kRegistryCID,
|
|
NS_REGISTRY_CLASSNAME,
|
|
NS_REGISTRY_CONTRACTID,
|
|
registryFactory, PR_TRUE);
|
|
NS_RELEASE(registryFactory);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Category Manager
|
|
{
|
|
nsCOMPtr<nsIFactory> categoryManagerFactory;
|
|
if ( NS_FAILED(rv = NS_CategoryManagerGetFactory(getter_AddRefs(categoryManagerFactory))) )
|
|
return rv;
|
|
|
|
NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
|
|
|
|
rv = compMgr->RegisterFactory(kCategoryManagerCID,
|
|
NS_CATEGORYMANAGER_CLASSNAME,
|
|
NS_CATEGORYMANAGER_CONTRACTID,
|
|
categoryManagerFactory,
|
|
PR_TRUE);
|
|
if ( NS_FAILED(rv) )
|
|
return rv;
|
|
}
|
|
|
|
for (int i = 0; i < components_length; i++)
|
|
RegisterGenericFactory(compMgr, &components[i]);
|
|
|
|
// Prepopulate registry for performance
|
|
// Ignore return value. It is ok if this fails.
|
|
nsComponentManagerImpl::gComponentManager->PlatformPrePopulateRegistry();
|
|
|
|
// Pay the cost at startup time of starting this singleton.
|
|
nsIInterfaceInfoManager* iim = XPTI_GetInterfaceInfoManager();
|
|
NS_IF_RELEASE(iim);
|
|
|
|
return rv;
|
|
}
|
|
|
|
static nsVoidArray gExitRoutines;
|
|
static void CallExitRoutines()
|
|
{
|
|
PRInt32 count = gExitRoutines.Count();
|
|
for (PRInt32 i = 0; i < count; i++) {
|
|
XPCOMExitRoutine func = (XPCOMExitRoutine) gExitRoutines.ElementAt(i);
|
|
func();
|
|
}
|
|
gExitRoutines.Clear();
|
|
}
|
|
|
|
nsresult NS_COM
|
|
NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
|
|
{
|
|
// priority are not used right now. It will need to be implemented as more
|
|
// classes are moved into the glue library --dougt
|
|
PRBool okay = gExitRoutines.AppendElement((void*)exitRoutine);
|
|
return okay ? NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsresult NS_COM
|
|
NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
|
|
{
|
|
PRBool okay = gExitRoutines.RemoveElement((void*)exitRoutine);
|
|
return okay ? NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
|
|
//
|
|
// NS_ShutdownXPCOM()
|
|
//
|
|
// The shutdown sequence for xpcom would be
|
|
//
|
|
// - Release the Global Service Manager
|
|
// - Release all service instances held by the global service manager
|
|
// - Release the Global Service Manager itself
|
|
// - Release the Component Manager
|
|
// - Release all factories cached by the Component Manager
|
|
// - Unload Libraries
|
|
// - Release Contractid Cache held by Component Manager
|
|
// - Release dll abstraction held by Component Manager
|
|
// - Release the Registry held by Component Manager
|
|
// - Finally, release the component manager itself
|
|
//
|
|
nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
|
{
|
|
nsrefcnt cnt;
|
|
|
|
// Notify observers of xpcom shutting down
|
|
nsresult rv = NS_OK;
|
|
{
|
|
// Block it so that the COMPtr will get deleted before we hit
|
|
// servicemanager shutdown
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
do_GetService("@mozilla.org/observer-service;1", &rv);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIServiceManager> mgr;
|
|
rv = NS_GetServiceManager(getter_AddRefs(mgr));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
(void) observerService->NotifyObservers(mgr,
|
|
NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
|
nsnull);
|
|
}
|
|
}
|
|
}
|
|
|
|
// grab the event queue so that we can process events one last time before exiting
|
|
nsCOMPtr <nsIEventQueue> currentQ;
|
|
{
|
|
nsCOMPtr<nsIEventQueueService> eventQService =
|
|
do_GetService(kEventQueueServiceCID, &rv);
|
|
|
|
if (eventQService) {
|
|
eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentQ));
|
|
}
|
|
}
|
|
// XPCOM is officially in shutdown mode NOW
|
|
// Set this only after the observers have been notified as this
|
|
// will cause servicemanager to become inaccessible.
|
|
gXPCOMShuttingDown = PR_TRUE;
|
|
|
|
// We may have AddRef'd for the caller of NS_InitXPCOM, so release it
|
|
// here again:
|
|
NS_IF_RELEASE(servMgr);
|
|
|
|
// Shutdown global servicemanager
|
|
nsComponentManagerImpl::gComponentManager->FreeServices();
|
|
nsServiceManager::ShutdownGlobalServiceManager(nsnull);
|
|
|
|
if (currentQ) {
|
|
currentQ->ProcessPendingEvents();
|
|
currentQ = 0;
|
|
}
|
|
|
|
// Release the directory service
|
|
NS_IF_RELEASE(gDirectoryService);
|
|
|
|
// Shutdown nsLocalFile string conversion
|
|
NS_ShutdownLocalFile();
|
|
|
|
// Shutdown the timer thread and all timers that might still be alive before
|
|
// shutting down the component manager
|
|
nsTimerImpl::Shutdown();
|
|
|
|
// Shutdown xpcom. This will release all loaders and cause others holding
|
|
// a refcount to the component manager to release it.
|
|
rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
|
|
|
|
// Release our own singletons
|
|
// Do this _after_ shutting down the component manager, because the
|
|
// JS component loader will use XPConnect to call nsIModule::canUnload,
|
|
// and that will spin up the InterfaceInfoManager again -- bad mojo
|
|
XPTI_FreeInterfaceInfoManager();
|
|
|
|
// Finally, release the component manager last because it unloads the
|
|
// libraries:
|
|
NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
|
|
NS_WARN_IF_FALSE(cnt == 0, "Component Manager being held past XPCOM shutdown.");
|
|
nsComponentManagerImpl::gComponentManager = nsnull;
|
|
|
|
#ifdef DEBUG
|
|
extern void _FreeAutoLockStatics();
|
|
_FreeAutoLockStatics();
|
|
#endif
|
|
|
|
ShutdownSpecialSystemDirectory();
|
|
|
|
EmptyEnumeratorImpl::Shutdown();
|
|
nsMemoryImpl::Shutdown();
|
|
NS_IF_RELEASE(gMemory);
|
|
|
|
nsThread::Shutdown();
|
|
NS_PurgeAtomTable();
|
|
|
|
CallExitRoutines();
|
|
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
nsTraceRefcnt::DumpStatistics();
|
|
nsTraceRefcnt::ResetStatistics();
|
|
nsTraceRefcnt::Shutdown();
|
|
#endif
|
|
|
|
#ifdef GC_LEAK_DETECTOR
|
|
// Shutdown the Leak detector.
|
|
NS_ShutdownLeakDetector();
|
|
#endif
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
|