1999-03-10 12:53:25 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
1999-03-09 12:44:27 +03:00
|
|
|
/*
|
1999-11-06 06:43:54 +03:00
|
|
|
* 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/
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
1999-11-06 06:43:54 +03:00
|
|
|
* 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.
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
1999-11-06 06:43:54 +03:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1999-03-09 12:44:27 +03:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 06:43:54 +03:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
2000-05-03 02:38:04 +04:00
|
|
|
* This Original Code has been modified by IBM Corporation.
|
|
|
|
* Modifications made by IBM described herein are
|
|
|
|
* Copyright (c) International Business Machines
|
|
|
|
* Corporation, 2000
|
|
|
|
*
|
|
|
|
* Modifications to Mozilla code or documentation
|
|
|
|
* identified per MPL Section 3.3
|
|
|
|
*
|
|
|
|
* Date Modified by Description of modification
|
|
|
|
* 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
|
1999-03-09 12:44:27 +03:00
|
|
|
*/
|
1999-06-22 18:02:58 +04:00
|
|
|
#include <stdlib.h>
|
2000-04-25 09:11:30 +04:00
|
|
|
#include "nscore.h"
|
|
|
|
#include "nsISupports.h"
|
2001-10-16 07:35:52 +04:00
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nspr.h"
|
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
// Arena used by component manager for storing contractid string, dll
|
|
|
|
// location strings and small objects
|
|
|
|
// CAUTION: Arena align mask needs to be defined before including plarena.h
|
|
|
|
// currently from nsComponentManager.h
|
|
|
|
#define PL_ARENA_CONST_ALIGN_MASK 7
|
|
|
|
#define NS_CM_BLOCK_SIZE (1024)
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "NSReg.h"
|
|
|
|
#include "nsAutoLock.h"
|
1999-06-22 18:02:58 +04:00
|
|
|
#include "nsCOMPtr.h"
|
1999-03-09 12:44:27 +03:00
|
|
|
#include "nsComponentManager.h"
|
2001-12-19 03:12:41 +03:00
|
|
|
#include "nsComponentManagerObsolete.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsDirectoryService.h"
|
|
|
|
#include "nsDirectoryServiceDefs.h"
|
2000-05-26 08:56:23 +04:00
|
|
|
#include "nsICategoryManager.h"
|
2002-03-22 02:43:21 +03:00
|
|
|
#include "nsCategoryManagerUtils.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsIComponentLoader.h"
|
1999-07-02 07:35:09 +04:00
|
|
|
#include "nsIEnumerator.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsIInterfaceInfoManager.h"
|
1999-08-09 09:40:51 +04:00
|
|
|
#include "nsIModule.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsIObserverService.h"
|
|
|
|
#include "nsISimpleEnumerator.h"
|
1999-08-09 09:02:25 +04:00
|
|
|
#include "nsISupportsPrimitives.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsLocalFile.h"
|
1999-09-01 01:40:21 +04:00
|
|
|
#include "nsNativeComponentLoader.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsRegistry.h"
|
1999-11-10 03:28:34 +03:00
|
|
|
#include "nsXPIDLString.h"
|
1999-03-09 12:44:27 +03:00
|
|
|
#include "prcmon.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
|
2002-05-03 01:25:08 +04:00
|
|
|
#include <new.h> // for placement new
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-06-29 14:27:58 +04:00
|
|
|
#ifdef XP_BEOS
|
|
|
|
#include <FindDirectory.h>
|
|
|
|
#include <Path.h>
|
|
|
|
#endif
|
|
|
|
|
1999-06-14 06:07:03 +04:00
|
|
|
// Logging of debug output
|
2001-05-05 14:18:53 +04:00
|
|
|
#ifdef MOZ_LOGGING
|
1999-06-29 01:51:46 +04:00
|
|
|
#define FORCE_PR_LOG /* Allow logging in the release build */
|
2001-05-05 14:18:53 +04:00
|
|
|
#endif
|
2000-10-29 02:17:53 +04:00
|
|
|
#include "prlog.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
PRLogModuleInfo* nsComponentManagerLog = nsnull;
|
1999-06-14 06:07:03 +04:00
|
|
|
|
2002-01-10 09:55:18 +03:00
|
|
|
#if defined(DEBUG)
|
2002-05-12 01:15:06 +04:00
|
|
|
// #define SHOW_DENIED_ON_SHUTDOWN
|
2002-01-10 09:55:18 +03:00
|
|
|
#endif
|
2002-01-10 05:10:37 +03:00
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
// Loader Types
|
|
|
|
#define NS_LOADER_DATA_ALLOC_STEP 6
|
|
|
|
|
2001-11-30 10:50:03 +03:00
|
|
|
// Bloated registry buffer size to improve startup performance -- needs to
|
|
|
|
// be big enough to fit the entire file into memory or it'll thrash.
|
|
|
|
// 512K is big enough to allow for some future growth in the registry.
|
|
|
|
#define BIG_REGISTRY_BUFLEN (512*1024)
|
|
|
|
|
1999-04-05 04:07:18 +04:00
|
|
|
// Common Key Names
|
2000-02-20 06:12:59 +03:00
|
|
|
const char classIDKeyName[]="classID";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char classesKeyName[]="contractID";
|
2000-02-16 10:45:20 +03:00
|
|
|
const char componentLoadersKeyName[]="componentLoaders";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char componentsKeyName[]="components";
|
2000-02-16 10:45:20 +03:00
|
|
|
const char xpcomComponentsKeyName[]="software/mozilla/XPCOM/components";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char xpcomKeyName[]="software/mozilla/XPCOM";
|
1999-04-05 04:07:18 +04:00
|
|
|
|
|
|
|
// Common Value Names
|
2000-02-20 06:12:59 +03:00
|
|
|
const char classIDValueName[]="ClassID";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char classNameValueName[]="ClassName";
|
1999-04-05 04:07:18 +04:00
|
|
|
const char componentCountValueName[]="ComponentsCount";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char componentTypeValueName[]="ComponentType";
|
2000-09-14 03:57:52 +04:00
|
|
|
const char contractIDValueName[]="ContractID";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char fileSizeValueName[]="FileSize";
|
1999-04-05 04:07:18 +04:00
|
|
|
const char inprocServerValueName[]="InprocServer";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char lastModValueName[]="LastModTimeStamp";
|
1999-09-02 11:00:29 +04:00
|
|
|
const char nativeComponentType[]="application/x-mozilla-native";
|
2001-06-21 00:21:49 +04:00
|
|
|
const char staticComponentType[]="application/x-mozilla-static";
|
2002-01-30 00:22:13 +03:00
|
|
|
const char versionValueName[]="VersionString";
|
1999-04-05 04:07:18 +04:00
|
|
|
|
1999-09-07 09:06:37 +04:00
|
|
|
const static char XPCOM_ABSCOMPONENT_PREFIX[] = "abs:";
|
|
|
|
const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:";
|
|
|
|
const char XPCOM_LIB_PREFIX[] = "lib:";
|
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
// Nonexistent factory entry
|
|
|
|
// This is used to mark non-existent contractid mappings
|
|
|
|
static nsFactoryEntry * kNonExistentContractID = (nsFactoryEntry*) 1;
|
1999-04-12 16:32:24 +04:00
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
|
|
|
|
#define NS_EMPTY_IID \
|
|
|
|
{ \
|
|
|
|
0x00000000, \
|
|
|
|
0x0000, \
|
|
|
|
0x0000, \
|
|
|
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DEFINE_CID(kEmptyCID, NS_EMPTY_IID);
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
// Set to true from NS_ShutdownXPCOM.
|
2001-10-16 07:35:52 +04:00
|
|
|
extern PRBool gXPCOMShuttingDown;
|
2001-09-07 01:13:11 +04:00
|
|
|
|
1999-06-14 06:07:03 +04:00
|
|
|
// Build is using USE_NSREG to turn off xpcom using registry
|
|
|
|
// but internally we use USE_REGISTRY. Map them propertly.
|
|
|
|
#ifdef USE_NSREG
|
|
|
|
#define USE_REGISTRY
|
|
|
|
#endif /* USE_NSREG */
|
1999-04-12 16:32:24 +04:00
|
|
|
|
1999-10-31 03:35:48 +03:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
nsresult
|
2002-03-22 02:43:21 +03:00
|
|
|
nsCreateInstanceFromCategory::operator()( const nsIID& aIID, void** aInstancePtr) const
|
2000-05-26 08:56:23 +04:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If I were a real man, I would consolidate this with
|
2000-09-14 03:57:52 +04:00
|
|
|
* nsGetServiceFromContractID::operator().
|
2000-05-26 08:56:23 +04:00
|
|
|
*/
|
|
|
|
nsresult status;
|
|
|
|
nsXPIDLCString value;
|
2002-03-22 02:43:21 +03:00
|
|
|
nsCOMPtr<nsIComponentManager> compMgr;
|
2000-05-26 08:56:23 +04:00
|
|
|
nsCOMPtr<nsICategoryManager> catman =
|
2000-09-14 03:57:52 +04:00
|
|
|
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &status);
|
2002-03-22 02:43:21 +03:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
if (NS_FAILED(status)) goto error;
|
2002-03-22 02:43:21 +03:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
if (!mCategory || !mEntry) {
|
|
|
|
// when categories have defaults, use that for null mEntry
|
|
|
|
status = NS_ERROR_NULL_POINTER;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
/* find the contractID for category.entry */
|
2000-05-26 08:56:23 +04:00
|
|
|
status = catman->GetCategoryEntry(mCategory, mEntry,
|
|
|
|
getter_Copies(value));
|
|
|
|
if (NS_FAILED(status)) goto error;
|
|
|
|
if (!value) {
|
|
|
|
status = NS_ERROR_SERVICE_NOT_FOUND;
|
|
|
|
goto error;
|
|
|
|
}
|
2002-03-22 02:43:21 +03:00
|
|
|
NS_GetComponentManager(getter_AddRefs(compMgr));
|
|
|
|
if (!compMgr)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
compMgr->CreateInstanceByContractID(value,
|
|
|
|
mOuter,
|
|
|
|
aIID,
|
|
|
|
aInstancePtr);
|
|
|
|
error:
|
2000-05-26 08:56:23 +04:00
|
|
|
if (NS_FAILED(status)) {
|
|
|
|
*aInstancePtr = 0;
|
|
|
|
}
|
2002-03-22 02:43:21 +03:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
*mErrorPtr = status;
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
|
|
|
|
nsresult
|
2002-03-22 02:43:21 +03:00
|
|
|
nsGetServiceFromCategory::operator()( const nsIID& aIID, void** aInstancePtr) const
|
|
|
|
{
|
|
|
|
nsresult status;
|
|
|
|
nsXPIDLCString value;
|
|
|
|
nsCOMPtr<nsICategoryManager> catman =
|
|
|
|
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &status);
|
|
|
|
if (NS_FAILED(status)) goto error;
|
|
|
|
if (!mCategory || !mEntry) {
|
|
|
|
// when categories have defaults, use that for null mEntry
|
|
|
|
status = NS_ERROR_NULL_POINTER;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
/* find the contractID for category.entry */
|
|
|
|
status = catman->GetCategoryEntry(mCategory, mEntry,
|
|
|
|
getter_Copies(value));
|
|
|
|
if (NS_FAILED(status)) goto error;
|
|
|
|
if (!value) {
|
|
|
|
status = NS_ERROR_SERVICE_NOT_FOUND;
|
|
|
|
goto error;
|
2001-10-16 07:35:52 +04:00
|
|
|
}
|
|
|
|
if ( mServiceManager ) {
|
2002-03-22 02:43:21 +03:00
|
|
|
status = mServiceManager->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
|
2001-10-16 07:35:52 +04:00
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIServiceManager> mgr;
|
|
|
|
NS_GetServiceManager(getter_AddRefs(mgr));
|
|
|
|
if (mgr)
|
2002-03-22 02:43:21 +03:00
|
|
|
status = mgr->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
|
2001-10-16 07:35:52 +04:00
|
|
|
}
|
2002-03-22 02:43:21 +03:00
|
|
|
if (NS_FAILED(status)) {
|
|
|
|
error:
|
2001-10-16 07:35:52 +04:00
|
|
|
*aInstancePtr = 0;
|
|
|
|
}
|
2002-03-22 02:43:21 +03:00
|
|
|
*mErrorPtr = status;
|
|
|
|
return status;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
2002-03-22 02:43:21 +03:00
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Arena helper functions
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static inline char *
|
|
|
|
ArenaStrdup(const char *s, PLArenaPool *arena)
|
|
|
|
{
|
|
|
|
void *mem;
|
|
|
|
// Include trailing null in the len
|
|
|
|
PRInt32 len = strlen(s) + 1;
|
|
|
|
PL_ARENA_ALLOCATE(mem, arena, len);
|
|
|
|
if (mem)
|
|
|
|
memcpy(mem, s, len);
|
|
|
|
return NS_STATIC_CAST(char *, mem);
|
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Hashtable Callbacks
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2000-05-03 02:38:04 +04:00
|
|
|
PRBool PR_CALLBACK
|
1999-09-01 01:40:21 +04:00
|
|
|
nsFactoryEntry_Destroy(nsHashKey *aKey, void *aData, void* closure);
|
1999-04-12 16:32:24 +04:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
PR_STATIC_CALLBACK(const void *)
|
|
|
|
factory_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
|
|
|
|
{
|
|
|
|
nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
|
|
|
|
|
|
|
|
return &entry->mFactoryEntry->cid;
|
|
|
|
}
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PLDHashNumber)
|
|
|
|
factory_HashKey(PLDHashTable *aTable, const void *aKey)
|
|
|
|
{
|
|
|
|
const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
|
|
|
|
|
|
|
|
return cidp->m0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
factory_MatchEntry(PLDHashTable *aTable, const PLDHashEntryHdr *aHdr,
|
|
|
|
const void *aKey)
|
|
|
|
{
|
|
|
|
const nsFactoryTableEntry* entry =
|
|
|
|
NS_STATIC_CAST(const nsFactoryTableEntry*, aHdr);
|
|
|
|
const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
|
|
|
|
|
|
|
|
return (entry->mFactoryEntry->cid).Equals(*cidp);
|
|
|
|
}
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(void)
|
|
|
|
factory_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
|
|
|
|
{
|
|
|
|
nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
|
2002-05-03 01:25:08 +04:00
|
|
|
// nsFactoryEntry is arena allocated. So we dont delete it.
|
|
|
|
// We call the destructor by hand.
|
|
|
|
entry->mFactoryEntry->~nsFactoryEntry();
|
2001-10-23 06:28:12 +04:00
|
|
|
PL_DHashClearEntryStub(aTable, aHdr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PLDHashTableOps factory_DHashTableOps = {
|
|
|
|
PL_DHashAllocTable,
|
|
|
|
PL_DHashFreeTable,
|
|
|
|
factory_GetKey,
|
|
|
|
factory_HashKey,
|
|
|
|
factory_MatchEntry,
|
|
|
|
PL_DHashMoveEntryStub,
|
|
|
|
factory_ClearEntry,
|
|
|
|
PL_DHashFinalizeStub,
|
|
|
|
};
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(const void *)
|
|
|
|
contractID_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
|
|
|
|
{
|
|
|
|
nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
|
|
|
|
|
|
|
|
return entry->mContractID;
|
|
|
|
}
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
contractID_MatchEntry(PLDHashTable *aTable, const PLDHashEntryHdr *aHdr,
|
|
|
|
const void *aKey)
|
|
|
|
{
|
|
|
|
const nsContractIDTableEntry* entry =
|
|
|
|
NS_STATIC_CAST(const nsContractIDTableEntry*, aHdr);
|
|
|
|
|
|
|
|
const char* contractID = NS_REINTERPRET_CAST(const char*, aKey);
|
|
|
|
|
|
|
|
return strcmp(entry->mContractID, contractID) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(void)
|
|
|
|
contractID_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
|
|
|
|
{
|
|
|
|
nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
|
|
|
|
|
|
|
|
if (entry->mFactoryEntry != kNonExistentContractID &&
|
|
|
|
entry->mFactoryEntry->typeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY &&
|
|
|
|
entry->mFactoryEntry->cid.Equals(kEmptyCID)) {
|
2002-05-03 01:25:08 +04:00
|
|
|
// this object is owned by the hash.
|
|
|
|
// nsFactoryEntry is arena allocated. So we dont delete it.
|
|
|
|
// We call the destructor by hand.
|
|
|
|
entry->mFactoryEntry->~nsFactoryEntry();
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
// contractIDs are arena allocated. No need to free them.
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
PL_DHashClearEntryStub(aTable, aHdr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PLDHashTableOps contractID_DHashTableOps = {
|
|
|
|
PL_DHashAllocTable,
|
|
|
|
PL_DHashFreeTable,
|
|
|
|
contractID_GetKey,
|
|
|
|
PL_DHashStringKey,
|
|
|
|
contractID_MatchEntry,
|
|
|
|
PL_DHashMoveEntryStub,
|
|
|
|
contractID_ClearEntry,
|
|
|
|
PL_DHashFinalizeStub,
|
|
|
|
};
|
2001-09-07 01:13:11 +04:00
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsFactoryEntry
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2001-01-28 02:06:33 +03:00
|
|
|
MOZ_DECL_CTOR_COUNTER(nsFactoryEntry)
|
2001-09-07 01:13:11 +04:00
|
|
|
nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
|
|
|
|
const char *aLocation,
|
2001-08-30 18:10:41 +04:00
|
|
|
int aType)
|
2001-11-16 16:53:04 +03:00
|
|
|
: cid(aClass), typeIndex(aType)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2002-05-03 01:25:08 +04:00
|
|
|
// Arena allocate the location string
|
|
|
|
location = ArenaStrdup(aLocation, &nsComponentManagerImpl::gComponentManager->mArena);
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsFactoryEntry::nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory)
|
2001-11-16 16:53:04 +03:00
|
|
|
: cid(aClass), typeIndex(NS_COMPONENT_TYPE_FACTORY_ONLY)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
1999-09-01 01:40:21 +04:00
|
|
|
factory = aFactory;
|
2001-10-23 06:28:12 +04:00
|
|
|
location = nsnull;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
// nsFactoryEntry is usually arena allocated including the strings it
|
|
|
|
// holds. So we call destructor by hand.
|
1999-03-09 12:44:27 +03:00
|
|
|
nsFactoryEntry::~nsFactoryEntry(void)
|
|
|
|
{
|
2002-05-03 01:25:08 +04:00
|
|
|
// Release the reference to the factory
|
|
|
|
factory = nsnull;
|
|
|
|
|
|
|
|
// Release any service reference
|
|
|
|
mServiceObject = nsnull;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
nsresult
|
2001-08-30 18:10:41 +04:00
|
|
|
nsFactoryEntry::ReInit(const nsCID &aClass, const char *aLocation, int aType)
|
2001-08-22 02:42:35 +04:00
|
|
|
{
|
2001-09-08 04:01:03 +04:00
|
|
|
NS_ENSURE_TRUE(typeIndex != NS_COMPONENT_TYPE_FACTORY_ONLY, NS_ERROR_INVALID_ARG);
|
|
|
|
// cid has to match
|
|
|
|
// SERVICE_ONLY entries can be promoted to an entry of another type
|
|
|
|
NS_ENSURE_TRUE((typeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || cid.Equals(aClass)),
|
|
|
|
NS_ERROR_INVALID_ARG);
|
2002-05-03 01:25:08 +04:00
|
|
|
|
|
|
|
// Arena allocate the location string
|
|
|
|
location = ArenaStrdup(aLocation, &nsComponentManagerImpl::gComponentManager->mArena);
|
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
typeIndex = aType;
|
2001-08-22 02:42:35 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFactoryEntry::ReInit(const nsCID &aClass, nsIFactory *aFactory)
|
|
|
|
{
|
2001-09-08 04:01:03 +04:00
|
|
|
// cids has to match
|
|
|
|
// SERVICE_ONLY entries can be promoted to an entry of another type
|
|
|
|
NS_ENSURE_TRUE((typeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || cid.Equals(aClass)),
|
|
|
|
NS_ERROR_INVALID_ARG);
|
2001-09-11 22:10:31 +04:00
|
|
|
// We are going to let native component be overridden by a factory.
|
2001-08-22 02:42:35 +04:00
|
|
|
factory = aFactory;
|
2001-09-07 01:13:11 +04:00
|
|
|
typeIndex = NS_COMPONENT_TYPE_FACTORY_ONLY;
|
2001-08-22 02:42:35 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
|
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2002-01-30 00:22:13 +03:00
|
|
|
// Hashtable Enumeration
|
1999-03-09 12:44:27 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2002-01-30 00:22:13 +03:00
|
|
|
typedef NS_CALLBACK(EnumeratorConverter)(PLDHashTable *table,
|
|
|
|
const PLDHashEntryHdr *hdr,
|
|
|
|
void *data,
|
|
|
|
nsISupports **retval);
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
class PLDHashTableEnumeratorImpl : public nsIBidirectionalEnumerator,
|
|
|
|
public nsISimpleEnumerator
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIENUMERATOR
|
|
|
|
NS_DECL_NSIBIDIRECTIONALENUMERATOR
|
|
|
|
NS_DECL_NSISIMPLEENUMERATOR
|
|
|
|
|
|
|
|
virtual ~PLDHashTableEnumeratorImpl();
|
|
|
|
PLDHashTableEnumeratorImpl(PLDHashTable *table,
|
|
|
|
EnumeratorConverter converter,
|
|
|
|
void *converterData);
|
|
|
|
PRInt32 Count() { return mCount; }
|
|
|
|
private:
|
|
|
|
PLDHashTableEnumeratorImpl(); /* no implementation */
|
|
|
|
NS_IMETHODIMP ReleaseElements();
|
|
|
|
|
|
|
|
nsVoidArray mElements;
|
|
|
|
PRInt32 mCount, mCurrent;
|
|
|
|
PRMonitor* mMonitor;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
struct Closure {
|
|
|
|
PRBool succeeded;
|
|
|
|
EnumeratorConverter converter;
|
|
|
|
void *data;
|
|
|
|
PLDHashTableEnumeratorImpl *impl;
|
|
|
|
};
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
static PLDHashOperator PR_CALLBACK Enumerator(PLDHashTable *table,
|
|
|
|
PLDHashEntryHdr *hdr,
|
|
|
|
PRUint32 number,
|
|
|
|
void *data);
|
|
|
|
};
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
// static
|
|
|
|
PLDHashOperator PR_CALLBACK
|
|
|
|
PLDHashTableEnumeratorImpl::Enumerator(PLDHashTable *table,
|
|
|
|
PLDHashEntryHdr *hdr,
|
|
|
|
PRUint32 number,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
Closure *c = NS_REINTERPRET_CAST(Closure *, data);
|
|
|
|
nsISupports *converted;
|
|
|
|
if (NS_FAILED(c->converter(table, hdr, c->data, &converted)) ||
|
|
|
|
!c->impl->mElements.AppendElement(converted)) {
|
|
|
|
c->succeeded = PR_FALSE;
|
|
|
|
return PL_DHASH_STOP;
|
2000-10-29 02:17:53 +04:00
|
|
|
}
|
1999-06-14 06:07:03 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
c->succeeded = PR_TRUE;
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
PLDHashTableEnumeratorImpl::PLDHashTableEnumeratorImpl(PLDHashTable *table,
|
|
|
|
EnumeratorConverter converter,
|
|
|
|
void *converterData)
|
|
|
|
: mCurrent(0)
|
|
|
|
{
|
|
|
|
mMonitor = nsAutoMonitor::NewMonitor("PLDHashTableEnumeratorImpl");
|
|
|
|
NS_ASSERTION(mMonitor, "NULL Monitor");
|
|
|
|
|
|
|
|
nsAutoMonitor mon(mMonitor);
|
|
|
|
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
Closure c = { PR_FALSE, converter, converterData, this };
|
|
|
|
mCount = PL_DHashTableEnumerate(table, Enumerator, &c);
|
|
|
|
if (!c.succeeded) {
|
|
|
|
ReleaseElements();
|
|
|
|
mCount = 0;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMPL_ISUPPORTS3(PLDHashTableEnumeratorImpl,
|
|
|
|
nsIBidirectionalEnumerator,
|
|
|
|
nsIEnumerator,
|
|
|
|
nsISimpleEnumerator);
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
PLDHashTableEnumeratorImpl::~PLDHashTableEnumeratorImpl()
|
|
|
|
{
|
|
|
|
(void) ReleaseElements();
|
1999-09-01 01:40:21 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
// Destroy the Lock
|
|
|
|
if (mMonitor)
|
2002-04-16 02:33:03 +04:00
|
|
|
nsAutoMonitor::DestroyMonitor(mMonitor);
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::ReleaseElements()
|
|
|
|
{
|
|
|
|
for (PRInt32 i = 0; i < mCount; i++) {
|
|
|
|
nsISupports *supports = NS_REINTERPRET_CAST(nsISupports *,
|
|
|
|
mElements[i]);
|
|
|
|
NS_IF_RELEASE(supports);
|
1999-09-01 01:40:21 +04:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-06-21 00:21:49 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
PL_NewDHashTableEnumerator(PLDHashTable *table,
|
|
|
|
EnumeratorConverter converter,
|
|
|
|
void *converterData,
|
|
|
|
PLDHashTableEnumeratorImpl **retval)
|
|
|
|
{
|
|
|
|
PLDHashTableEnumeratorImpl *impl =
|
|
|
|
new PLDHashTableEnumeratorImpl(table, converter, converterData);
|
|
|
|
|
|
|
|
if (!impl)
|
2001-08-30 18:10:41 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
if (impl->Count() == -1) {
|
|
|
|
// conversion failed
|
|
|
|
delete impl;
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-06-21 00:21:49 +04:00
|
|
|
}
|
2001-09-01 01:45:58 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_ADDREF(*retval = impl);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-03-31 11:04:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::First()
|
|
|
|
{
|
|
|
|
if (!mCount)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
mCurrent = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-01-25 00:28:28 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::Last()
|
|
|
|
{
|
|
|
|
if (!mCount)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
mCurrent = mCount - 1;
|
1999-06-14 06:07:03 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-03-31 11:04:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::Prev()
|
1999-06-14 06:07:03 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
if (!mCurrent)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
mCurrent--;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::Next()
|
|
|
|
{
|
|
|
|
// If empty or we're past the end, or we are at the end return error
|
|
|
|
if (!mCount || (mCurrent == mCount) || (++mCurrent == mCount))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::CurrentItem(nsISupports **retval)
|
|
|
|
{
|
|
|
|
if (!mCount || mCurrent == mCount)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
*retval = NS_REINTERPRET_CAST(nsISupports *, mElements[mCurrent]);
|
|
|
|
if (*retval)
|
|
|
|
NS_ADDREF(*retval);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::IsDone()
|
|
|
|
{
|
|
|
|
if (!mCount || (mCurrent == mCount))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
return NS_COMFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::HasMoreElements(PRBool *_retval)
|
|
|
|
{
|
|
|
|
if (!mCount || (mCurrent == mCount))
|
|
|
|
*_retval = PR_FALSE;
|
|
|
|
else
|
|
|
|
*_retval = PR_TRUE;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
PLDHashTableEnumeratorImpl::GetNext(nsISupports **_retval)
|
|
|
|
{
|
|
|
|
nsresult rv = Next();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return CurrentItem(_retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
static NS_IMETHODIMP
|
|
|
|
ConvertFactoryEntryToCID(PLDHashTable *table,
|
|
|
|
const PLDHashEntryHdr *hdr,
|
|
|
|
void *data, nsISupports **retval)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2002-02-13 23:34:14 +03:00
|
|
|
nsCOMPtr<nsISupportsID> wrapper;
|
|
|
|
|
|
|
|
nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
|
|
|
|
|
|
|
|
rv = cm->CreateInstanceByContractID(NS_SUPPORTS_ID_CONTRACTID, nsnull,
|
|
|
|
NS_GET_IID(nsISupportsID), getter_AddRefs(wrapper));
|
2002-01-30 00:22:13 +03:00
|
|
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
const nsFactoryTableEntry *entry =
|
|
|
|
NS_REINTERPRET_CAST(const nsFactoryTableEntry *, hdr);
|
|
|
|
if(entry) {
|
|
|
|
nsFactoryEntry *fe = entry->mFactoryEntry;
|
|
|
|
|
|
|
|
wrapper->SetData(&fe->cid);
|
|
|
|
*retval = wrapper;
|
|
|
|
NS_ADDREF(*retval);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*retval = nsnull;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static NS_IMETHODIMP
|
|
|
|
ConvertContractIDKeyToString(PLDHashTable *table,
|
|
|
|
const PLDHashEntryHdr *hdr,
|
|
|
|
void *data, nsISupports **retval)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2002-02-13 23:34:14 +03:00
|
|
|
nsCOMPtr<nsISupportsString> wrapper;
|
|
|
|
|
|
|
|
nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
|
|
|
|
|
|
|
|
rv = cm->CreateInstanceByContractID(NS_SUPPORTS_STRING_CONTRACTID, nsnull,
|
|
|
|
NS_GET_IID(nsISupportsString), getter_AddRefs(wrapper));
|
2002-01-30 00:22:13 +03:00
|
|
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
const nsContractIDTableEntry *entry =
|
|
|
|
NS_REINTERPRET_CAST(const nsContractIDTableEntry *, hdr);
|
|
|
|
|
2002-02-13 23:34:14 +03:00
|
|
|
wrapper->SetData(entry->mContractID);
|
2002-01-30 00:22:13 +03:00
|
|
|
*retval = wrapper;
|
|
|
|
NS_ADDREF(*retval);
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsComponentManagerImpl
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
nsComponentManagerImpl::nsComponentManagerImpl()
|
|
|
|
:
|
2002-04-16 02:33:03 +04:00
|
|
|
mMon(nsnull),
|
|
|
|
mRegistry(nsnull),
|
2002-01-30 00:22:13 +03:00
|
|
|
mPrePopulationDone(PR_FALSE),
|
|
|
|
mNativeComponentLoader(0),
|
|
|
|
mStaticComponentLoader(0),
|
|
|
|
mShuttingDown(NS_SHUTDOWN_NEVERHAPPENED),
|
|
|
|
mLoaderData(nsnull)
|
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
mFactories.ops = nsnull;
|
|
|
|
mContractIDs.ops = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsComponentManagerImpl::Init(void)
|
|
|
|
{
|
|
|
|
PR_ASSERT(mShuttingDown != NS_SHUTDOWN_INPROGRESS);
|
|
|
|
if (mShuttingDown == NS_SHUTDOWN_INPROGRESS)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
mShuttingDown = NS_SHUTDOWN_NEVERHAPPENED;
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (nsComponentManagerLog == nsnull)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
|
|
|
nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
|
|
|
("xpcom-log-version : " NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING));
|
|
|
|
}
|
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
// Initialize our arena
|
|
|
|
PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
if (!mFactories.ops) {
|
|
|
|
if (!PL_DHashTableInit(&mFactories, &factory_DHashTableOps,
|
|
|
|
0, sizeof(nsFactoryTableEntry),
|
|
|
|
1024)) {
|
|
|
|
mFactories.ops = nsnull;
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Minimum alpha uses k=3 because nsFactoryTableEntry saves three
|
|
|
|
// words compared to what a chained hash table requires.
|
|
|
|
PL_DHashTableSetAlphaBounds(&mFactories,
|
|
|
|
0.875,
|
|
|
|
PL_DHASH_MIN_ALPHA(&mFactories, 3));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mContractIDs.ops) {
|
|
|
|
if (!PL_DHashTableInit(&mContractIDs, &contractID_DHashTableOps,
|
|
|
|
0, sizeof(nsContractIDTableEntry),
|
|
|
|
1024)) {
|
|
|
|
mContractIDs.ops = nsnull;
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Minimum alpha uses k=2 because nsContractIDTableEntry saves two
|
|
|
|
// words compared to what a chained hash table requires.
|
|
|
|
PL_DHashTableSetAlphaBounds(&mContractIDs,
|
|
|
|
0.875,
|
|
|
|
PL_DHASH_MIN_ALPHA(&mContractIDs, 2));
|
|
|
|
}
|
2002-04-16 02:33:03 +04:00
|
|
|
if (mMon == nsnull) {
|
|
|
|
mMon = nsAutoMonitor::NewMonitor("nsComponentManagerImpl");
|
|
|
|
if (mMon == nsnull)
|
2002-01-30 00:22:13 +03:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mNativeComponentLoader == nsnull) {
|
|
|
|
/* Create the NativeComponentLoader */
|
|
|
|
mNativeComponentLoader = new nsNativeComponentLoader();
|
|
|
|
if (!mNativeComponentLoader)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(mNativeComponentLoader);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add predefined loaders
|
|
|
|
mLoaderData = (nsLoaderdata *) PR_Malloc(sizeof(nsLoaderdata) * NS_LOADER_DATA_ALLOC_STEP);
|
|
|
|
if (!mLoaderData)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
mMaxNLoaderData = NS_LOADER_DATA_ALLOC_STEP;
|
|
|
|
|
|
|
|
mNLoaderData = NS_COMPONENT_TYPE_NATIVE;
|
|
|
|
mLoaderData[mNLoaderData].type = PL_strdup(nativeComponentType);
|
|
|
|
mLoaderData[mNLoaderData].loader = mNativeComponentLoader;
|
|
|
|
NS_ADDREF(mLoaderData[mNLoaderData].loader);
|
|
|
|
mNLoaderData++;
|
|
|
|
|
|
|
|
#ifdef ENABLE_STATIC_COMPONENT_LOADER
|
|
|
|
if (mStaticComponentLoader == nsnull) {
|
|
|
|
extern nsresult NS_NewStaticComponentLoader(nsIComponentLoader **);
|
|
|
|
NS_NewStaticComponentLoader(&mStaticComponentLoader);
|
|
|
|
if (!mStaticComponentLoader)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mLoaderData[mNLoaderData].type = PL_strdup(staticComponentType);
|
|
|
|
mLoaderData[mNLoaderData].loader = mStaticComponentLoader;
|
|
|
|
NS_ADDREF(mLoaderData[mNLoaderData].loader);
|
|
|
|
mNLoaderData++;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_REGISTRY
|
|
|
|
NR_StartupRegistry();
|
|
|
|
{
|
|
|
|
nsresult ret;
|
|
|
|
ret = PlatformInit();
|
|
|
|
if( NS_FAILED( ret ) ) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
|
|
|
("nsComponentManager: Initialized."));
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsComponentManagerImpl::Shutdown(void)
|
|
|
|
{
|
|
|
|
PR_ASSERT(mShuttingDown == NS_SHUTDOWN_NEVERHAPPENED);
|
|
|
|
if (mShuttingDown != NS_SHUTDOWN_NEVERHAPPENED)
|
1999-10-22 01:34:39 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
mShuttingDown = NS_SHUTDOWN_INPROGRESS;
|
|
|
|
|
|
|
|
// Shutdown the component manager
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS, ("nsComponentManager: Beginning Shutdown."));
|
1999-07-31 09:55:04 +04:00
|
|
|
|
|
|
|
// Release all cached factories
|
2001-10-23 06:28:12 +04:00
|
|
|
if (mContractIDs.ops) {
|
|
|
|
PL_DHashTableFinish(&mContractIDs);
|
|
|
|
mContractIDs.ops = nsnull;
|
|
|
|
}
|
|
|
|
if (mFactories.ops) {
|
|
|
|
PL_DHashTableFinish(&mFactories);
|
|
|
|
mFactories.ops = nsnull;
|
|
|
|
}
|
1999-07-31 09:55:04 +04:00
|
|
|
// Unload libraries
|
2002-04-16 02:33:03 +04:00
|
|
|
UnloadLibraries(nsnull, NS_Shutdown);
|
1999-07-31 09:55:04 +04:00
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
// delete arena for strings and small objects
|
|
|
|
PL_FinishArenaPool(&mArena);
|
|
|
|
|
1999-06-14 06:07:03 +04:00
|
|
|
#ifdef USE_REGISTRY
|
1999-07-31 09:55:04 +04:00
|
|
|
// Release registry
|
1999-09-01 01:40:21 +04:00
|
|
|
NS_IF_RELEASE(mRegistry);
|
1999-06-14 06:07:03 +04:00
|
|
|
#endif /* USE_REGISTRY */
|
1999-09-01 01:40:21 +04:00
|
|
|
|
2000-01-29 02:37:27 +03:00
|
|
|
// This is were the nsFileSpec was deleted, so I am
|
2000-05-12 05:24:36 +04:00
|
|
|
// going to assign zero to
|
|
|
|
mComponentsDir = 0;
|
1999-09-21 00:53:57 +04:00
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
// Release all the component data - loaders and type strings
|
|
|
|
for(int i=0; i < mNLoaderData; i++) {
|
|
|
|
NS_IF_RELEASE(mLoaderData[i].loader);
|
|
|
|
PL_strfree((char *)mLoaderData[i].type);
|
|
|
|
}
|
|
|
|
PR_Free(mLoaderData);
|
|
|
|
mLoaderData = nsnull;
|
1999-09-01 01:40:21 +04:00
|
|
|
|
|
|
|
// we have an extra reference on this one, which is probably a good thing
|
|
|
|
NS_IF_RELEASE(mNativeComponentLoader);
|
2001-06-21 00:21:49 +04:00
|
|
|
#ifdef ENABLE_STATIC_COMPONENT_LOADER
|
|
|
|
NS_IF_RELEASE(mStaticComponentLoader);
|
|
|
|
#endif
|
1999-07-31 09:55:04 +04:00
|
|
|
|
1999-09-27 01:20:21 +04:00
|
|
|
#ifdef USE_REGISTRY
|
|
|
|
NR_ShutdownRegistry();
|
|
|
|
#endif /* USE_REGISTRY */
|
|
|
|
|
1999-10-22 01:34:39 +04:00
|
|
|
mShuttingDown = NS_SHUTDOWN_COMPLETE;
|
1999-07-31 09:55:04 +04:00
|
|
|
|
1999-10-22 01:34:39 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS, ("nsComponentManager: Shutdown complete."));
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsComponentManagerImpl::~nsComponentManagerImpl()
|
|
|
|
{
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS, ("nsComponentManager: Beginning destruction."));
|
|
|
|
|
|
|
|
if (mShuttingDown != NS_SHUTDOWN_COMPLETE)
|
|
|
|
Shutdown();
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (mMon) {
|
|
|
|
nsAutoMonitor::DestroyMonitor(mMon);
|
|
|
|
}
|
1999-10-22 01:34:39 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS, ("nsComponentManager: Destroyed."));
|
1999-06-14 06:07:03 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS7(nsComponentManagerImpl,
|
2001-10-16 07:35:52 +04:00
|
|
|
nsIComponentManager,
|
|
|
|
nsIServiceManager,
|
|
|
|
nsISupportsWeakReference,
|
2001-10-17 03:39:20 +04:00
|
|
|
nsIInterfaceRequestor,
|
2002-01-30 00:22:13 +03:00
|
|
|
nsIComponentRegistrar,
|
2001-12-19 03:12:41 +03:00
|
|
|
nsIServiceManagerObsolete,
|
|
|
|
nsIComponentManagerObsolete)
|
1999-06-14 06:07:03 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
|
|
|
|
{
|
|
|
|
if (uuid.Equals(NS_GET_IID(nsIServiceManager)))
|
|
|
|
{
|
|
|
|
*result = NS_STATIC_CAST(nsIServiceManager*, this);
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fall through to QI as anything QIable is a superset of what canbe
|
|
|
|
// got via the GetInterface()
|
|
|
|
return QueryInterface(uuid, result);
|
|
|
|
}
|
|
|
|
|
1999-06-14 06:07:03 +04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsComponentManagerImpl: Platform methods
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifdef USE_REGISTRY
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::PlatformInit(void)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
1999-06-22 18:02:58 +04:00
|
|
|
// We need to create our registry. Since we are in the constructor
|
1999-06-14 06:07:03 +04:00
|
|
|
// we haven't gone as far as registering the registry factory.
|
|
|
|
// Hence, we hand create a registry.
|
2002-04-16 02:33:03 +04:00
|
|
|
if (mRegistry == nsnull) {
|
|
|
|
nsIFactory *registryFactory = nsnull;
|
1999-06-14 06:07:03 +04:00
|
|
|
rv = NS_RegistryGetFactory(®istryFactory);
|
1999-03-31 11:04:12 +04:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
2002-04-16 02:33:03 +04:00
|
|
|
rv = registryFactory->CreateInstance(nsnull, NS_GET_IID(nsIRegistry),(void **)&mRegistry);
|
1999-06-14 06:07:03 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-03-31 11:04:12 +04:00
|
|
|
NS_RELEASE(registryFactory);
|
|
|
|
}
|
|
|
|
}
|
1999-03-11 10:44:23 +03:00
|
|
|
|
1999-06-09 23:18:24 +04:00
|
|
|
// Open the App Components registry. We will keep it open forever!
|
1999-06-14 06:07:03 +04:00
|
|
|
rv = mRegistry->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2001-04-17 18:25:19 +04:00
|
|
|
// Set larger-than-standard buffer size to speed startup.
|
|
|
|
// This will be re-set at the end of PrePopulateRegistry()
|
2001-11-30 10:50:03 +03:00
|
|
|
((nsRegistry *)mRegistry)->SetBufferSize( BIG_REGISTRY_BUFLEN );
|
2001-04-17 18:25:19 +04:00
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
// Check the version of registry. Nuke old versions.
|
2000-02-16 10:45:20 +03:00
|
|
|
nsRegistryKey xpcomRoot;
|
|
|
|
rv = PlatformVersionCheck(&xpcomRoot);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-04-06 12:26:38 +04:00
|
|
|
|
1999-05-06 17:29:37 +04:00
|
|
|
// Open common registry keys here to speed access
|
|
|
|
// Do this after PlatformVersionCheck as it may re-create our keys
|
2000-02-16 10:45:20 +03:00
|
|
|
rv = mRegistry->AddSubtree(xpcomRoot, componentsKeyName, &mXPCOMKey);
|
1999-06-14 06:07:03 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-04-06 12:26:38 +04:00
|
|
|
|
2000-02-16 10:45:20 +03:00
|
|
|
rv = mRegistry->AddSubtree(xpcomRoot, classesKeyName, &mClassesKey);
|
1999-06-14 06:07:03 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-04-06 12:26:38 +04:00
|
|
|
|
2000-02-16 10:45:20 +03:00
|
|
|
rv = mRegistry->AddSubtree(xpcomRoot, classIDKeyName, &mCLSIDKey);
|
1999-06-14 06:07:03 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
2001-11-30 10:50:03 +03:00
|
|
|
|
2000-01-25 00:28:28 +03:00
|
|
|
nsCOMPtr<nsIProperties> directoryService;
|
|
|
|
rv = nsDirectoryService::Create(nsnull,
|
|
|
|
NS_GET_IID(nsIProperties),
|
|
|
|
getter_AddRefs(directoryService));
|
2001-11-30 10:50:03 +03:00
|
|
|
|
2000-08-12 00:31:57 +04:00
|
|
|
directoryService->Get(NS_XPCOM_COMPONENT_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mComponentsDir));
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-09-07 09:06:37 +04:00
|
|
|
if (!mComponentsDir)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2001-11-30 10:50:03 +03:00
|
|
|
|
2002-04-27 09:33:09 +04:00
|
|
|
nsCAutoString componentDescriptor;
|
|
|
|
rv = mComponentsDir->GetNativePath(componentDescriptor);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-12-14 04:27:16 +03:00
|
|
|
|
2002-04-27 09:33:09 +04:00
|
|
|
mComponentsOffset = componentDescriptor.Length();
|
2001-12-14 04:27:16 +03:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
if (mNativeComponentLoader) {
|
|
|
|
/* now that we have the registry, Init the native loader */
|
|
|
|
rv = mNativeComponentLoader->Init(this, mRegistry);
|
|
|
|
} else {
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
|
|
|
("no native component loader available for init"));
|
|
|
|
}
|
2001-06-21 00:21:49 +04:00
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
#ifdef ENABLE_STATIC_COMPONENT_LOADER
|
2001-06-21 00:21:49 +04:00
|
|
|
if (mStaticComponentLoader) {
|
2001-08-30 18:10:41 +04:00
|
|
|
/* now that we have the registry, Init the static loader */
|
2001-06-21 00:21:49 +04:00
|
|
|
rv = mStaticComponentLoader->Init(this, mRegistry);
|
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
#endif
|
2001-06-21 00:21:49 +04:00
|
|
|
|
1999-06-14 06:07:03 +04:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* PlatformVersionCheck()
|
|
|
|
*
|
|
|
|
* Checks to see if the XPCOM hierarchy in the registry is the same as that of
|
|
|
|
* the software as defined by NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING
|
|
|
|
*/
|
|
|
|
nsresult
|
2000-02-16 10:45:20 +03:00
|
|
|
nsComponentManagerImpl::PlatformVersionCheck(nsRegistryKey *aXPCOMRootKey)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey xpcomKey;
|
1999-06-14 06:07:03 +04:00
|
|
|
nsresult rv;
|
|
|
|
rv = mRegistry->AddSubtree(nsIRegistry::Common, xpcomKeyName, &xpcomKey);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
2001-11-30 10:50:03 +03:00
|
|
|
|
1999-11-10 03:28:34 +03:00
|
|
|
nsXPIDLCString buf;
|
2000-02-15 04:32:12 +03:00
|
|
|
nsresult err = mRegistry->GetStringUTF8(xpcomKey, versionValueName,
|
1999-11-10 03:28:34 +03:00
|
|
|
getter_Copies(buf));
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
// If there is a version mismatch or no version string, we got an old registry.
|
|
|
|
// Delete the old repository hierarchies and recreate version string
|
1999-05-06 17:29:37 +04:00
|
|
|
if (NS_FAILED(err) || PL_strcmp(buf, NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING))
|
1999-03-10 12:53:25 +03:00
|
|
|
{
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
2000-03-12 01:44:51 +03:00
|
|
|
("nsComponentManager: Registry version mismatch (old:%s vs new:%s)."
|
1999-11-10 03:28:34 +03:00
|
|
|
"Nuking xpcom registry hierarchy.", (const char *)buf,
|
|
|
|
NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING));
|
1999-03-10 12:53:25 +03:00
|
|
|
|
2000-02-16 10:45:20 +03:00
|
|
|
// Delete the XPCOM hierarchy
|
|
|
|
rv = mRegistry->RemoveSubtree(nsIRegistry::Common, xpcomKeyName);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
2000-02-16 10:45:20 +03:00
|
|
|
("nsComponentManager: Failed To Nuke Subtree (%s)",xpcomKeyName));
|
|
|
|
return rv;
|
1999-03-31 11:04:12 +04:00
|
|
|
}
|
|
|
|
|
2000-02-16 10:45:20 +03:00
|
|
|
// The top-level Classes and CLSID trees are from an early alpha version,
|
|
|
|
// we can probably remove these two deletions after the second beta or so.
|
2000-03-12 01:44:51 +03:00
|
|
|
(void) mRegistry->RemoveSubtree(nsIRegistry::Common, classIDKeyName);
|
|
|
|
(void) mRegistry->RemoveSubtree(nsIRegistry::Common, classesKeyName);
|
1999-03-31 11:04:12 +04:00
|
|
|
|
2000-02-16 10:45:20 +03:00
|
|
|
// Recreate XPCOM key and version
|
|
|
|
rv = mRegistry->AddSubtree(nsIRegistry::Common,xpcomKeyName, &xpcomKey);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
2000-02-16 10:45:20 +03:00
|
|
|
("nsComponentManager: Failed To Add Subtree (%s)",xpcomKeyName));
|
1999-03-31 11:04:12 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2000-02-15 04:32:12 +03:00
|
|
|
rv = mRegistry->SetStringUTF8(xpcomKey,versionValueName, NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
1999-04-05 04:07:18 +04:00
|
|
|
("nsComponentManager: Failed To Set String (Version) Under (%s)",xpcomKeyName));
|
1999-03-31 11:04:12 +04:00
|
|
|
return rv;
|
|
|
|
}
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
2000-02-16 10:45:20 +03:00
|
|
|
else
|
1999-03-31 11:04:12 +04:00
|
|
|
{
|
1999-03-10 12:53:25 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
|
|
|
("nsComponentManager: platformVersionCheck() passed."));
|
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2000-02-16 10:45:20 +03:00
|
|
|
|
2000-03-12 01:44:51 +03:00
|
|
|
// return the XPCOM key (null check deferred so cleanup always happens)
|
2000-02-16 10:45:20 +03:00
|
|
|
if (!aXPCOMRootKey)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
else
|
|
|
|
*aXPCOMRootKey = xpcomKey;
|
1999-09-02 11:00:29 +04:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
return NS_OK;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2002-01-30 00:22:13 +03:00
|
|
|
nsComponentManagerImpl::PlatformUnregister(const char *cidString,
|
|
|
|
const char *aLibrary)
|
2000-05-12 05:24:36 +04:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
PRUint32 length = strlen(aLibrary);
|
|
|
|
char* eLibrary;
|
|
|
|
rv = mRegistry->EscapeKey((PRUint8*)aLibrary, 1, &length, (PRUint8**)&eLibrary);
|
|
|
|
if (rv != NS_OK)
|
|
|
|
{
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
if (eLibrary == nsnull) // No escaping required
|
|
|
|
eLibrary = (char*)aLibrary;
|
|
|
|
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
PR_ASSERT(mRegistry!=nsnull);
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey cidKey;
|
1999-06-14 06:07:03 +04:00
|
|
|
rv = mRegistry->AddSubtreeRaw(mCLSIDKey, cidString, &cidKey);
|
1999-03-10 12:53:25 +03:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
char *contractID = nsnull;
|
2000-09-14 03:57:52 +04:00
|
|
|
rv = mRegistry->GetStringUTF8(cidKey, contractIDValueName, &contractID);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_SUCCEEDED(rv))
|
1999-03-10 12:53:25 +03:00
|
|
|
{
|
2000-09-14 03:57:52 +04:00
|
|
|
mRegistry->RemoveSubtreeRaw(mClassesKey, contractID);
|
|
|
|
PR_FREEIF(contractID);
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
|
|
|
|
1999-06-14 06:07:03 +04:00
|
|
|
mRegistry->RemoveSubtree(mCLSIDKey, cidString);
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey libKey;
|
2000-05-12 05:24:36 +04:00
|
|
|
rv = mRegistry->GetSubtreeRaw(mXPCOMKey, eLibrary, &libKey);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_FAILED(rv)) return rv;
|
1999-03-10 12:53:25 +03:00
|
|
|
|
|
|
|
// We need to reduce the ComponentCount by 1.
|
|
|
|
// If the ComponentCount hits 0, delete the entire key.
|
1999-09-29 06:54:18 +04:00
|
|
|
PRInt32 nComponents = 0;
|
1999-04-05 04:07:18 +04:00
|
|
|
rv = mRegistry->GetInt(libKey, componentCountValueName, &nComponents);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_FAILED(rv)) return rv;
|
|
|
|
nComponents--;
|
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
if (nComponents <= 0)
|
|
|
|
{
|
2000-05-12 05:24:36 +04:00
|
|
|
rv = mRegistry->RemoveSubtreeRaw(mXPCOMKey, eLibrary);
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-04-05 04:07:18 +04:00
|
|
|
rv = mRegistry->SetInt(libKey, componentCountValueName, nComponents);
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2000-05-12 05:24:36 +04:00
|
|
|
if (eLibrary != aLibrary)
|
2000-06-03 13:46:12 +04:00
|
|
|
nsMemory::Free(eLibrary);
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
1999-09-01 01:40:21 +04:00
|
|
|
nsComponentManagerImpl::PlatformFind(const nsCID &aCID, nsFactoryEntry* *result)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2002-04-16 02:33:03 +04:00
|
|
|
PR_ASSERT(mRegistry!=nsnull);
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
nsresult rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
char *cidString = aCID.ToString();
|
1999-09-01 01:40:21 +04:00
|
|
|
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey cidKey;
|
1999-05-06 08:19:06 +04:00
|
|
|
rv = mRegistry->GetSubtreeRaw(mCLSIDKey, cidString, &cidKey);
|
1999-03-10 12:53:25 +03:00
|
|
|
delete [] cidString;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-09-01 01:40:21 +04:00
|
|
|
|
1999-11-10 03:28:34 +03:00
|
|
|
nsXPIDLCString library;
|
2000-05-12 05:24:36 +04:00
|
|
|
PRUint32 tmp;
|
|
|
|
rv = mRegistry->GetBytesUTF8(cidKey, inprocServerValueName,
|
|
|
|
&tmp, (PRUint8**)getter_Copies(library).operator char**());
|
1999-03-31 11:04:12 +04:00
|
|
|
if (NS_FAILED(rv))
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
1999-03-10 12:53:25 +03:00
|
|
|
// Registry inconsistent. No File name for CLSID.
|
1999-03-31 11:04:12 +04:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
1999-03-31 11:04:12 +04:00
|
|
|
|
2001-06-17 09:23:38 +04:00
|
|
|
nsXPIDLCString componentTypeStr;
|
2000-02-15 04:32:12 +03:00
|
|
|
rv = mRegistry->GetStringUTF8(cidKey, componentTypeValueName,
|
2001-06-17 09:23:38 +04:00
|
|
|
getter_Copies(componentTypeStr));
|
|
|
|
const char* componentType = componentTypeStr.get();
|
2001-09-07 01:13:11 +04:00
|
|
|
int type = NS_COMPONENT_TYPE_FACTORY_ONLY;
|
1999-03-31 11:04:12 +04:00
|
|
|
|
2001-08-31 02:59:12 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
2001-08-30 18:10:41 +04:00
|
|
|
if (rv == NS_ERROR_REG_NOT_FOUND) {
|
|
|
|
/* missing componentType, we assume application/x-moz-native */
|
|
|
|
type = NS_COMPONENT_TYPE_NATIVE;
|
|
|
|
}
|
2001-08-31 02:59:12 +04:00
|
|
|
else
|
|
|
|
return rv; // XXX translate error code?
|
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
if (type < 0) {
|
|
|
|
// Find the right loader type index
|
|
|
|
type = GetLoaderType(componentType);
|
|
|
|
}
|
1999-09-01 01:40:21 +04:00
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
// Arena allocate the nsFactoryEntry
|
|
|
|
void *mem;
|
|
|
|
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
|
|
|
|
if (!mem)
|
1999-09-01 01:40:21 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-05-03 01:25:08 +04:00
|
|
|
nsFactoryEntry *res = new (mem) nsFactoryEntry(aCID, library, type);
|
1999-03-10 12:53:25 +03:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
*result = res;
|
1999-03-10 12:53:25 +03:00
|
|
|
return NS_OK;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2000-09-14 03:57:52 +04:00
|
|
|
nsComponentManagerImpl::PlatformContractIDToCLSID(const char *aContractID, nsCID *aClass)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2002-04-16 02:33:03 +04:00
|
|
|
PR_ASSERT(aClass != nsnull);
|
1999-03-31 11:04:12 +04:00
|
|
|
PR_ASSERT(mRegistry);
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
nsresult rv;
|
2000-05-12 05:24:36 +04:00
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
nsRegistryKey contractIDKey;
|
|
|
|
rv = mRegistry->GetSubtreeRaw(mClassesKey, aContractID, &contractIDKey);
|
1999-11-14 18:41:40 +03:00
|
|
|
if (NS_FAILED(rv)) return NS_ERROR_FACTORY_NOT_REGISTERED;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
char *cidString;
|
2000-09-14 03:57:52 +04:00
|
|
|
rv = mRegistry->GetStringUTF8(contractIDKey, classIDValueName, &cidString);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_FAILED(rv)) return rv;
|
1999-03-10 12:53:25 +03:00
|
|
|
if (!(aClass->Parse(cidString)))
|
|
|
|
{
|
1999-06-22 18:02:58 +04:00
|
|
|
rv = NS_ERROR_FAILURE;
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
1999-03-31 11:04:12 +04:00
|
|
|
|
1999-06-22 18:02:58 +04:00
|
|
|
PR_FREEIF(cidString);
|
1999-11-14 18:41:40 +03:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2000-09-14 03:57:52 +04:00
|
|
|
nsComponentManagerImpl::PlatformCLSIDToContractID(const nsCID *aClass,
|
2002-01-30 00:22:13 +03:00
|
|
|
char* *aClassName,
|
|
|
|
char* *aContractID)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
PR_ASSERT(aClass);
|
|
|
|
PR_ASSERT(mRegistry);
|
1999-03-10 12:53:25 +03:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
nsresult rv;
|
1999-03-10 12:53:25 +03:00
|
|
|
|
1999-03-31 11:04:12 +04:00
|
|
|
char* cidStr = aClass->ToString();
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey cidKey;
|
1999-07-31 09:55:04 +04:00
|
|
|
rv = mRegistry->GetSubtreeRaw(mCLSIDKey, cidStr, &cidKey);
|
1999-03-31 11:04:12 +04:00
|
|
|
if(NS_FAILED(rv)) return rv;
|
|
|
|
PR_FREEIF(cidStr);
|
1999-03-10 12:53:25 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
if (aClassName) {
|
|
|
|
char* classnameString;
|
|
|
|
rv = mRegistry->GetStringUTF8(cidKey, classNameValueName, &classnameString);
|
|
|
|
if(NS_FAILED(rv)) return rv;
|
|
|
|
*aClassName = classnameString;
|
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
if (aContractID) {
|
|
|
|
char* contractidString;
|
|
|
|
rv = mRegistry->GetStringUTF8(cidKey,contractIDValueName,&contractidString);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
*aContractID = contractidString;
|
|
|
|
}
|
1999-03-31 11:04:12 +04:00
|
|
|
return NS_OK;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
|
1999-07-02 07:35:09 +04:00
|
|
|
nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
|
|
|
|
{
|
1999-09-01 01:40:21 +04:00
|
|
|
nsresult rv;
|
2001-11-16 05:38:23 +03:00
|
|
|
char buf[MAXREGPATHLEN];
|
|
|
|
PRUint32 bufLength = sizeof(buf);
|
1999-07-02 07:35:09 +04:00
|
|
|
|
1999-09-08 08:22:37 +04:00
|
|
|
if (mPrePopulationDone)
|
|
|
|
return NS_OK;
|
2000-09-08 05:51:45 +04:00
|
|
|
|
2001-11-30 10:50:03 +03:00
|
|
|
(void)((nsRegistry *)mRegistry)->SetBufferSize( BIG_REGISTRY_BUFLEN );
|
2001-11-16 05:38:23 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIRegistryGetter> regGetter = do_QueryInterface(mRegistry);
|
|
|
|
if (!regGetter.get())
|
|
|
|
return NS_ERROR_FAILURE;
|
2000-09-08 05:51:45 +04:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
// Read in all CID entries and populate the mFactories
|
1999-07-02 07:35:09 +04:00
|
|
|
nsCOMPtr<nsIEnumerator> cidEnum;
|
|
|
|
rv = mRegistry->EnumerateSubtrees( mCLSIDKey, getter_AddRefs(cidEnum));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2001-02-01 01:05:28 +03:00
|
|
|
nsCOMPtr<nsIRegistryEnumerator> regEnum(do_QueryInterface(cidEnum, &rv));
|
2000-04-25 05:11:08 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-07-02 07:35:09 +04:00
|
|
|
|
2000-04-25 05:11:08 +04:00
|
|
|
for (rv = regEnum->First();
|
|
|
|
NS_SUCCEEDED(rv) && (regEnum->IsDone() != NS_OK);
|
|
|
|
rv = regEnum->Next())
|
|
|
|
{
|
|
|
|
const char *cidString;
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey cidKey;
|
2000-04-25 05:11:08 +04:00
|
|
|
/*
|
|
|
|
* CurrentItemInPlaceUTF8 will give us back a _shared_ pointer in
|
|
|
|
* cidString. This is bad XPCOM practice. It is evil, and requires
|
|
|
|
* great care with the relative lifetimes of cidString and regEnum.
|
|
|
|
*
|
|
|
|
* It is also faster, and less painful in the allocation department.
|
|
|
|
*/
|
|
|
|
rv = regEnum->CurrentItemInPlaceUTF8(&cidKey, &cidString);
|
|
|
|
if (NS_FAILED(rv)) continue;
|
1999-07-02 07:35:09 +04:00
|
|
|
|
2001-11-16 05:38:23 +03:00
|
|
|
// Figure out the component type
|
|
|
|
// Use the non allocating registry getter. Our buffer is big enough
|
|
|
|
// We wont get NS_ERROR_REG_BUFFER_TOO_SMALL
|
|
|
|
bufLength = sizeof(buf);
|
|
|
|
rv = regGetter->GetStringUTF8IntoBuffer(cidKey, componentTypeValueName, buf, &bufLength);
|
|
|
|
if (NS_FAILED(rv))
|
1999-09-08 03:18:47 +04:00
|
|
|
continue;
|
|
|
|
|
2001-11-16 05:38:23 +03:00
|
|
|
int loadertype = GetLoaderType(buf);
|
2001-08-31 02:59:12 +04:00
|
|
|
if (loadertype < 0) {
|
2001-11-16 05:38:23 +03:00
|
|
|
loadertype = AddLoaderType(buf);
|
2001-08-31 02:59:12 +04:00
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
|
2001-11-16 05:38:23 +03:00
|
|
|
// Create the CID entry
|
|
|
|
bufLength = sizeof(buf);
|
|
|
|
rv = regGetter->GetBytesUTF8IntoBuffer(cidKey, inprocServerValueName,
|
|
|
|
(PRUint8 *) buf, &bufLength);
|
|
|
|
if (NS_FAILED(rv))
|
1999-09-01 01:40:21 +04:00
|
|
|
continue;
|
2001-11-16 05:38:23 +03:00
|
|
|
nsCID aClass;
|
|
|
|
if (!(aClass.Parse(cidString)))
|
|
|
|
continue;
|
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
// Arena allocate the nsFactoryEntry
|
|
|
|
void *mem;
|
|
|
|
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
|
|
|
|
if (!mem)
|
2001-11-16 05:38:23 +03:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-05-03 01:25:08 +04:00
|
|
|
nsFactoryEntry *entry = new (mem) nsFactoryEntry(aClass, buf, loadertype);
|
1999-07-02 07:35:09 +04:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
2001-11-30 10:50:03 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_ADD));
|
2001-11-30 10:50:03 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
if (!factoryTableEntry)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
factoryTableEntry->mFactoryEntry = entry;
|
1999-07-02 07:35:09 +04:00
|
|
|
}
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
// Finally read in CONTRACTID -> CID mappings
|
|
|
|
nsCOMPtr<nsIEnumerator> contractidEnum;
|
|
|
|
rv = mRegistry->EnumerateSubtrees( mClassesKey, getter_AddRefs(contractidEnum));
|
1999-07-31 09:55:04 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
regEnum = do_QueryInterface(contractidEnum, &rv);
|
2000-04-25 05:11:08 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-07-31 09:55:04 +04:00
|
|
|
|
2000-04-25 05:11:08 +04:00
|
|
|
for (rv = regEnum->First();
|
|
|
|
NS_SUCCEEDED(rv) && (regEnum->IsDone() != NS_OK);
|
|
|
|
rv = regEnum->Next())
|
|
|
|
{
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *contractidString;
|
|
|
|
nsRegistryKey contractidKey;
|
2000-04-25 05:11:08 +04:00
|
|
|
/*
|
|
|
|
* CurrentItemInPlaceUTF8 will give us back a _shared_ pointer in
|
2000-09-14 03:57:52 +04:00
|
|
|
* contractidString. This is bad XPCOM practice. It is evil, and requires
|
|
|
|
* great care with the relative lifetimes of contractidString and regEnum.
|
2000-04-25 05:11:08 +04:00
|
|
|
*
|
|
|
|
* It is also faster, and less painful in the allocation department.
|
|
|
|
*/
|
2000-09-14 03:57:52 +04:00
|
|
|
rv = regEnum->CurrentItemInPlaceUTF8(&contractidKey, &contractidString);
|
2001-11-16 05:38:23 +03:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
continue;
|
1999-11-10 03:28:34 +03:00
|
|
|
|
2001-11-16 05:38:23 +03:00
|
|
|
// Use the non allocating registry getter. Our buffer is big enough
|
|
|
|
// We wont get NS_ERROR_REG_BUFFER_TOO_SMALL
|
|
|
|
bufLength = sizeof(buf);
|
|
|
|
rv = regGetter->GetStringUTF8IntoBuffer(contractidKey, classIDValueName, buf, &bufLength);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
continue;
|
2001-08-22 02:42:35 +04:00
|
|
|
nsCID aClass;
|
2001-11-16 05:38:23 +03:00
|
|
|
if (!aClass.Parse(buf))
|
1999-07-31 09:55:04 +04:00
|
|
|
continue;
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
// put the {contractid, Cid} mapping into our map
|
2001-08-22 02:42:35 +04:00
|
|
|
HashContractID(contractidString, aClass);
|
1999-07-31 09:55:04 +04:00
|
|
|
}
|
1999-07-02 07:35:09 +04:00
|
|
|
|
2001-11-30 10:50:03 +03:00
|
|
|
// Create the category manage to ensure prepopulation of categories
|
|
|
|
nsCOMPtr<nsICategoryManager> catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
|
|
|
|
|
|
|
|
// reset registry buffer to standard size
|
|
|
|
(void)((nsRegistry *)mRegistry)->SetBufferSize( -1 );
|
|
|
|
|
1999-08-09 09:02:25 +04:00
|
|
|
mPrePopulationDone = PR_TRUE;
|
1999-07-02 07:35:09 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-06-14 06:07:03 +04:00
|
|
|
#endif /* USE_REGISTRY */
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Hash Functions
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
1999-06-22 18:02:58 +04:00
|
|
|
nsresult
|
2001-08-22 02:42:35 +04:00
|
|
|
nsComponentManagerImpl::HashContractID(const char *aContractID, const nsCID &aClass, nsFactoryEntry **pfe)
|
|
|
|
{
|
|
|
|
nsIDKey cidKey(aClass);
|
|
|
|
return HashContractID(aContractID, aClass, cidKey, pfe);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::HashContractID(const char *aContractID, const nsCID &aClass, nsIDKey &cidKey, nsFactoryEntry **pfe)
|
1999-06-22 18:02:58 +04:00
|
|
|
{
|
2000-09-14 03:57:52 +04:00
|
|
|
if(!aContractID)
|
1999-06-22 18:02:58 +04:00
|
|
|
{
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
// Find the factory entry corresponding to the CID.
|
|
|
|
nsFactoryEntry *entry = GetFactoryEntry(aClass, cidKey);
|
|
|
|
if (!entry) {
|
|
|
|
// Non existent. We use the special kNonExistentContractID to mark
|
|
|
|
// that this contractid does not have a mapping.
|
|
|
|
entry = kNonExistentContractID;
|
1999-06-22 18:02:58 +04:00
|
|
|
}
|
2001-08-22 02:42:35 +04:00
|
|
|
|
|
|
|
nsresult rv = HashContractID(aContractID, entry);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// Fill the entry out parameter
|
|
|
|
if (pfe) *pfe = entry;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::HashContractID(const char *aContractID, nsFactoryEntry *fe)
|
|
|
|
{
|
|
|
|
if(!aContractID)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-06-22 18:02:58 +04:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsContractIDTableEntry* contractIDTableEntry =
|
|
|
|
NS_STATIC_CAST(nsContractIDTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mContractIDs, aContractID,
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
if (!contractIDTableEntry)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2002-05-03 01:25:08 +04:00
|
|
|
NS_ASSERTION(!contractIDTableEntry->mContractID || !strcmp(contractIDTableEntry->mContractID, aContractID), "contractid conflict");
|
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
if (!contractIDTableEntry->mContractID)
|
2002-05-03 01:25:08 +04:00
|
|
|
contractIDTableEntry->mContractID = ArenaStrdup(aContractID, &mArena);
|
2001-10-23 06:28:12 +04:00
|
|
|
|
|
|
|
contractIDTableEntry->mFactoryEntry = fe;
|
|
|
|
|
1999-06-22 18:02:58 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
/**
|
|
|
|
* LoadFactory()
|
|
|
|
*
|
|
|
|
* Given a FactoryEntry, this loads the dll if it has to, find the NSGetFactory
|
|
|
|
* symbol, calls the routine to create a new factory and returns it to the
|
|
|
|
* caller.
|
|
|
|
*
|
|
|
|
* No attempt is made to store the factory in any form anywhere.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
|
|
|
|
nsIFactory **aFactory)
|
|
|
|
{
|
1999-09-01 01:40:21 +04:00
|
|
|
|
|
|
|
if (!aFactory)
|
1999-03-10 12:53:25 +03:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
2002-04-16 02:33:03 +04:00
|
|
|
*aFactory = nsnull;
|
1999-03-10 12:53:25 +03:00
|
|
|
|
1999-09-08 03:18:47 +04:00
|
|
|
nsresult rv;
|
|
|
|
rv = aEntry->GetFactory(aFactory, this);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
1999-08-09 09:40:51 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
2000-03-12 01:44:51 +03:00
|
|
|
("nsComponentManager: FAILED to load factory from %s (%s)\n",
|
2001-08-30 18:10:41 +04:00
|
|
|
(const char *)aEntry->location, mLoaderData[aEntry->typeIndex].type));
|
1999-03-10 12:53:25 +03:00
|
|
|
return rv;
|
|
|
|
}
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
return NS_OK;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
1999-07-07 11:47:14 +04:00
|
|
|
nsFactoryEntry *
|
2001-08-22 02:42:35 +04:00
|
|
|
nsComponentManagerImpl::GetFactoryEntry(const char *aContractID, int checkRegistry)
|
1999-07-07 11:47:14 +04:00
|
|
|
{
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry *fe = nsnull;
|
|
|
|
{
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
|
|
|
nsContractIDTableEntry* contractIDTableEntry =
|
|
|
|
NS_STATIC_CAST(nsContractIDTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mContractIDs, aContractID,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
|
|
|
|
fe = contractIDTableEntry->mFactoryEntry;
|
|
|
|
}
|
|
|
|
} //exit monitor
|
1999-07-07 11:47:14 +04:00
|
|
|
|
|
|
|
#ifdef USE_REGISTRY
|
2001-08-22 02:42:35 +04:00
|
|
|
if (!fe)
|
2000-03-12 01:44:51 +03:00
|
|
|
{
|
2001-08-22 02:42:35 +04:00
|
|
|
if (checkRegistry < 0) {
|
|
|
|
// default
|
|
|
|
checkRegistry = !mPrePopulationDone;
|
|
|
|
}
|
|
|
|
|
1999-07-07 11:47:14 +04:00
|
|
|
if (checkRegistry)
|
|
|
|
{
|
2001-08-22 02:42:35 +04:00
|
|
|
nsCID cid;
|
|
|
|
nsresult rv = PlatformContractIDToCLSID(aContractID, &cid);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
HashContractID(aContractID, cid, &fe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* USE_REGISTRY */
|
|
|
|
|
|
|
|
// If no mapping found, add a special non-existent mapping
|
|
|
|
// so the next time around, we dont have to waste time doing the
|
|
|
|
// same mapping over and over again
|
|
|
|
if (!fe) {
|
|
|
|
fe = kNonExistentContractID;
|
|
|
|
HashContractID(aContractID, fe);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (fe);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsFactoryEntry *
|
|
|
|
nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass, int checkRegistry)
|
|
|
|
{
|
|
|
|
nsIDKey cidKey(aClass);
|
|
|
|
return GetFactoryEntry(aClass, cidKey, checkRegistry);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsFactoryEntry *
|
|
|
|
nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass, nsIDKey &cidKey, int checkRegistry)
|
|
|
|
{
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry *entry = nsnull;
|
|
|
|
{
|
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
|
|
|
|
entry = factoryTableEntry->mFactoryEntry;
|
|
|
|
}
|
|
|
|
} // exit monitor
|
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
|
|
|
|
#ifdef USE_REGISTRY
|
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
if (checkRegistry < 0) {
|
|
|
|
// default
|
|
|
|
checkRegistry = !mPrePopulationDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (checkRegistry) {
|
1999-09-01 01:40:21 +04:00
|
|
|
nsresult rv = PlatformFind(aClass, &entry);
|
|
|
|
|
|
|
|
// If we got one, cache it in our hashtable
|
|
|
|
if (NS_SUCCEEDED(rv))
|
1999-07-07 11:47:14 +04:00
|
|
|
{
|
2001-10-23 06:28:12 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &cidKey,
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
|
|
|
|
if (!factoryTableEntry) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
factoryTableEntry->mFactoryEntry = entry;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-03-12 01:44:51 +03:00
|
|
|
#endif /* USE_REGISTRY */
|
1999-07-07 11:47:14 +04:00
|
|
|
|
|
|
|
return (entry);
|
|
|
|
}
|
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
/**
|
|
|
|
* FindFactory()
|
|
|
|
*
|
|
|
|
* Given a classID, this finds the factory for this CID by first searching the
|
|
|
|
* local CID<->factory mapping. Next it searches for a Dll that implements
|
|
|
|
* this classID and calls LoadFactory() to create the factory.
|
|
|
|
*
|
|
|
|
* Again, no attempt is made at storing the factory.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::FindFactory(const nsCID &aClass,
|
|
|
|
nsIFactory **aFactory)
|
|
|
|
{
|
2002-04-16 02:33:03 +04:00
|
|
|
PR_ASSERT(aFactory != nsnull);
|
1999-06-19 03:27:09 +04:00
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
nsFactoryEntry *entry = GetFactoryEntry(aClass);
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
if (!entry)
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
|
1999-09-08 03:18:47 +04:00
|
|
|
return entry->GetFactory(aFactory, this);
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::FindFactory(const char *contractID,
|
|
|
|
nsIFactory **aFactory)
|
|
|
|
{
|
2002-04-16 02:33:03 +04:00
|
|
|
PR_ASSERT(aFactory != nsnull);
|
2001-08-22 02:42:35 +04:00
|
|
|
|
|
|
|
nsFactoryEntry *entry = GetFactoryEntry(contractID);
|
|
|
|
|
|
|
|
if (!entry || entry == kNonExistentContractID)
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
|
|
|
|
return entry->GetFactory(aFactory, this);
|
|
|
|
}
|
|
|
|
|
1999-08-19 18:54:12 +04:00
|
|
|
/**
|
|
|
|
* GetClassObject()
|
|
|
|
*
|
|
|
|
* Given a classID, this finds the singleton ClassObject that implements the CID.
|
|
|
|
* Returns an interface of type aIID off the singleton classobject.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
|
|
|
|
void **aResult)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFactory> factory;
|
|
|
|
|
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
|
|
|
char *buf = aClass.ToString();
|
|
|
|
PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
|
|
|
|
delete [] buf;
|
|
|
|
}
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
PR_ASSERT(aResult != nsnull);
|
1999-08-19 18:54:12 +04:00
|
|
|
|
|
|
|
rv = FindFactory(aClass, getter_AddRefs(factory));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = factory->QueryInterface(aIID, aResult);
|
|
|
|
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
|
|
|
|
("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-08-19 18:54:12 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2001-12-19 03:12:41 +03:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
|
|
|
|
const nsIID &aIID,
|
|
|
|
void **aResult)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFactory> factory;
|
|
|
|
|
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
|
|
|
PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
|
|
|
|
}
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
PR_ASSERT(aResult != nsnull);
|
2001-12-19 03:12:41 +03:00
|
|
|
|
|
|
|
rv = FindFactory(contractID, getter_AddRefs(factory));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = factory->QueryInterface(aIID, aResult);
|
|
|
|
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
|
|
|
|
("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
/**
|
2000-09-14 03:57:52 +04:00
|
|
|
* ContractIDToClassID()
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
2000-09-14 03:57:52 +04:00
|
|
|
* Mapping function from a ContractID to a classID. Directly talks to the registry.
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
nsresult
|
2002-01-30 00:22:13 +03:00
|
|
|
nsComponentManagerImpl::ContractIDToClassID(const char *aContractID, nsCID *aClass)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2002-04-16 02:33:03 +04:00
|
|
|
NS_PRECONDITION(aContractID != nsnull, "null ptr");
|
2000-09-14 03:57:52 +04:00
|
|
|
if (! aContractID)
|
1999-03-10 12:53:25 +03:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
NS_PRECONDITION(aClass != nsnull, "null ptr");
|
1999-03-10 12:53:25 +03:00
|
|
|
if (! aClass)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
nsFactoryEntry *fe = GetFactoryEntry(aContractID);
|
|
|
|
if (fe && fe != kNonExistentContractID) {
|
|
|
|
*aClass = fe->cid;
|
|
|
|
res = NS_OK;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS)) {
|
1999-09-02 11:00:29 +04:00
|
|
|
char *buf = 0;
|
1999-03-10 12:53:25 +03:00
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
buf = aClass->ToString();
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
2000-09-14 03:57:52 +04:00
|
|
|
("nsComponentManager: ContractIDToClassID(%s)->%s", aContractID,
|
1999-03-10 12:53:25 +03:00
|
|
|
NS_SUCCEEDED(res) ? buf : "[FAILED]"));
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
delete [] buf;
|
|
|
|
}
|
1999-06-14 06:07:03 +04:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
return res;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2000-09-14 03:57:52 +04:00
|
|
|
* CLSIDToContractID()
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
2000-09-14 03:57:52 +04:00
|
|
|
* Translates a classID to a {ContractID, Class Name}. Does direct registry
|
1999-03-09 12:44:27 +03:00
|
|
|
* access to do the translation.
|
|
|
|
*
|
2000-05-05 10:37:39 +04:00
|
|
|
* NOTE: Since this isn't heavily used, we arent caching this.
|
1999-03-09 12:44:27 +03:00
|
|
|
*/
|
|
|
|
nsresult
|
2000-09-14 03:57:52 +04:00
|
|
|
nsComponentManagerImpl::CLSIDToContractID(const nsCID &aClass,
|
2002-01-30 00:22:13 +03:00
|
|
|
char* *aClassName,
|
|
|
|
char* *aContractID)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
1999-03-10 12:53:25 +03:00
|
|
|
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
|
|
|
#ifdef USE_REGISTRY
|
2000-09-14 03:57:52 +04:00
|
|
|
res = PlatformCLSIDToContractID(&aClass, aClassName, aContractID);
|
1999-03-09 12:44:27 +03:00
|
|
|
#endif /* USE_REGISTRY */
|
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
1999-09-05 10:27:42 +04:00
|
|
|
char *buf = aClass.ToString();
|
1999-03-10 12:53:25 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
|
2000-09-14 03:57:52 +04:00
|
|
|
("nsComponentManager: CLSIDToContractID(%s)->%s", buf,
|
|
|
|
NS_SUCCEEDED(res) ? *aContractID : "[FAILED]"));
|
1999-03-10 12:53:25 +03:00
|
|
|
delete [] buf;
|
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
return res;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* CreateInstance()
|
|
|
|
*
|
|
|
|
* Create an instance of an object that implements an interface and belongs
|
|
|
|
* to the implementation aClass using the factory. The factory is immediately
|
|
|
|
* released and not held onto for any longer.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
|
|
|
|
nsISupports *aDelegate,
|
|
|
|
const nsIID &aIID,
|
|
|
|
void **aResult)
|
|
|
|
{
|
2000-05-05 03:11:30 +04:00
|
|
|
// test this first, since there's no point in creating a component during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
2001-10-16 07:35:52 +04:00
|
|
|
if (gXPCOMShuttingDown) {
|
2000-05-05 03:11:30 +04:00
|
|
|
// When processing shutdown, dont process new GetService() requests
|
2002-01-10 05:10:37 +03:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
|
|
|
nsXPIDLCString cid, iid;
|
|
|
|
cid.Adopt(aClass.ToString());
|
|
|
|
iid.Adopt(aIID.ToString());
|
2002-05-12 01:15:06 +04:00
|
|
|
fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
|
2002-01-10 05:10:37 +03:00
|
|
|
" CID: %s\n IID: %s\n", cid.get(), iid.get());
|
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2000-05-05 03:11:30 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (aResult == nsnull)
|
1999-03-10 12:53:25 +03:00
|
|
|
{
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2002-04-16 02:33:03 +04:00
|
|
|
*aResult = nsnull;
|
2000-05-12 05:24:36 +04:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
nsIFactory *factory = nsnull;
|
1999-03-10 12:53:25 +03:00
|
|
|
nsresult res = FindFactory(aClass, &factory);
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
{
|
|
|
|
res = factory->CreateInstance(aDelegate, aIID, aResult);
|
|
|
|
NS_RELEASE(factory);
|
2000-03-12 01:44:51 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Translate error values
|
|
|
|
res = NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
|
|
|
char *buf = aClass.ToString();
|
1999-03-10 12:53:25 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
2000-03-12 01:44:51 +03:00
|
|
|
("nsComponentManager: CreateInstance(%s) %s", buf,
|
1999-04-06 09:06:47 +04:00
|
|
|
NS_SUCCEEDED(res) ? "succeeded" : "FAILED"));
|
2000-03-12 01:44:51 +03:00
|
|
|
delete [] buf;
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2000-03-12 01:44:51 +03:00
|
|
|
return res;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2000-09-14 03:57:52 +04:00
|
|
|
* CreateInstanceByContractID()
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
1999-09-07 09:06:37 +04:00
|
|
|
* A variant of CreateInstance() that creates an instance of the object that
|
2000-09-14 03:57:52 +04:00
|
|
|
* implements the interface aIID and whose implementation has a contractID aContractID.
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
|
|
|
* This is only a convenience routine that turns around can calls the
|
|
|
|
* CreateInstance() with classid and iid.
|
|
|
|
*/
|
|
|
|
nsresult
|
2000-09-14 03:57:52 +04:00
|
|
|
nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
|
1999-09-05 10:27:42 +04:00
|
|
|
nsISupports *aDelegate,
|
|
|
|
const nsIID &aIID,
|
|
|
|
void **aResult)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2001-08-22 02:42:35 +04:00
|
|
|
// test this first, since there's no point in creating a component during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
2001-10-16 07:35:52 +04:00
|
|
|
if (gXPCOMShuttingDown) {
|
2001-08-22 02:42:35 +04:00
|
|
|
// When processing shutdown, dont process new GetService() requests
|
2002-01-10 05:10:37 +03:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
|
|
|
nsXPIDLCString iid;
|
|
|
|
iid.Adopt(aIID.ToString());
|
2002-05-12 01:15:06 +04:00
|
|
|
fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
|
2002-01-10 05:10:37 +03:00
|
|
|
" ContractID: %s\n IID: %s\n", aContractID, iid.get());
|
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2001-08-22 02:42:35 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (aResult == nsnull)
|
2001-08-22 02:42:35 +04:00
|
|
|
{
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2002-04-16 02:33:03 +04:00
|
|
|
*aResult = nsnull;
|
2001-08-22 02:42:35 +04:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
nsIFactory *factory = nsnull;
|
2001-08-22 02:42:35 +04:00
|
|
|
nsresult res = FindFactory(aContractID, &factory);
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
{
|
|
|
|
res = factory->CreateInstance(aDelegate, aIID, aResult);
|
|
|
|
NS_RELEASE(factory);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Translate error values
|
|
|
|
res = NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
|
|
|
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
|
|
|
("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
|
|
|
|
NS_SUCCEEDED(res) ? "succeeded" : "FAILED"));
|
|
|
|
|
|
|
|
return res;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
// Service Manager Impl
|
2002-01-30 00:22:13 +03:00
|
|
|
static
|
2001-10-23 06:28:12 +04:00
|
|
|
PLDHashOperator PR_CALLBACK
|
|
|
|
FreeServiceFactoryEntryEnumerate(PLDHashTable *aTable,
|
|
|
|
PLDHashEntryHdr *aHdr,
|
|
|
|
PRUint32 aNumber,
|
|
|
|
void *aData)
|
2001-09-07 01:13:11 +04:00
|
|
|
{
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
|
|
|
|
|
|
|
|
if (!entry->mFactoryEntry || entry->mFactoryEntry == kNonExistentContractID)
|
|
|
|
return PL_DHASH_NEXT;
|
2001-09-07 01:13:11 +04:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
|
2001-11-16 16:53:04 +03:00
|
|
|
factoryEntry->mServiceObject = nsnull;
|
2001-10-23 06:28:12 +04:00
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
static
|
2001-10-23 06:28:12 +04:00
|
|
|
PLDHashOperator PR_CALLBACK
|
|
|
|
FreeServiceContractIDEntryEnumerate(PLDHashTable *aTable,
|
|
|
|
PLDHashEntryHdr *aHdr,
|
|
|
|
PRUint32 aNumber,
|
|
|
|
void *aData)
|
|
|
|
{
|
|
|
|
nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
|
|
|
|
|
|
|
|
if (!entry->mFactoryEntry || entry->mFactoryEntry == kNonExistentContractID)
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
|
|
|
|
nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
|
2001-11-16 16:53:04 +03:00
|
|
|
factoryEntry->mServiceObject = nsnull;
|
2001-10-23 06:28:12 +04:00
|
|
|
return PL_DHASH_NEXT;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::FreeServices()
|
|
|
|
{
|
2002-01-13 02:35:57 +03:00
|
|
|
NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services");
|
|
|
|
|
|
|
|
if (!gXPCOMShuttingDown)
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
if (mContractIDs.ops) {
|
|
|
|
PL_DHashTableEnumerate(&mContractIDs, FreeServiceContractIDEntryEnumerate, nsnull);
|
|
|
|
}
|
2001-09-07 01:13:11 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
|
|
|
|
if (mFactories.ops) {
|
|
|
|
PL_DHashTableEnumerate(&mFactories, FreeServiceFactoryEntryEnumerate, nsnull);
|
|
|
|
}
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2001-10-16 07:35:52 +04:00
|
|
|
nsComponentManagerImpl::GetService(const nsCID& aClass,
|
|
|
|
const nsIID& aIID,
|
|
|
|
void* *result)
|
2001-09-07 01:13:11 +04:00
|
|
|
{
|
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
2001-10-16 07:35:52 +04:00
|
|
|
if (gXPCOMShuttingDown) {
|
2001-09-07 01:13:11 +04:00
|
|
|
// When processing shutdown, dont process new GetService() requests
|
2002-01-10 05:10:37 +03:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
|
|
|
nsXPIDLCString cid, iid;
|
|
|
|
cid.Adopt(aClass.ToString());
|
|
|
|
iid.Adopt(aIID.ToString());
|
2002-05-12 01:15:06 +04:00
|
|
|
fprintf(stderr, "Getting service on shutdown. Denied.\n"
|
2002-01-10 05:10:37 +03:00
|
|
|
" CID: %s\n IID: %s\n", cid.get(), iid.get());
|
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
nsIDKey key(aClass);
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry* entry = nsnull;
|
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
|
|
|
|
entry = factoryTableEntry->mFactoryEntry;
|
|
|
|
}
|
2001-11-16 16:53:04 +03:00
|
|
|
|
|
|
|
if (entry && entry->mServiceObject) {
|
|
|
|
return entry->mServiceObject->QueryInterface(aIID, result);
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
nsCOMPtr<nsISupports> service;
|
2001-09-07 01:13:11 +04:00
|
|
|
// We need to not be holding the service manager's monitor while calling
|
|
|
|
// CreateInstance, because it invokes user code which could try to re-enter
|
|
|
|
// the service manager:
|
|
|
|
mon.Exit();
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
rv = CreateInstance(aClass, nsnull, aIID, getter_AddRefs(service));
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
mon.Enter();
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (!entry) { // second hash lookup for GetService
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_LOOKUP));
|
2001-11-16 16:53:04 +03:00
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
|
|
|
|
entry = factoryTableEntry->mFactoryEntry;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
2001-11-16 16:53:04 +03:00
|
|
|
NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
|
|
|
|
if (!entry) return NS_ERROR_FAILURE;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
entry->mServiceObject = service;
|
|
|
|
*result = service.get();
|
|
|
|
NS_ADDREF(NS_STATIC_CAST(nsISupports*, (*result)));
|
2001-09-07 01:13:11 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::RegisterService(const nsCID& aClass, nsISupports* aService)
|
|
|
|
{
|
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
|
|
|
// check to see if we have a factory entry for the service
|
|
|
|
nsIDKey key(aClass);
|
|
|
|
nsFactoryEntry *entry = GetFactoryEntry(aClass, key, 0);
|
|
|
|
|
|
|
|
if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
|
2002-05-03 01:25:08 +04:00
|
|
|
void *mem;
|
|
|
|
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
|
|
|
|
if (!mem)
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-05-03 01:25:08 +04:00
|
|
|
entry = new (mem) nsFactoryEntry(aClass, nsnull);
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
entry->typeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
if (!factoryTableEntry)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
factoryTableEntry->mFactoryEntry = entry;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
else {
|
2001-11-16 16:53:04 +03:00
|
|
|
if (entry->mServiceObject)
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
entry->mServiceObject = aService;
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::UnregisterService(const nsCID& aClass)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
|
|
|
nsFactoryEntry* entry = nsnull;
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_LOOKUP));
|
2001-09-07 01:13:11 +04:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
|
|
|
|
entry = factoryTableEntry->mFactoryEntry;
|
|
|
|
}
|
2001-09-07 01:13:11 +04:00
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
if (!entry || !entry->mServiceObject)
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_SERVICE_NOT_FOUND;
|
2001-11-16 16:53:04 +03:00
|
|
|
|
|
|
|
entry->mServiceObject = nsnull;
|
2001-09-07 01:13:11 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-10-17 03:39:20 +04:00
|
|
|
nsComponentManagerImpl::RegisterService(const char* aContractID, nsISupports* aService)
|
2001-09-07 01:13:11 +04:00
|
|
|
{
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
|
|
|
// check to see if we have a factory entry for the service
|
|
|
|
nsFactoryEntry *entry = GetFactoryEntry(aContractID, 0);
|
|
|
|
|
|
|
|
if (entry == kNonExistentContractID)
|
|
|
|
entry = nsnull;
|
|
|
|
|
|
|
|
if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
|
2002-05-03 01:25:08 +04:00
|
|
|
void *mem;
|
|
|
|
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
|
|
|
|
if (!mem)
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-05-03 01:25:08 +04:00
|
|
|
entry = new (mem) nsFactoryEntry(kEmptyCID, nsnull);
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
entry->typeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
|
|
|
nsContractIDTableEntry* contractIDTableEntry =
|
|
|
|
NS_STATIC_CAST(nsContractIDTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mContractIDs, aContractID,
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
if (!contractIDTableEntry) {
|
|
|
|
delete entry;
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!contractIDTableEntry->mContractID)
|
2002-05-03 01:25:08 +04:00
|
|
|
contractIDTableEntry->mContractID = ArenaStrdup(aContractID, &mArena);
|
2001-10-23 06:28:12 +04:00
|
|
|
|
|
|
|
contractIDTableEntry->mFactoryEntry = entry;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
else {
|
2001-11-16 16:53:04 +03:00
|
|
|
if (entry->mServiceObject)
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
entry->mServiceObject = aService;
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-10-16 07:35:52 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass,
|
|
|
|
const nsIID& aIID,
|
|
|
|
PRBool *result)
|
|
|
|
{
|
|
|
|
// Now we want to get the service if we already got it. If not, we dont want
|
|
|
|
// to create an instance of it. mmh!
|
|
|
|
|
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, dont process new GetService() requests
|
2002-01-10 05:10:37 +03:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
|
|
|
nsXPIDLCString cid, iid;
|
|
|
|
cid.Adopt(aClass.ToString());
|
|
|
|
iid.Adopt(aIID.ToString());
|
2002-05-12 01:15:06 +04:00
|
|
|
fprintf(stderr, "Checking for service on shutdown. Denied.\n"
|
2002-01-10 05:10:37 +03:00
|
|
|
" CID: %s\n IID: %s\n", cid.get(), iid.get());
|
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2001-10-16 07:35:52 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = NS_ERROR_SERVICE_NOT_FOUND;
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry* entry = nsnull;
|
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
|
|
|
|
entry = factoryTableEntry->mFactoryEntry;
|
|
|
|
}
|
2001-10-16 07:35:52 +04:00
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
if (entry && entry->mServiceObject) {
|
|
|
|
nsCOMPtr<nsISupports> service;
|
|
|
|
rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
|
2001-10-16 07:35:52 +04:00
|
|
|
*result =(service!=nsnull);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID,
|
|
|
|
const nsIID& aIID,
|
|
|
|
PRBool *result)
|
|
|
|
{
|
|
|
|
// Now we want to get the service if we already got it. If not, we dont want
|
|
|
|
// to create an instance of it. mmh!
|
|
|
|
|
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, dont process new GetService() requests
|
2002-01-10 05:10:37 +03:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
|
|
|
nsXPIDLCString iid;
|
|
|
|
iid.Adopt(aIID.ToString());
|
2002-05-12 01:15:06 +04:00
|
|
|
fprintf(stderr, "Checking for service on shutdown. Denied.\n"
|
2002-01-10 05:10:37 +03:00
|
|
|
" ContractID: %s\n IID: %s\n", aContractID, iid.get());
|
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2001-10-16 07:35:52 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = NS_ERROR_SERVICE_NOT_FOUND;
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry *entry = nsnull;
|
|
|
|
{
|
|
|
|
nsAutoMonitor mon(mMon);
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsContractIDTableEntry* contractIDTableEntry =
|
|
|
|
NS_STATIC_CAST(nsContractIDTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mContractIDs, aContractID,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
|
|
|
|
entry = contractIDTableEntry->mFactoryEntry;
|
|
|
|
}
|
|
|
|
} // exit monitor
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
if (entry && entry != kNonExistentContractID && entry->mServiceObject) {
|
|
|
|
nsCOMPtr<nsISupports> service;
|
|
|
|
rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
|
2001-10-16 07:35:52 +04:00
|
|
|
*result =(service!=nsnull);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
NS_IMETHODIMP
|
2001-10-17 03:39:20 +04:00
|
|
|
nsComponentManagerImpl::UnregisterService(const char* aContractID)
|
2001-09-07 01:13:11 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry *entry = nsnull;
|
|
|
|
nsContractIDTableEntry* contractIDTableEntry =
|
|
|
|
NS_STATIC_CAST(nsContractIDTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mContractIDs, aContractID,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
|
|
|
|
entry = contractIDTableEntry->mFactoryEntry;
|
|
|
|
}
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
if (entry == nsnull || entry == kNonExistentContractID || entry->mServiceObject == nsnull)
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_SERVICE_NOT_FOUND;
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
entry->mServiceObject = nsnull;
|
|
|
|
return rv;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-10-16 07:35:52 +04:00
|
|
|
nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
|
|
|
|
const nsIID& aIID,
|
|
|
|
void* *result)
|
2001-09-07 01:13:11 +04:00
|
|
|
{
|
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
2001-10-16 07:35:52 +04:00
|
|
|
if (gXPCOMShuttingDown) {
|
2001-09-07 01:13:11 +04:00
|
|
|
// When processing shutdown, dont process new GetService() requests
|
2002-01-10 05:10:37 +03:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
|
|
|
nsXPIDLCString iid;
|
|
|
|
iid.Adopt(aIID.ToString());
|
2002-05-12 01:15:06 +04:00
|
|
|
fprintf(stderr, "Getting service on shutdown. Denied.\n"
|
2002-01-10 05:10:37 +03:00
|
|
|
" ContractID: %s\n IID: %s\n", aContractID, iid.get());
|
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2001-09-07 01:13:11 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
nsresult rv = NS_OK;
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry *entry = nsnull;
|
|
|
|
nsContractIDTableEntry* contractIDTableEntry =
|
|
|
|
NS_STATIC_CAST(nsContractIDTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mContractIDs, aContractID,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
|
|
|
|
entry = contractIDTableEntry->mFactoryEntry;
|
|
|
|
}
|
2001-11-16 16:53:04 +03:00
|
|
|
|
|
|
|
if (entry && entry != kNonExistentContractID && entry->mServiceObject) {
|
|
|
|
return entry->mServiceObject->QueryInterface(aIID, result);
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
nsCOMPtr<nsISupports> service;
|
2001-09-07 01:13:11 +04:00
|
|
|
// We need to not be holding the service manager's monitor while calling
|
|
|
|
// CreateInstance, because it invokes user code which could try to re-enter
|
|
|
|
// the service manager:
|
|
|
|
mon.Exit();
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
rv = CreateInstanceByContractID(aContractID, nsnull, aIID, getter_AddRefs(service));
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-09-07 01:13:11 +04:00
|
|
|
mon.Enter();
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (!entry) { // second hash lookup for GetService
|
2001-10-23 06:28:12 +04:00
|
|
|
nsContractIDTableEntry* contractIDTableEntry =
|
|
|
|
NS_STATIC_CAST(nsContractIDTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mContractIDs, aContractID,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
|
|
|
|
entry = contractIDTableEntry->mFactoryEntry;
|
|
|
|
}
|
2001-09-07 01:13:11 +04:00
|
|
|
NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
|
|
|
|
if (!entry) return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-11-16 16:53:04 +03:00
|
|
|
entry->mServiceObject = service;
|
|
|
|
*result = service.get();
|
|
|
|
NS_ADDREF(NS_STATIC_CAST(nsISupports*, (*result)));
|
2001-09-07 01:13:11 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2001-10-17 03:39:20 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
|
|
|
|
nsISupports* *result,
|
|
|
|
nsIShutdownListener* shutdownListener)
|
|
|
|
{
|
|
|
|
return GetService(aClass, aIID, (void**)result);
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::GetService(const char* aContractID, const nsIID& aIID,
|
|
|
|
nsISupports* *result,
|
|
|
|
nsIShutdownListener* shutdownListener )
|
|
|
|
{
|
|
|
|
return GetServiceByContractID(aContractID, aIID, (void**)result);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::ReleaseService(const nsCID& aClass, nsISupports* service,
|
|
|
|
nsIShutdownListener* shutdownListener )
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(service);
|
|
|
|
return NS_OK;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::ReleaseService(const char* aContractID, nsISupports* service,
|
|
|
|
nsIShutdownListener* shutdownListener )
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(service);
|
|
|
|
return NS_OK;
|
|
|
|
};
|
2001-09-07 01:13:11 +04:00
|
|
|
|
1999-09-07 09:06:37 +04:00
|
|
|
/*
|
|
|
|
* I want an efficient way to allocate a buffer to the right size
|
|
|
|
* and stick the prefix and dllName in, then be able to hand that buffer
|
|
|
|
* off to the FactoryEntry. Is that so wrong?
|
|
|
|
*
|
|
|
|
* *regName is allocated on success.
|
|
|
|
*
|
|
|
|
* This should live in nsNativeComponentLoader.cpp, I think.
|
|
|
|
*/
|
|
|
|
static nsresult
|
|
|
|
MakeRegistryName(const char *aDllName, const char *prefix, char **regName)
|
|
|
|
{
|
|
|
|
char *registryName;
|
|
|
|
|
2002-02-20 09:38:38 +03:00
|
|
|
PRUint32 len = strlen(prefix);
|
1999-09-07 09:06:37 +04:00
|
|
|
|
2002-02-20 09:38:38 +03:00
|
|
|
PRUint32 registryNameLen = strlen(aDllName) + len;
|
2000-06-03 13:46:12 +04:00
|
|
|
registryName = (char *)nsMemory::Alloc(registryNameLen + 1);
|
1999-09-07 09:06:37 +04:00
|
|
|
|
|
|
|
// from here on it, we want len sans terminating NUL
|
|
|
|
|
|
|
|
if (!registryName)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2002-01-12 06:18:55 +03:00
|
|
|
memcpy(registryName, prefix, len);
|
1999-09-07 09:06:37 +04:00
|
|
|
strcpy(registryName + len, aDllName); // no nsCRT::strcpy? for shame!
|
|
|
|
registryName[registryNameLen] = '\0';
|
|
|
|
*regName = registryName;
|
|
|
|
|
|
|
|
#ifdef DEBUG_shaver_off
|
2000-10-29 02:17:53 +04:00
|
|
|
fprintf(stderr, "MakeRegistryName(%s, %s, &[%s])\n",
|
1999-09-07 09:06:37 +04:00
|
|
|
aDllName, prefix, *regName);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::RegistryNameForLib(const char *aLibName,
|
|
|
|
char **aRegistryName)
|
|
|
|
{
|
|
|
|
return MakeRegistryName(aLibName, XPCOM_LIB_PREFIX, aRegistryName);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2000-01-25 00:28:28 +03:00
|
|
|
nsComponentManagerImpl::RegistryLocationForSpec(nsIFile *aSpec,
|
1999-09-07 09:06:37 +04:00
|
|
|
char **aRegistryName)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2000-01-25 00:28:28 +03:00
|
|
|
|
|
|
|
if (!mComponentsDir)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
1999-09-07 09:06:37 +04:00
|
|
|
|
2001-06-21 00:21:49 +04:00
|
|
|
if (!aSpec) {
|
|
|
|
*aRegistryName = nsCRT::strdup("");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-01-25 00:28:28 +03:00
|
|
|
PRBool containedIn;
|
2000-01-29 02:54:26 +03:00
|
|
|
mComponentsDir->Contains(aSpec, PR_TRUE, &containedIn);
|
2000-01-25 00:28:28 +03:00
|
|
|
|
2002-04-27 09:33:09 +04:00
|
|
|
nsCAutoString persistentDescriptor;
|
2001-12-14 04:27:16 +03:00
|
|
|
|
2000-01-25 00:28:28 +03:00
|
|
|
if (containedIn){
|
2002-04-27 09:33:09 +04:00
|
|
|
rv = aSpec->GetNativePath(persistentDescriptor);
|
2001-12-14 04:27:16 +03:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2000-02-01 10:54:46 +03:00
|
|
|
|
2002-04-27 09:33:09 +04:00
|
|
|
const char* relativeLocation = persistentDescriptor.get() + mComponentsOffset + 1;
|
2001-12-14 04:27:16 +03:00
|
|
|
|
|
|
|
rv = MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX,
|
1999-09-07 09:06:37 +04:00
|
|
|
aRegistryName);
|
|
|
|
} else {
|
|
|
|
/* absolute names include volume info on Mac, so persistent descriptor */
|
2002-04-27 09:33:09 +04:00
|
|
|
rv = aSpec->GetNativePath(persistentDescriptor);
|
1999-09-07 09:06:37 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2002-04-27 09:33:09 +04:00
|
|
|
rv = MakeRegistryName(persistentDescriptor.get(), XPCOM_ABSCOMPONENT_PREFIX,
|
1999-09-07 09:06:37 +04:00
|
|
|
aRegistryName);
|
|
|
|
}
|
2000-01-25 00:28:28 +03:00
|
|
|
|
1999-09-07 09:06:37 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::SpecForRegistryLocation(const char *aLocation,
|
2000-01-25 00:28:28 +03:00
|
|
|
nsIFile **aSpec)
|
1999-09-07 09:06:37 +04:00
|
|
|
{
|
2002-04-27 09:33:09 +04:00
|
|
|
// i18n: assuming aLocation is encoded for the current locale
|
|
|
|
|
1999-09-07 09:06:37 +04:00
|
|
|
nsresult rv;
|
|
|
|
if (!aLocation || !aSpec)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
/* abs:/full/path/to/libcomponent.so */
|
|
|
|
if (!nsCRT::strncmp(aLocation, XPCOM_ABSCOMPONENT_PREFIX, 4)) {
|
2000-01-25 00:28:28 +03:00
|
|
|
|
|
|
|
nsLocalFile* file = new nsLocalFile;
|
|
|
|
if (!file) return NS_ERROR_FAILURE;
|
|
|
|
|
2002-04-27 09:33:09 +04:00
|
|
|
rv = file->InitWithNativePath(nsDependentCString((char *)aLocation + 4));
|
2000-01-25 00:28:28 +03:00
|
|
|
file->QueryInterface(NS_GET_IID(nsILocalFile), (void**)aSpec);
|
|
|
|
return rv;
|
1999-09-07 09:06:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!nsCRT::strncmp(aLocation, XPCOM_RELCOMPONENT_PREFIX, 4)) {
|
2000-01-25 00:28:28 +03:00
|
|
|
|
|
|
|
if (!mComponentsDir)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
nsILocalFile* file = nsnull;
|
|
|
|
rv = mComponentsDir->Clone((nsIFile**)&file);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2002-04-27 09:33:09 +04:00
|
|
|
rv = file->AppendRelativeNativePath(nsDependentCString(aLocation + 4));
|
2000-01-25 00:28:28 +03:00
|
|
|
*aSpec = file;
|
|
|
|
return rv;
|
1999-09-07 09:06:37 +04:00
|
|
|
}
|
|
|
|
*aSpec = nsnull;
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* RegisterFactory()
|
|
|
|
*
|
|
|
|
* Register a factory to be responsible for creation of implementation of
|
2000-09-14 03:57:52 +04:00
|
|
|
* classID aClass. Plus creates as association of aClassName and aContractID
|
1999-03-09 12:44:27 +03:00
|
|
|
* to the classID. If replace is PR_TRUE, we replace any existing registrations
|
|
|
|
* with this one.
|
|
|
|
*
|
|
|
|
* Once registration is complete, we add the class to the factories cache
|
|
|
|
* that we maintain. The factories cache is the ONLY place where these
|
|
|
|
* registrations are ever kept.
|
1999-09-01 01:40:21 +04:00
|
|
|
*
|
|
|
|
* The other RegisterFunctions create a loader mapping and persistent
|
|
|
|
* location, but we just slam it into the cache here. And we don't call the
|
|
|
|
* loader's OnRegister function, either.
|
1999-03-09 12:44:27 +03:00
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
|
|
|
|
const char *aClassName,
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *aContractID,
|
1999-03-09 12:44:27 +03:00
|
|
|
nsIFactory *aFactory,
|
|
|
|
PRBool aReplace)
|
|
|
|
{
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryEntry *entry = nsnull;
|
1999-07-07 11:47:14 +04:00
|
|
|
nsIDKey key(aClass);
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
2001-12-19 03:12:41 +03:00
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
entry = GetFactoryEntry(aClass, key,
|
|
|
|
0 /* dont check registry */);
|
2000-03-12 01:44:51 +03:00
|
|
|
|
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
|
|
|
char *buf = aClass.ToString();
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
|
|
|
("nsComponentManager: RegisterFactory(%s, %s)", buf,
|
2000-09-14 03:57:52 +04:00
|
|
|
(aContractID ? aContractID : "(null)")));
|
2000-03-12 01:44:51 +03:00
|
|
|
delete [] buf;
|
|
|
|
|
|
|
|
}
|
1999-09-01 01:40:21 +04:00
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
if (entry && !aReplace) {
|
1999-07-07 11:47:14 +04:00
|
|
|
// Already registered
|
1999-09-01 01:40:21 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
|
|
|
("\t\tFactory already registered."));
|
1999-07-07 11:47:14 +04:00
|
|
|
return NS_ERROR_FACTORY_EXISTS;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
1999-07-07 11:47:14 +04:00
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
if (entry) {
|
|
|
|
entry->ReInit(aClass, aFactory);
|
|
|
|
}
|
|
|
|
else {
|
2002-05-03 01:25:08 +04:00
|
|
|
void *mem;
|
|
|
|
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
|
|
|
|
if (!mem)
|
2001-10-23 06:28:12 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-05-03 01:25:08 +04:00
|
|
|
entry = new (mem) nsFactoryEntry(aClass, aFactory);
|
2001-10-23 06:28:12 +04:00
|
|
|
|
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
|
|
|
|
if (!factoryTableEntry)
|
2001-08-22 02:42:35 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
|
|
|
factoryTableEntry->mFactoryEntry = entry;
|
1999-04-12 16:32:24 +04:00
|
|
|
}
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
// Update the ContractID->CLSID Map
|
|
|
|
if (aContractID) {
|
2001-08-22 02:42:35 +04:00
|
|
|
nsresult rv = HashContractID(aContractID, entry);
|
1999-09-01 01:40:21 +04:00
|
|
|
if(NS_FAILED(rv)) {
|
1999-04-12 16:32:24 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
|
1999-09-01 01:40:21 +04:00
|
|
|
("\t\tFactory register succeeded. "
|
2000-09-14 03:57:52 +04:00
|
|
|
"Hashing contractid (%s) FAILED.", aContractID));
|
1999-09-01 01:40:21 +04:00
|
|
|
return rv;
|
1999-04-12 16:32:24 +04:00
|
|
|
}
|
|
|
|
}
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
|
2000-09-14 03:57:52 +04:00
|
|
|
("\t\tFactory register succeeded contractid=%s.",
|
|
|
|
aContractID ? aContractID : "<none>"));
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
return NS_OK;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::RegisterComponent(const nsCID &aClass,
|
|
|
|
const char *aClassName,
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *aContractID,
|
1999-09-01 01:40:21 +04:00
|
|
|
const char *aPersistentDescriptor,
|
1999-03-09 12:44:27 +03:00
|
|
|
PRBool aReplace,
|
|
|
|
PRBool aPersist)
|
|
|
|
{
|
2000-09-14 03:57:52 +04:00
|
|
|
return RegisterComponentCommon(aClass, aClassName, aContractID,
|
1999-12-09 03:01:46 +03:00
|
|
|
aPersistentDescriptor, aReplace, aPersist,
|
|
|
|
nativeComponentType);
|
1999-06-22 18:02:58 +04:00
|
|
|
}
|
|
|
|
|
1999-09-06 20:43:09 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::RegisterComponentWithType(const nsCID &aClass,
|
|
|
|
const char *aClassName,
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *aContractID,
|
2000-01-25 00:28:28 +03:00
|
|
|
nsIFile *aSpec,
|
1999-09-07 09:06:37 +04:00
|
|
|
const char *aLocation,
|
1999-09-06 20:43:09 +04:00
|
|
|
PRBool aReplace,
|
|
|
|
PRBool aPersist,
|
|
|
|
const char *aType)
|
|
|
|
{
|
2000-09-14 03:57:52 +04:00
|
|
|
return RegisterComponentCommon(aClass, aClassName, aContractID,
|
1999-11-19 05:14:23 +03:00
|
|
|
aLocation,
|
1999-09-06 20:43:09 +04:00
|
|
|
aReplace, aPersist,
|
|
|
|
aType);
|
|
|
|
}
|
1999-06-22 18:02:58 +04:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
/*
|
2000-01-25 00:28:28 +03:00
|
|
|
* Register a component, using whatever they stuck in the nsIFile.
|
1999-09-01 01:40:21 +04:00
|
|
|
*/
|
1999-06-22 18:02:58 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::RegisterComponentSpec(const nsCID &aClass,
|
|
|
|
const char *aClassName,
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *aContractID,
|
2000-01-25 00:28:28 +03:00
|
|
|
nsIFile *aLibrarySpec,
|
1999-06-22 18:02:58 +04:00
|
|
|
PRBool aReplace,
|
|
|
|
PRBool aPersist)
|
|
|
|
{
|
1999-11-19 05:14:23 +03:00
|
|
|
nsXPIDLCString registryName;
|
|
|
|
nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
|
1999-09-07 09:06:37 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
rv = RegisterComponentWithType(aClass, aClassName, aContractID, aLibrarySpec,
|
1999-09-07 09:06:37 +04:00
|
|
|
registryName,
|
|
|
|
aReplace, aPersist,
|
|
|
|
nativeComponentType);
|
|
|
|
return rv;
|
1999-09-01 01:40:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Register a ``library'', which is a DLL location named by a simple filename
|
|
|
|
* such as ``libnsappshell.so'', rather than a relative or absolute path.
|
|
|
|
*
|
|
|
|
* It implies application/x-moz-dll as the component type, and skips the
|
|
|
|
* FindLoaderForType phase.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::RegisterComponentLib(const nsCID &aClass,
|
|
|
|
const char *aClassName,
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *aContractID,
|
1999-09-01 01:40:21 +04:00
|
|
|
const char *aDllName,
|
|
|
|
PRBool aReplace,
|
|
|
|
PRBool aPersist)
|
|
|
|
{
|
1999-11-19 05:14:23 +03:00
|
|
|
nsXPIDLCString registryName;
|
|
|
|
nsresult rv = RegistryNameForLib(aDllName, getter_Copies(registryName));
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2000-09-14 03:57:52 +04:00
|
|
|
return RegisterComponentCommon(aClass, aClassName, aContractID, registryName,
|
1999-09-01 01:40:21 +04:00
|
|
|
aReplace, aPersist, nativeComponentType);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add a component to the known universe of components.
|
|
|
|
|
|
|
|
* Once we enter this function, we own aRegistryName, and must free it
|
|
|
|
* or hand it to nsFactoryEntry. Common exit point ``out'' helps keep us
|
|
|
|
* sane.
|
|
|
|
*/
|
2001-08-22 02:42:35 +04:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
|
|
|
|
const char *aClassName,
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *aContractID,
|
1999-11-19 05:14:23 +03:00
|
|
|
const char *aRegistryName,
|
1999-09-01 01:40:21 +04:00
|
|
|
PRBool aReplace,
|
|
|
|
PRBool aPersist,
|
|
|
|
const char *aType)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-07-07 11:47:14 +04:00
|
|
|
nsIDKey key(aClass);
|
2001-10-23 06:28:12 +04:00
|
|
|
nsAutoMonitor mon(mMon);
|
2001-12-19 03:12:41 +03:00
|
|
|
|
1999-09-10 09:27:23 +04:00
|
|
|
nsFactoryEntry *entry = GetFactoryEntry(aClass, !mPrePopulationDone);
|
1999-07-07 11:47:14 +04:00
|
|
|
|
2000-03-25 09:57:25 +03:00
|
|
|
// Normalize proid and classname
|
2002-04-16 02:33:03 +04:00
|
|
|
const char *contractID = (aContractID && *aContractID) ? aContractID : nsnull;
|
|
|
|
const char *className = (aClassName && *aClassName) ? aClassName : nsnull;
|
2000-03-25 09:57:25 +03:00
|
|
|
|
2000-03-12 01:44:51 +03:00
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
|
|
|
char *buf = aClass.ToString();
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
|
|
|
|
("nsComponentManager: RegisterComponentCommon(%s, %s, %s, %s)",
|
|
|
|
buf,
|
2000-09-14 03:57:52 +04:00
|
|
|
contractID ? contractID : "(null)",
|
2000-03-12 01:44:51 +03:00
|
|
|
aRegistryName, aType));
|
|
|
|
delete [] buf;
|
|
|
|
}
|
1999-09-01 01:40:21 +04:00
|
|
|
|
|
|
|
if (entry && !aReplace) {
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
|
|
|
("\t\tFactory already registered."));
|
2001-08-22 02:42:35 +04:00
|
|
|
return NS_ERROR_FACTORY_EXISTS;
|
1999-09-01 01:40:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_REGISTRY
|
|
|
|
if (aPersist) {
|
|
|
|
/* Add to the registry */
|
2000-09-14 03:57:52 +04:00
|
|
|
rv = AddComponentToRegistry(aClass, className, contractID,
|
1999-09-01 01:40:21 +04:00
|
|
|
aRegistryName, aType);
|
|
|
|
if (NS_FAILED(rv)) {
|
2001-08-22 02:42:35 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
|
|
|
("\t\tadding %s %s to registry FAILED", className, contractID));
|
|
|
|
return rv;
|
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
#endif
|
1999-09-01 01:40:21 +04:00
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
int typeIndex = GetLoaderType(aType);
|
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
nsCOMPtr<nsIComponentLoader> loader;
|
2001-08-30 18:10:41 +04:00
|
|
|
rv = GetLoaderForType(typeIndex, getter_AddRefs(loader));
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
2001-08-22 02:42:35 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
|
|
|
("\t\tgetting loader for %s FAILED\n", aType));
|
|
|
|
return rv;
|
1999-06-22 18:02:58 +04:00
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
|
2001-08-22 02:42:35 +04:00
|
|
|
if (entry) {
|
2001-08-30 18:10:41 +04:00
|
|
|
entry->ReInit(aClass, aRegistryName, typeIndex);
|
1999-09-01 01:40:21 +04:00
|
|
|
}
|
2001-08-22 02:42:35 +04:00
|
|
|
else {
|
2002-05-03 01:25:08 +04:00
|
|
|
void *mem;
|
|
|
|
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
|
|
|
|
if (!mem)
|
2001-08-22 02:42:35 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-05-03 01:25:08 +04:00
|
|
|
entry = new (mem) nsFactoryEntry(aClass, aRegistryName, typeIndex);
|
1999-09-01 01:40:21 +04:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
nsFactoryTableEntry* factoryTableEntry =
|
|
|
|
NS_STATIC_CAST(nsFactoryTableEntry*,
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass,
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
|
|
|
|
if (!factoryTableEntry)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
factoryTableEntry->mFactoryEntry = entry;
|
1999-09-01 01:40:21 +04:00
|
|
|
}
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
// Update the ContractID->CLSID Map
|
|
|
|
if (contractID
|
1999-06-22 18:02:58 +04:00
|
|
|
#ifdef USE_REGISTRY
|
2000-03-03 04:48:41 +03:00
|
|
|
&& (mPrePopulationDone || !aPersist)
|
1999-09-01 01:40:21 +04:00
|
|
|
#endif
|
|
|
|
) {
|
2001-08-22 02:42:35 +04:00
|
|
|
rv = HashContractID(contractID, entry);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
2001-08-22 02:42:35 +04:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
|
|
|
("\t\tHashContractID(%s) FAILED\n", contractID));
|
|
|
|
return rv;
|
|
|
|
}
|
1999-09-01 01:40:21 +04:00
|
|
|
}
|
1999-07-07 11:47:14 +04:00
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
// Let the loader do magic things now
|
2000-09-14 03:57:52 +04:00
|
|
|
rv = loader->OnRegister(aClass, aType, className, contractID, aRegistryName,
|
1999-09-01 01:40:21 +04:00
|
|
|
aReplace, aPersist);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
|
2000-03-12 01:44:51 +03:00
|
|
|
("\t\tloader->OnRegister FAILED for %s \"%s\" %s %s", aType,
|
2000-09-14 03:57:52 +04:00
|
|
|
className, contractID, aRegistryName));
|
2001-08-22 02:42:35 +04:00
|
|
|
return rv;
|
1999-09-01 01:40:21 +04:00
|
|
|
}
|
|
|
|
|
2000-03-12 01:44:51 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
|
|
|
("\t\tRegisterComponentCommon() %s",
|
|
|
|
NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
1999-06-22 18:02:58 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2001-08-30 18:10:41 +04:00
|
|
|
nsComponentManagerImpl::GetLoaderForType(int aType,
|
1999-09-01 01:40:21 +04:00
|
|
|
nsIComponentLoader **aLoader)
|
1999-06-22 18:02:58 +04:00
|
|
|
{
|
1999-09-01 01:40:21 +04:00
|
|
|
nsresult rv;
|
1999-06-22 18:02:58 +04:00
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
// Make sure we have a valid type
|
|
|
|
if (aType < 0 || aType >= mNLoaderData)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
*aLoader = mLoaderData[aType].loader;
|
|
|
|
if (*aLoader) {
|
|
|
|
NS_ADDREF(*aLoader);
|
2000-05-26 08:56:23 +04:00
|
|
|
return NS_OK;
|
1999-06-22 18:02:58 +04:00
|
|
|
}
|
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
nsCOMPtr<nsIComponentLoader> loader;
|
|
|
|
loader = do_GetServiceFromCategory("component-loader", mLoaderData[aType].type, &rv);
|
1999-09-02 11:00:29 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
1999-09-04 03:51:31 +04:00
|
|
|
rv = loader->Init(this, mRegistry);
|
1999-09-01 01:40:21 +04:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2001-08-30 18:10:41 +04:00
|
|
|
mLoaderData[aType].loader = loader;
|
|
|
|
NS_ADDREF(mLoaderData[aType].loader);
|
2000-05-26 08:56:23 +04:00
|
|
|
*aLoader = loader;
|
|
|
|
NS_ADDREF(*aLoader);
|
1999-06-22 18:02:58 +04:00
|
|
|
}
|
1999-09-01 01:40:21 +04:00
|
|
|
return rv;
|
|
|
|
}
|
1999-06-22 18:02:58 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
|
|
|
|
// Convert a loader type string into an index into the component data
|
|
|
|
// array. Empty loader types are converted to NATIVE. Returns -1 if
|
|
|
|
// loader type cannot be determined.
|
|
|
|
int
|
|
|
|
nsComponentManagerImpl::GetLoaderType(const char *typeStr)
|
|
|
|
{
|
|
|
|
if (!typeStr || !*typeStr) {
|
|
|
|
// Empty type strings are NATIVE
|
|
|
|
return NS_COMPONENT_TYPE_NATIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=NS_COMPONENT_TYPE_NATIVE; i<mNLoaderData; i++) {
|
|
|
|
if (!strcmp(typeStr, mLoaderData[i].type))
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
// Not found
|
|
|
|
return NS_COMPONENT_TYPE_FACTORY_ONLY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a loader type if not already known. Return the typeIndex
|
|
|
|
// if the loader type is either added or already there.
|
|
|
|
int
|
|
|
|
nsComponentManagerImpl::AddLoaderType(const char *typeStr)
|
|
|
|
{
|
|
|
|
int typeIndex = GetLoaderType(typeStr);
|
|
|
|
if (typeIndex >= 0) {
|
|
|
|
return typeIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the loader type
|
|
|
|
if (mNLoaderData >= mMaxNLoaderData) {
|
|
|
|
NS_ASSERTION(mNLoaderData == mMaxNLoaderData,
|
|
|
|
"Memory corruption. nsComponentManagerImpl::mLoaderData array overrun.");
|
|
|
|
// Need to increase our loader array
|
|
|
|
nsLoaderdata *new_mLoaderData = (nsLoaderdata *) PR_Realloc(mLoaderData, (mMaxNLoaderData + NS_LOADER_DATA_ALLOC_STEP) * sizeof(nsLoaderdata));
|
|
|
|
if (!new_mLoaderData)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
mLoaderData = new_mLoaderData;
|
|
|
|
mMaxNLoaderData += NS_LOADER_DATA_ALLOC_STEP;
|
|
|
|
}
|
|
|
|
|
|
|
|
typeIndex = mNLoaderData;
|
|
|
|
mLoaderData[typeIndex].type = PL_strdup(typeStr);
|
|
|
|
if (!mLoaderData[typeIndex].type) {
|
|
|
|
// mmh! no memory. return failure.
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
mLoaderData[typeIndex].loader = nsnull;
|
|
|
|
mNLoaderData++;
|
|
|
|
|
|
|
|
return typeIndex;
|
|
|
|
}
|
|
|
|
|
1999-09-01 01:40:21 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass,
|
|
|
|
const char *aClassName,
|
2000-09-14 03:57:52 +04:00
|
|
|
const char *aContractID,
|
1999-09-01 01:40:21 +04:00
|
|
|
const char *aRegistryName,
|
|
|
|
const char *aType)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2000-05-12 05:24:36 +04:00
|
|
|
PRUint32 length = strlen(aRegistryName);
|
|
|
|
char* eRegistryName;
|
|
|
|
rv = mRegistry->EscapeKey((PRUint8*)aRegistryName, 1, &length, (PRUint8**)&eRegistryName);
|
|
|
|
if (rv != NS_OK)
|
|
|
|
{
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
if (eRegistryName == nsnull) // No escaping required
|
|
|
|
eRegistryName = (char*)aRegistryName;
|
|
|
|
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey IDKey;
|
1999-09-29 06:54:18 +04:00
|
|
|
PRInt32 nComponents = 0;
|
1999-09-01 01:40:21 +04:00
|
|
|
|
|
|
|
/* so why do we use strings here rather than writing bytes, anyway? */
|
|
|
|
char *cidString = aClass.ToString();
|
|
|
|
if (!cidString)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
rv = mRegistry->AddSubtreeRaw(mCLSIDKey, cidString, &IDKey);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (aClassName) {
|
2000-02-15 04:32:12 +03:00
|
|
|
rv = mRegistry->SetStringUTF8(IDKey, classNameValueName, aClassName);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
1999-03-10 12:16:28 +03:00
|
|
|
}
|
1999-07-07 11:47:14 +04:00
|
|
|
|
2000-05-12 05:24:36 +04:00
|
|
|
rv = mRegistry->SetBytesUTF8(IDKey, inprocServerValueName,
|
|
|
|
strlen(aRegistryName) + 1,
|
|
|
|
(PRUint8*)aRegistryName);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
|
|
|
|
2000-02-15 04:32:12 +03:00
|
|
|
rv = mRegistry->SetStringUTF8(IDKey, componentTypeValueName, aType);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
if (aContractID) {
|
|
|
|
rv = mRegistry->SetStringUTF8(IDKey, contractIDValueName, aContractID);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
|
|
|
|
2000-09-14 03:57:52 +04:00
|
|
|
nsRegistryKey contractIDKey;
|
|
|
|
rv = mRegistry->AddSubtreeRaw(mClassesKey, aContractID, &contractIDKey);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
2000-09-14 03:57:52 +04:00
|
|
|
rv = mRegistry->SetStringUTF8(contractIDKey, classIDValueName, cidString);
|
1999-09-01 01:40:21 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
1999-09-29 06:35:42 +04:00
|
|
|
nsRegistryKey compKey;
|
2000-05-12 05:24:36 +04:00
|
|
|
rv = mRegistry->AddSubtreeRaw(mXPCOMKey, eRegistryName, &compKey);
|
1999-09-01 01:40:21 +04:00
|
|
|
|
|
|
|
// update component count
|
|
|
|
rv = mRegistry->GetInt(compKey, componentCountValueName, &nComponents);
|
|
|
|
nComponents++;
|
|
|
|
rv = mRegistry->SetInt(compKey, componentCountValueName, nComponents);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
out:
|
|
|
|
// XXX if failed, undo registry adds or set invalid bit? How?
|
1999-09-21 00:53:57 +04:00
|
|
|
nsCRT::free(cidString);
|
2000-05-12 05:24:36 +04:00
|
|
|
if (eRegistryName != aRegistryName)
|
2000-06-03 13:46:12 +04:00
|
|
|
nsMemory::Free(eRegistryName);
|
1999-03-10 12:53:25 +03:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
const nsCID* cid;
|
|
|
|
const char* regName;
|
|
|
|
nsIFactory* factory;
|
|
|
|
} UnregisterConditions;
|
|
|
|
|
|
|
|
static PLDHashOperator PR_CALLBACK
|
|
|
|
DeleteFoundCIDs(PLDHashTable *aTable,
|
|
|
|
PLDHashEntryHdr *aHdr,
|
|
|
|
PRUint32 aNumber,
|
|
|
|
void *aData)
|
|
|
|
{
|
|
|
|
nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
|
|
|
|
|
|
|
|
if (!entry->mFactoryEntry || entry->mFactoryEntry == kNonExistentContractID)
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
|
|
|
|
UnregisterConditions* data = (UnregisterConditions*)aData;
|
|
|
|
|
|
|
|
nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
|
|
|
|
if (data->cid->Equals(factoryEntry->cid) &&
|
|
|
|
((data->regName && !PL_strcasecmp(factoryEntry->location, data->regName)) ||
|
|
|
|
(data->factory && data->factory == factoryEntry->factory.get())))
|
|
|
|
return PL_DHASH_REMOVE;
|
|
|
|
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, const char*registryName)
|
|
|
|
{
|
|
|
|
UnregisterConditions aData;
|
|
|
|
aData.cid = aClass;
|
|
|
|
aData.regName = registryName;
|
|
|
|
aData.factory = nsnull;
|
|
|
|
PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory)
|
|
|
|
{
|
|
|
|
UnregisterConditions aData;
|
|
|
|
aData.cid = aClass;
|
|
|
|
aData.regName = nsnull;
|
|
|
|
aData.factory = factory;
|
|
|
|
PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
|
|
|
|
}
|
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
|
|
|
|
nsIFactory *aFactory)
|
|
|
|
{
|
1999-03-10 12:53:25 +03:00
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
|
|
|
char *buf = aClass.ToString();
|
2000-03-12 01:44:51 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
|
|
|
|
("nsComponentManager: UnregisterFactory(%s)", buf));
|
1999-03-10 12:53:25 +03:00
|
|
|
delete [] buf;
|
|
|
|
}
|
2000-05-12 05:24:36 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
nsFactoryEntry *old;
|
|
|
|
|
|
|
|
// first delete all contract id entries that are registered with this cid.
|
|
|
|
DeleteContractIDEntriesByCID(&aClass, aFactory);
|
|
|
|
|
|
|
|
// next check to see if there is a CID registered
|
1999-03-10 12:53:25 +03:00
|
|
|
nsIDKey key(aClass);
|
|
|
|
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
|
2002-01-30 00:22:13 +03:00
|
|
|
old = GetFactoryEntry(aClass, key, 0 /* dont check registry */);
|
|
|
|
|
|
|
|
if (old && (old->factory.get() == aFactory))
|
|
|
|
{
|
|
|
|
nsAutoMonitor mon(mMon);
|
|
|
|
PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
|
|
|
|
res = NS_OK;
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
|
2000-03-12 01:44:51 +03:00
|
|
|
("\t\tUnregisterFactory() %s",
|
|
|
|
NS_SUCCEEDED(res) ? "succeeded" : "FAILED"));
|
1999-03-10 12:53:25 +03:00
|
|
|
return res;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
|
2000-05-05 10:37:39 +04:00
|
|
|
const char *registryName)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
|
|
|
|
{
|
|
|
|
char *buf = aClass.ToString();
|
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
|
|
|
|
("nsComponentManager: UnregisterComponent(%s)", buf));
|
|
|
|
delete [] buf;
|
|
|
|
}
|
1999-08-13 23:30:13 +04:00
|
|
|
|
2000-05-05 10:37:39 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(registryName);
|
2002-01-30 00:22:13 +03:00
|
|
|
nsresult rv;
|
|
|
|
nsFactoryEntry *old;
|
|
|
|
|
|
|
|
// first delete all contract id entries that are registered with this cid.
|
|
|
|
DeleteContractIDEntriesByCID(&aClass, registryName);
|
1999-08-13 23:30:13 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
// next check to see if there is a CID registered
|
2000-04-18 09:25:05 +04:00
|
|
|
nsIDKey key(aClass);
|
2002-01-30 00:22:13 +03:00
|
|
|
old = GetFactoryEntry(aClass, key, 0 /* dont check registry */);
|
|
|
|
if (old && old->location && !PL_strcasecmp(old->location, registryName))
|
|
|
|
{
|
|
|
|
nsAutoMonitor mon(mMon);
|
2001-10-23 06:28:12 +04:00
|
|
|
PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
|
2000-04-18 09:25:05 +04:00
|
|
|
}
|
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
#ifdef USE_REGISTRY
|
2000-04-18 09:25:05 +04:00
|
|
|
// Remove registry entries for this cid
|
|
|
|
char *cidString = aClass.ToString();
|
|
|
|
rv = PlatformUnregister(cidString, registryName);
|
|
|
|
delete [] cidString;
|
1999-03-09 12:44:27 +03:00
|
|
|
#endif
|
2001-10-23 06:28:12 +04:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
|
2000-05-05 10:37:39 +04:00
|
|
|
("nsComponentManager: Factory unregister(%s) %s.", registryName,
|
2000-04-18 09:25:05 +04:00
|
|
|
NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
|
|
|
|
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2000-05-05 10:37:39 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::UnregisterComponentSpec(const nsCID &aClass,
|
|
|
|
nsIFile *aLibrarySpec)
|
|
|
|
{
|
|
|
|
nsXPIDLCString registryName;
|
|
|
|
nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
return UnregisterComponent(aClass, registryName);
|
|
|
|
}
|
|
|
|
|
1999-09-26 22:04:27 +04:00
|
|
|
// XXX Need to pass in aWhen and servicemanager
|
1999-03-09 12:44:27 +03:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::FreeLibraries(void)
|
1999-07-31 09:55:04 +04:00
|
|
|
{
|
2001-10-16 07:35:52 +04:00
|
|
|
return UnloadLibraries(NS_STATIC_CAST(nsIServiceManager*, this), NS_Timer); // XXX when
|
1999-07-31 09:55:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Private implementation of unloading libraries
|
|
|
|
nsresult
|
1999-09-26 22:04:27 +04:00
|
|
|
nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 aWhen)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
1999-09-23 04:01:53 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
2001-12-19 03:12:41 +03:00
|
|
|
nsAutoMonitor mon(mMon);
|
2000-05-12 05:24:36 +04:00
|
|
|
|
1999-03-10 12:53:25 +03:00
|
|
|
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
|
1999-07-31 09:55:04 +04:00
|
|
|
("nsComponentManager: Unloading Libraries."));
|
1999-03-09 12:44:27 +03:00
|
|
|
|
1999-09-23 04:14:00 +04:00
|
|
|
// UnloadAll the loaders
|
|
|
|
/* iterate over all known loaders and ask them to autoregister. */
|
2001-08-30 18:10:41 +04:00
|
|
|
// Skip mNativeComponentLoader
|
|
|
|
for (int i=NS_COMPONENT_TYPE_NATIVE + 1; i<mNLoaderData; i++) {
|
2001-08-31 21:45:51 +04:00
|
|
|
if (mLoaderData[i].loader) {
|
|
|
|
rv = mLoaderData[i].loader->UnloadAll(aWhen);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
}
|
1999-09-23 04:01:53 +04:00
|
|
|
|
|
|
|
// UnloadAll the native loader
|
1999-09-26 22:04:27 +04:00
|
|
|
rv = mNativeComponentLoader->UnloadAll(aWhen);
|
1999-09-23 04:01:53 +04:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
1999-04-03 00:28:22 +04:00
|
|
|
* AutoRegister(RegistrationInstant, const char *directory)
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
1999-04-03 00:28:22 +04:00
|
|
|
* Given a directory in the following format, this will ensure proper registration
|
2002-01-30 00:22:13 +03:00
|
|
|
* of all components. No default directory is looked at.
|
1999-04-03 00:28:22 +04:00
|
|
|
*
|
|
|
|
* Directory and fullname are what NSPR will accept. For eg.
|
2002-01-30 00:22:13 +03:00
|
|
|
* WIN y:/home/dp/mozilla/dist/bin
|
|
|
|
* UNIX /home/dp/mozilla/dist/bin
|
2000-05-12 05:24:36 +04:00
|
|
|
* MAC /Hard drive/mozilla/dist/apprunner
|
1999-03-09 12:44:27 +03:00
|
|
|
*
|
|
|
|
* This will take care not loading already registered dlls, finding and
|
|
|
|
* registering new dlls, re-registration of modified dlls
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
nsresult
|
2000-01-25 00:28:28 +03:00
|
|
|
nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
|
2000-09-08 05:51:45 +04:00
|
|
|
{
|
2000-09-08 06:53:12 +04:00
|
|
|
nsresult rv;
|
2001-11-30 10:50:03 +03:00
|
|
|
((nsRegistry *)mRegistry)->SetBufferSize( BIG_REGISTRY_BUFLEN );
|
2000-09-08 06:53:12 +04:00
|
|
|
rv = AutoRegisterImpl(when, inDirSpec);
|
2001-04-17 18:25:19 +04:00
|
|
|
mRegistry->Flush();
|
2001-11-30 10:50:03 +03:00
|
|
|
((nsRegistry *)mRegistry)->SetBufferSize( -1 );
|
2000-09-08 06:53:12 +04:00
|
|
|
return rv;
|
2000-09-08 05:51:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2002-01-30 00:22:13 +03:00
|
|
|
nsComponentManagerImpl::AutoRegisterImpl(PRInt32 when,
|
|
|
|
nsIFile *inDirSpec,
|
|
|
|
PRBool fileIsCompDir)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2000-01-25 00:28:28 +03:00
|
|
|
nsCOMPtr<nsIFile> dir;
|
1999-06-22 18:02:58 +04:00
|
|
|
nsresult rv;
|
1999-03-10 12:53:25 +03:00
|
|
|
|
2000-05-05 10:37:39 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
// testing release behaviour
|
|
|
|
if (getenv("XPCOM_NO_AUTOREG"))
|
|
|
|
return NS_OK;
|
|
|
|
#endif
|
2000-05-02 04:54:11 +04:00
|
|
|
if (inDirSpec)
|
|
|
|
{
|
|
|
|
// Use supplied components' directory
|
|
|
|
dir = inDirSpec;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-09-01 01:40:21 +04:00
|
|
|
// Do default components directory
|
2001-07-25 11:54:28 +04:00
|
|
|
nsCOMPtr<nsIProperties> directoryService =
|
2002-01-30 00:22:13 +03:00
|
|
|
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2000-01-25 00:28:28 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
rv = directoryService->Get(NS_XPCOM_COMPONENT_DIR,
|
|
|
|
NS_GET_IID(nsIFile),
|
|
|
|
getter_AddRefs(dir));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv; // XXX translate error code?
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
1999-06-22 18:02:58 +04:00
|
|
|
|
2000-04-25 09:11:30 +04:00
|
|
|
nsCOMPtr<nsIInterfaceInfoManager> iim =
|
|
|
|
dont_AddRef(XPTI_GetInterfaceInfoManager());
|
|
|
|
|
|
|
|
if (!iim)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2001-10-31 01:19:32 +03:00
|
|
|
|
2000-05-15 23:28:12 +04:00
|
|
|
// Notify observers of xpcom autoregistration start
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
|
|
|
|
nsnull,
|
2001-11-01 02:17:30 +03:00
|
|
|
"start");
|
2000-04-25 09:11:30 +04:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
/* do the native loader first, so we can find other loaders */
|
|
|
|
rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
|
2000-09-09 05:36:18 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2001-06-21 00:21:49 +04:00
|
|
|
#ifdef ENABLE_STATIC_COMPONENT_LOADER
|
|
|
|
rv = mStaticComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
#endif
|
|
|
|
|
2000-09-09 05:36:18 +04:00
|
|
|
/* do InterfaceInfoManager after native loader so it can use components. */
|
|
|
|
rv = iim->AutoRegisterInterfaces();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-09-01 01:40:21 +04:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
nsCOMPtr<nsICategoryManager> catman =
|
2000-09-14 03:57:52 +04:00
|
|
|
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
|
2000-05-26 08:56:23 +04:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-09-02 11:00:29 +04:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
nsCOMPtr<nsISimpleEnumerator> loaderEnum;
|
|
|
|
rv = catman->EnumerateCategory("component-loader",
|
|
|
|
getter_AddRefs(loaderEnum));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
1999-11-10 03:28:34 +03:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
PRBool hasMore;
|
|
|
|
while (NS_SUCCEEDED(loaderEnum->HasMoreElements(&hasMore)) && hasMore) {
|
|
|
|
nsCOMPtr<nsISupports> supports;
|
|
|
|
if (NS_FAILED(loaderEnum->GetNext(getter_AddRefs(supports))))
|
2000-05-15 23:28:12 +04:00
|
|
|
continue;
|
1999-11-10 03:28:34 +03:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
nsCOMPtr<nsISupportsString> supStr = do_QueryInterface(supports);
|
|
|
|
if (!supStr)
|
|
|
|
continue;
|
2000-05-15 23:28:12 +04:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
nsXPIDLCString loaderType;
|
|
|
|
if (NS_FAILED(supStr->GetData(getter_Copies(loaderType))))
|
|
|
|
continue;
|
|
|
|
|
2001-08-30 18:10:41 +04:00
|
|
|
// We depend on the loader being created. Add the loader type and
|
|
|
|
// create the loader object too.
|
2000-05-26 08:56:23 +04:00
|
|
|
nsCOMPtr<nsIComponentLoader> loader;
|
2001-08-30 18:10:41 +04:00
|
|
|
GetLoaderForType(AddLoaderType(loaderType), getter_AddRefs(loader));
|
2000-05-15 23:28:12 +04:00
|
|
|
}
|
2000-05-17 05:53:50 +04:00
|
|
|
|
2000-05-26 08:56:23 +04:00
|
|
|
/* iterate over all known loaders and ask them to autoregister. */
|
|
|
|
/* XXX convert when to nsIComponentLoader::(when) properly */
|
2001-08-30 18:10:41 +04:00
|
|
|
nsIFile *spec = dir.get();
|
|
|
|
for (int i = NS_COMPONENT_TYPE_NATIVE + 1; i < mNLoaderData; i++) {
|
2001-11-18 23:19:44 +03:00
|
|
|
if (!mLoaderData[i].loader) {
|
|
|
|
rv = GetLoaderForType(i, &mLoaderData[i].loader);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
continue;
|
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
rv = mLoaderData[i].loader->AutoRegisterComponents(when, spec);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
}
|
2000-05-26 08:56:23 +04:00
|
|
|
|
2000-05-15 23:28:12 +04:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
2001-08-30 18:10:41 +04:00
|
|
|
PRBool registered;
|
2000-05-15 23:28:12 +04:00
|
|
|
do {
|
2001-08-30 18:10:41 +04:00
|
|
|
registered = PR_FALSE;
|
|
|
|
for (int i = NS_COMPONENT_TYPE_NATIVE; i < mNLoaderData; i++) {
|
|
|
|
PRBool b = PR_FALSE;
|
2001-11-18 23:19:44 +03:00
|
|
|
if (mLoaderData[i].loader) {
|
|
|
|
rv = mLoaderData[i].loader->RegisterDeferredComponents(when, &b);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
continue;
|
|
|
|
registered |= b;
|
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
}
|
|
|
|
} while (NS_SUCCEEDED(rv) && registered);
|
2000-05-15 23:28:12 +04:00
|
|
|
}
|
2001-11-01 02:17:30 +03:00
|
|
|
|
|
|
|
// Notify observers of xpcom autoregistration completion
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
|
|
|
|
nsnull,
|
|
|
|
"end");
|
2000-05-15 23:28:12 +04:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
1999-09-05 10:27:42 +04:00
|
|
|
nsComponentManagerImpl::AutoRegisterComponent(PRInt32 when,
|
2000-01-25 00:28:28 +03:00
|
|
|
nsIFile *component)
|
1999-03-09 12:44:27 +03:00
|
|
|
{
|
2001-08-30 18:10:41 +04:00
|
|
|
nsresult rv = NS_OK;
|
1999-09-01 01:40:21 +04:00
|
|
|
/*
|
|
|
|
* Do we have to give the native loader first crack at it?
|
|
|
|
* I vote ``no''.
|
|
|
|
*/
|
2001-08-30 18:10:41 +04:00
|
|
|
for (int i = 0; i < mNLoaderData; i++) {
|
|
|
|
PRBool didRegister;
|
2001-11-18 23:19:44 +03:00
|
|
|
if (!mLoaderData[i].loader) {
|
|
|
|
rv = GetLoaderForType(i, &mLoaderData[i].loader);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
continue;
|
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
rv = mLoaderData[i].loader->AutoRegisterComponent((int)when, component, &didRegister);
|
|
|
|
if (NS_SUCCEEDED(rv) && didRegister)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return NS_FAILED(rv) ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
|
1999-08-09 09:40:51 +04:00
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2000-04-18 09:25:05 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 when,
|
|
|
|
nsIFile *component)
|
|
|
|
{
|
2001-08-30 18:10:41 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
for (int i = 0; i < mNLoaderData; i++) {
|
|
|
|
PRBool didUnRegister;
|
2001-11-18 23:19:44 +03:00
|
|
|
if (!mLoaderData[i].loader) {
|
|
|
|
rv = GetLoaderForType(i, &mLoaderData[i].loader);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
continue;
|
|
|
|
}
|
2001-08-30 18:10:41 +04:00
|
|
|
rv = mLoaderData[i].loader->AutoUnregisterComponent(when, component, &didUnRegister);
|
|
|
|
if (NS_SUCCEEDED(rv) && didUnRegister)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return NS_FAILED(rv) ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
|
2000-04-18 09:25:05 +04:00
|
|
|
}
|
|
|
|
|
1999-08-09 09:02:25 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::IsRegistered(const nsCID &aClass,
|
|
|
|
PRBool *aRegistered)
|
|
|
|
{
|
|
|
|
if(!aRegistered)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(0, "null ptr");
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2001-08-22 02:42:35 +04:00
|
|
|
*aRegistered = (nsnull != GetFactoryEntry(aClass));
|
1999-08-09 09:02:25 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
|
2001-10-23 06:28:12 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_ASSERTION(aEnumerator != nsnull, "null ptr");
|
|
|
|
if(!aEnumerator)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
*aEnumerator = nsnull;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
nsresult rv;
|
|
|
|
if(!mPrePopulationDone)
|
|
|
|
{
|
|
|
|
rv = PlatformPrePopulateRegistry();
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
PLDHashTableEnumeratorImpl *aEnum;
|
|
|
|
rv = PL_NewDHashTableEnumerator(&mFactories,
|
|
|
|
ConvertFactoryEntryToCID,
|
2002-02-13 23:34:14 +03:00
|
|
|
(void*)this,
|
2002-01-30 00:22:13 +03:00
|
|
|
&aEnum);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-03-05 11:06:25 +03:00
|
|
|
*aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
|
2002-01-30 00:22:13 +03:00
|
|
|
return NS_OK;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::EnumerateContractIDs(nsIEnumerator** aEnumerator)
|
2001-10-23 06:28:12 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_ASSERTION(aEnumerator != nsnull, "null ptr");
|
|
|
|
if(!aEnumerator)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
*aEnumerator = nsnull;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
nsresult rv;
|
|
|
|
if(!mPrePopulationDone)
|
|
|
|
{
|
|
|
|
rv = PlatformPrePopulateRegistry();
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
PLDHashTableEnumeratorImpl *aEnum;
|
|
|
|
rv = PL_NewDHashTableEnumerator(&mContractIDs,
|
|
|
|
ConvertContractIDKeyToString,
|
2002-02-13 23:34:14 +03:00
|
|
|
(void*)this,
|
2002-01-30 00:22:13 +03:00
|
|
|
&aEnum);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-03-05 11:06:25 +03:00
|
|
|
*aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
|
2001-10-23 06:28:12 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
// nsIComponentRegistrar
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::AutoRegister(nsIFile *aSpec)
|
2001-10-23 06:28:12 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
if (aSpec == nsnull)
|
|
|
|
return AutoRegisterImpl(0, aSpec);
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
PRBool directory;
|
|
|
|
aSpec->IsDirectory(&directory);
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
if (directory)
|
|
|
|
return AutoRegisterImpl(0, aSpec, PR_FALSE);
|
|
|
|
|
|
|
|
return AutoRegisterComponent(0, aSpec);
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::AutoUnregister(nsIFile *aSpec)
|
2001-10-23 06:28:12 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
// unregistering a complete directory is not implmeneted yet...FIX
|
|
|
|
if (aSpec == nsnull)
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
PRBool directory;
|
|
|
|
aSpec->IsDirectory(&directory);
|
|
|
|
|
|
|
|
if (directory)
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
return AutoUnregisterComponent(0, aSpec);
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::RegisterFactory(const nsCID & aClass,
|
|
|
|
const char *aClassName,
|
|
|
|
const char *aContractID,
|
|
|
|
nsIFactory *aFactory)
|
2001-10-23 06:28:12 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
return RegisterFactory(aClass,
|
|
|
|
aClassName,
|
|
|
|
aContractID,
|
|
|
|
aFactory,
|
|
|
|
PR_TRUE);
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::RegisterFactoryLocation(const nsCID & aClass,
|
|
|
|
const char *aClassName,
|
|
|
|
const char *aContractID,
|
|
|
|
nsIFile *aFile,
|
|
|
|
const char *loaderStr,
|
|
|
|
const char *aType)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
nsXPIDLCString registryName;
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
if (!loaderStr)
|
|
|
|
{
|
|
|
|
nsresult rv = RegistryLocationForSpec(aFile, getter_Copies(registryName));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1999-08-09 09:02:25 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
nsresult rv;
|
|
|
|
rv = RegisterComponentWithType(aClass,
|
|
|
|
aClassName,
|
|
|
|
aContractID,
|
|
|
|
aFile,
|
2002-01-30 06:51:47 +03:00
|
|
|
(loaderStr ? loaderStr : registryName.get()),
|
2002-01-30 00:22:13 +03:00
|
|
|
PR_TRUE,
|
|
|
|
PR_TRUE,
|
|
|
|
(aType ? aType : nativeComponentType) );
|
1999-08-09 09:02:25 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID & aClass,
|
|
|
|
nsIFile *aFile)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
return UnregisterComponentSpec(aClass, aFile);
|
|
|
|
}
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
|
|
|
|
PRBool *_retval)
|
|
|
|
{
|
|
|
|
return IsRegistered(aClass, _retval);
|
|
|
|
}
|
1999-09-05 10:27:42 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::IsContractIDRegistered(const char *aClass,
|
|
|
|
PRBool *_retval)
|
|
|
|
{
|
|
|
|
nsFactoryEntry *entry = GetFactoryEntry(aClass);
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
if (!entry || entry == kNonExistentContractID)
|
|
|
|
*_retval = PR_FALSE;
|
|
|
|
else
|
|
|
|
*_retval = PR_TRUE;
|
2001-10-23 06:28:12 +04:00
|
|
|
return NS_OK;
|
1999-08-09 09:02:25 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2001-10-23 06:28:12 +04:00
|
|
|
NS_ASSERTION(aEnumerator != nsnull, "null ptr");
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
if(!aEnumerator)
|
1999-08-09 09:02:25 +04:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
*aEnumerator = nsnull;
|
1999-08-09 09:02:25 +04:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
if(!mPrePopulationDone)
|
|
|
|
{
|
|
|
|
rv = PlatformPrePopulateRegistry();
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
PLDHashTableEnumeratorImpl *aEnum;
|
|
|
|
rv = PL_NewDHashTableEnumerator(&mFactories,
|
|
|
|
ConvertFactoryEntryToCID,
|
2002-02-13 23:34:14 +03:00
|
|
|
(void*)this,
|
2002-01-30 00:22:13 +03:00
|
|
|
&aEnum);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2002-03-05 11:06:25 +03:00
|
|
|
*aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
|
2002-01-30 00:22:13 +03:00
|
|
|
return NS_OK;
|
1999-08-09 09:02:25 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2001-10-23 06:28:12 +04:00
|
|
|
NS_ASSERTION(aEnumerator != nsnull, "null ptr");
|
|
|
|
if(!aEnumerator)
|
1999-08-09 09:02:25 +04:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
2001-10-23 06:28:12 +04:00
|
|
|
*aEnumerator = nsnull;
|
1999-08-09 09:02:25 +04:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
if(!mPrePopulationDone)
|
|
|
|
{
|
|
|
|
rv = PlatformPrePopulateRegistry();
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
PLDHashTableEnumeratorImpl *aEnum;
|
|
|
|
rv = PL_NewDHashTableEnumerator(&mContractIDs,
|
|
|
|
ConvertContractIDKeyToString,
|
2002-02-13 23:34:14 +03:00
|
|
|
(void*)this,
|
2002-01-30 00:22:13 +03:00
|
|
|
&aEnum);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2002-03-05 11:06:25 +03:00
|
|
|
*aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
|
2002-01-30 00:22:13 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-01-12 01:54:46 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::CIDToContractID(const nsCID & aClass,
|
|
|
|
char **_retval)
|
2000-01-12 01:54:46 +03:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
return CLSIDToContractID(aClass,
|
|
|
|
nsnull,
|
|
|
|
_retval);
|
2000-01-12 01:54:46 +03:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
|
|
|
|
nsCID * *_retval)
|
2001-08-30 18:10:41 +04:00
|
|
|
{
|
2002-01-30 00:22:13 +03:00
|
|
|
*_retval = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
|
2002-04-08 04:18:14 +04:00
|
|
|
if (!*_retval)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
nsresult rv = ContractIDToClassID(aContractID, *_retval);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
nsMemory::Free(*_retval);
|
|
|
|
*_retval = nsnull;
|
|
|
|
}
|
|
|
|
return rv;
|
2001-08-30 18:10:41 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
// end nsIComponentRegistrar
|
2001-08-30 18:10:41 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Static Access Functions
|
1999-03-09 12:44:27 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
NS_COM nsresult
|
|
|
|
NS_GetGlobalComponentManager(nsIComponentManager* *result)
|
|
|
|
{
|
2001-12-19 03:12:41 +03:00
|
|
|
#ifdef DEBUG_dougt
|
|
|
|
// NS_WARNING("DEPRECATED FUNCTION: Use NS_GetComponentManager");
|
|
|
|
#endif
|
1999-03-24 02:28:32 +03:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (nsComponentManagerImpl::gComponentManager == nsnull)
|
1999-03-24 02:28:32 +03:00
|
|
|
{
|
|
|
|
// XPCOM needs initialization.
|
2001-10-16 07:35:52 +04:00
|
|
|
rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
1999-03-24 02:28:32 +03:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
// NO ADDREF since this is never intended to be released.
|
2001-12-19 03:12:41 +03:00
|
|
|
// See nsComponentManagerObsolete.h for the reason for such
|
|
|
|
// casting uglyness
|
|
|
|
*result = (nsIComponentManager*)(void*)(nsIComponentManagerObsolete*) nsComponentManagerImpl::gComponentManager;
|
1999-03-24 02:28:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2001-10-16 07:35:52 +04:00
|
|
|
NS_COM nsresult
|
2001-12-19 03:12:41 +03:00
|
|
|
NS_GetComponentManager(nsIComponentManager* *result)
|
2001-10-16 07:35:52 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (nsComponentManagerImpl::gComponentManager == nsnull)
|
2001-10-16 07:35:52 +04:00
|
|
|
{
|
|
|
|
// XPCOM needs initialization.
|
|
|
|
rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2001-12-19 03:12:41 +03:00
|
|
|
|
|
|
|
*result = NS_STATIC_CAST(nsIComponentManager*,
|
2001-10-16 07:35:52 +04:00
|
|
|
nsComponentManagerImpl::gComponentManager);
|
|
|
|
NS_IF_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-12-19 03:12:41 +03:00
|
|
|
NS_COM nsresult
|
|
|
|
NS_GetServiceManager(nsIServiceManager* *result)
|
2001-09-07 01:13:11 +04:00
|
|
|
{
|
2001-12-19 03:12:41 +03:00
|
|
|
nsresult rv = NS_OK;
|
2001-09-07 01:13:11 +04:00
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (nsComponentManagerImpl::gComponentManager == nsnull)
|
2001-12-19 03:12:41 +03:00
|
|
|
{
|
|
|
|
// XPCOM needs initialization.
|
|
|
|
rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
|
|
|
}
|
2001-09-07 01:13:11 +04:00
|
|
|
|
2001-12-19 03:12:41 +03:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-09-07 01:13:11 +04:00
|
|
|
|
|
|
|
|
2001-12-19 03:12:41 +03:00
|
|
|
*result = NS_STATIC_CAST(nsIServiceManager*,
|
|
|
|
nsComponentManagerImpl::gComponentManager);
|
|
|
|
NS_IF_ADDREF(*result);
|
|
|
|
return NS_OK;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
NS_COM nsresult
|
|
|
|
NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
2002-04-16 02:33:03 +04:00
|
|
|
if (nsComponentManagerImpl::gComponentManager == nsnull)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
|
|
|
// XPCOM needs initialization.
|
|
|
|
rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
*result = NS_STATIC_CAST(nsIComponentRegistrar*,
|
|
|
|
nsComponentManagerImpl::gComponentManager);
|
|
|
|
NS_IF_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|