bug 94883 nsCreateInstanceByContractID() performance improvement

This commit is contained in:
dp@netscape.com
2001-08-21 22:42:35 +00:00
parent 1e95086105
commit 10f457b697
2 changed files with 226 additions and 149 deletions

View File

@@ -116,10 +116,9 @@ const static char XPCOM_ABSCOMPONENT_PREFIX[] = "abs:";
const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:"; const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:";
const char XPCOM_LIB_PREFIX[] = "lib:"; const char XPCOM_LIB_PREFIX[] = "lib:";
// We define a CID that is used to indicate the non-existence of a // Nonexistent factory entry
// contractid in the hash table. // This is used to mark non-existent contractid mappings
#define NS_NO_CID { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } static nsFactoryEntry * kNonExistentContractID = (nsFactoryEntry*) 1;
static NS_DEFINE_CID(kNoCID, NS_NO_CID);
// Build is using USE_NSREG to turn off xpcom using registry // Build is using USE_NSREG to turn off xpcom using registry
// but internally we use USE_REGISTRY. Map them propertly. // but internally we use USE_REGISTRY. Map them propertly.
@@ -204,8 +203,6 @@ nsCreateInstanceFromCategory::operator()( const nsIID& aIID,
PRBool PR_CALLBACK PRBool PR_CALLBACK
nsFactoryEntry_Destroy(nsHashKey *aKey, void *aData, void* closure); nsFactoryEntry_Destroy(nsHashKey *aKey, void *aData, void* closure);
PRBool PR_CALLBACK
nsCID_Destroy(nsHashKey *aKey, void *aData, void* closure);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// nsFactoryEntry // nsFactoryEntry
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -236,6 +233,24 @@ nsFactoryEntry::~nsFactoryEntry(void)
loader = 0; loader = 0;
} }
nsresult
nsFactoryEntry::ReInit(const nsCID &aClass, const char *aLocation,
const char *aType, nsIComponentLoader *aLoader)
{
cid = aClass;
location = aLocation;
type = aType;
loader = aLoader;
return NS_OK;
}
nsresult
nsFactoryEntry::ReInit(const nsCID &aClass, nsIFactory *aFactory)
{
cid = aClass;
factory = aFactory;
return NS_OK;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// nsComponentManagerImpl // nsComponentManagerImpl
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -258,16 +273,6 @@ nsFactoryEntry_Destroy(nsHashKey *aKey, void *aData, void* closure)
return PR_TRUE; return PR_TRUE;
} }
PRBool
nsCID_Destroy(nsHashKey *aKey, void *aData, void* closure)
{
nsCID* entry = NS_STATIC_CAST(nsCID*, aData);
// nasty hack. We "know" that kNoCID was entered into the hash table.
if (entry != &kNoCID)
delete entry;
return PR_TRUE;
}
nsresult nsComponentManagerImpl::Init(void) nsresult nsComponentManagerImpl::Init(void)
{ {
PR_ASSERT(mShuttingDown != NS_SHUTDOWN_INPROGRESS); PR_ASSERT(mShuttingDown != NS_SHUTDOWN_INPROGRESS);
@@ -291,9 +296,11 @@ nsresult nsComponentManagerImpl::Init(void)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
if (mContractIDs == NULL) { if (mContractIDs == NULL) {
// No destroy function for these as they hold weak references to the factory entry.
// The owning ref is from the mFactories hash table.
mContractIDs = new nsObjectHashtable(nsnull, nsnull, // should never be copied mContractIDs = new nsObjectHashtable(nsnull, nsnull, // should never be copied
nsCID_Destroy, nsnull, nsnull, nsnull,
256, /* Thread Safe */ PR_TRUE); 256, /* Thread Safe */ PR_TRUE);
if (mContractIDs == NULL) if (mContractIDs == NULL)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@@ -920,17 +927,14 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
getter_Copies(cidString)); getter_Copies(cidString));
if (NS_FAILED(rv)) continue; if (NS_FAILED(rv)) continue;
nsCID *aClass = new nsCID(); nsCID aClass;
if (!aClass) continue; // Protect against out of memory. if (!(aClass.Parse(cidString)))
if (!(aClass->Parse(cidString)))
{ {
delete aClass;
continue; continue;
} }
// put the {contractid, Cid} mapping into our map // put the {contractid, Cid} mapping into our map
nsCStringKey key(contractidString); HashContractID(contractidString, aClass);
mContractIDs->Put(&key, aClass);
// printf("Populating [ %s, %s ]\n", cidString, contractidString); // printf("Populating [ %s, %s ]\n", cidString, contractidString);
} }
@@ -946,34 +950,46 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
// HashContractID // HashContractID
// //
nsresult nsresult
nsComponentManagerImpl::HashContractID(const char *aContractID, const nsCID &aClass) 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)
{ {
if(!aContractID) if(!aContractID)
{ {
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
} }
nsCStringKey key(aContractID); // Find the factory entry corresponding to the CID.
nsCID* cid = (nsCID*) mContractIDs->Get(&key); nsFactoryEntry *entry = GetFactoryEntry(aClass, cidKey);
if (cid) if (!entry) {
{ // Non existent. We use the special kNonExistentContractID to mark
if (cid == &kNoCID) // that this contractid does not have a mapping.
{ entry = kNonExistentContractID;
// we don't delete this ptr as it's static (ugh)
}
else
{
delete cid;
}
} }
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;
cid = new nsCID(aClass); nsCStringKey key(aContractID);
if (!cid) mContractIDs->Put(&key, fe);
{
return NS_ERROR_OUT_OF_MEMORY;
}
mContractIDs->Put(&key, cid);
return NS_OK; return NS_OK;
} }
@@ -1011,24 +1027,71 @@ nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
return NS_OK; return NS_OK;
} }
nsFactoryEntry *
nsComponentManagerImpl::GetFactoryEntry(const char *aContractID, int checkRegistry)
{
nsCStringKey key(aContractID);
nsFactoryEntry *fe = (nsFactoryEntry *) mContractIDs->Get(&key);
#ifdef USE_REGISTRY
if (!fe)
{
if (checkRegistry < 0) {
// default
checkRegistry = !mPrePopulationDone;
}
if (checkRegistry)
{
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 * nsFactoryEntry *
nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass, PRBool checkRegistry) nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass, int checkRegistry)
{ {
nsIDKey key(aClass); nsIDKey cidKey(aClass);
nsFactoryEntry *entry = (nsFactoryEntry*) mFactories->Get(&key); return GetFactoryEntry(aClass, cidKey, checkRegistry);
}
nsFactoryEntry *
nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass, nsIDKey &cidKey, int checkRegistry)
{
nsFactoryEntry *entry = (nsFactoryEntry*) mFactories->Get(&cidKey);
#ifdef USE_REGISTRY #ifdef USE_REGISTRY
if (!entry) if (!entry)
{ {
if (checkRegistry) if (checkRegistry < 0) {
{ // default
checkRegistry = !mPrePopulationDone;
}
if (checkRegistry) {
nsresult rv = PlatformFind(aClass, &entry); nsresult rv = PlatformFind(aClass, &entry);
// If we got one, cache it in our hashtable // If we got one, cache it in our hashtable
if (NS_SUCCEEDED(rv)) if (NS_SUCCEEDED(rv))
{ {
mFactories->Put(&key, entry); mFactories->Put(&cidKey, entry);
} }
} }
} }
@@ -1037,6 +1100,7 @@ nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass, PRBool checkRegistr
return (entry); return (entry);
} }
/** /**
* FindFactory() * FindFactory()
* *
@@ -1052,7 +1116,7 @@ nsComponentManagerImpl::FindFactory(const nsCID &aClass,
{ {
PR_ASSERT(aFactory != NULL); PR_ASSERT(aFactory != NULL);
nsFactoryEntry *entry = GetFactoryEntry(aClass, !mPrePopulationDone); nsFactoryEntry *entry = GetFactoryEntry(aClass);
if (!entry) if (!entry)
return NS_ERROR_FACTORY_NOT_REGISTERED; return NS_ERROR_FACTORY_NOT_REGISTERED;
@@ -1060,6 +1124,21 @@ nsComponentManagerImpl::FindFactory(const nsCID &aClass,
return entry->GetFactory(aFactory, this); return entry->GetFactory(aFactory, this);
} }
nsresult
nsComponentManagerImpl::FindFactory(const char *contractID,
nsIFactory **aFactory)
{
PR_ASSERT(aFactory != NULL);
nsFactoryEntry *entry = GetFactoryEntry(contractID);
if (!entry || entry == kNonExistentContractID)
return NS_ERROR_FACTORY_NOT_REGISTERED;
return entry->GetFactory(aFactory, this);
}
/** /**
* GetClassObject() * GetClassObject()
* *
@@ -1113,41 +1192,11 @@ nsComponentManagerImpl::ContractIDToClassID(const char *aContractID, nsCID *aCla
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED; nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
#ifdef USE_REGISTRY nsFactoryEntry *fe = GetFactoryEntry(aContractID);
nsCStringKey key(aContractID); if (fe && fe != kNonExistentContractID) {
nsCID* cid = (nsCID*) mContractIDs->Get(&key); *aClass = fe->cid;
if (cid) { res = NS_OK;
if (cid == &kNoCID) {
// we've already tried to map this ContractID to a CLSID, and found
// that there _was_ no such mapping in the registry.
}
else {
*aClass = *cid;
res = NS_OK;
}
} }
else {
// This is the first time someone has asked for this
// ContractID. Go to the registry to find the CID.
if (!mPrePopulationDone)
res = PlatformContractIDToCLSID(aContractID, aClass);
if (NS_SUCCEEDED(res)) {
// Found it. So put it into the cache.
cid = new nsCID(*aClass);
if (!cid)
return NS_ERROR_OUT_OF_MEMORY;
mContractIDs->Put(&key, cid);
}
else {
// Didn't find it. Put a special CID in the cache so we
// don't need to hit the registry on subsequent requests
// for the same ContractID.
mContractIDs->Put(&key, (void *)&kNoCID);
}
}
#endif /* USE_REGISTRY */
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS)) { if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS)) {
char *buf = 0; char *buf = 0;
@@ -1264,10 +1313,41 @@ nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
const nsIID &aIID, const nsIID &aIID,
void **aResult) void **aResult)
{ {
nsCID clsid; // test this first, since there's no point in creating a component during
nsresult rv = ContractIDToClassID(aContractID, &clsid); // shutdown -- whether it's available or not would depend on the order it
if (NS_FAILED(rv)) return rv; // occurs in the list
return CreateInstance(clsid, aDelegate, aIID, aResult); if (gShuttingDown) {
// When processing shutdown, dont process new GetService() requests
#ifdef DEBUG_dp
NS_WARN_IF_FALSE(PR_FALSE, "Creating new instance on shutdown. Denied.");
#endif /* DEBUG_dp */
return NS_ERROR_UNEXPECTED;
}
if (aResult == NULL)
{
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
nsIFactory *factory = NULL;
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;
} }
/* /*
@@ -1422,7 +1502,8 @@ nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
nsFactoryEntry *entry = NULL; nsFactoryEntry *entry = NULL;
nsIDKey key(aClass); nsIDKey key(aClass);
entry = (nsFactoryEntry *)mFactories->Get(&key); entry = GetFactoryEntry(aClass, key,
0 /* dont check registry */);
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS)) if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{ {
@@ -1442,21 +1523,19 @@ nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
return NS_ERROR_FACTORY_EXISTS; return NS_ERROR_FACTORY_EXISTS;
} }
nsFactoryEntry *newEntry = new nsFactoryEntry(aClass, aFactory); if (entry) {
if (newEntry == NULL) entry->ReInit(aClass, aFactory);
return NS_ERROR_OUT_OF_MEMORY; }
else {
if (entry) { // aReplace implied by above check entry = new nsFactoryEntry(aClass, aFactory);
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, if (entry == NULL)
("\t\tdeleting old Factory Entry.")); return NS_ERROR_OUT_OF_MEMORY;
mFactories->RemoveAndDelete(&key); mFactories->Put(&key, entry);
entry = NULL;
} }
mFactories->Put(&key, newEntry);
// Update the ContractID->CLSID Map // Update the ContractID->CLSID Map
if (aContractID) { if (aContractID) {
nsresult rv = HashContractID(aContractID, aClass); nsresult rv = HashContractID(aContractID, entry);
if(NS_FAILED(rv)) { if(NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
("\t\tFactory register succeeded. " ("\t\tFactory register succeeded. "
@@ -1554,6 +1633,7 @@ nsComponentManagerImpl::RegisterComponentLib(const nsCID &aClass,
* or hand it to nsFactoryEntry. Common exit point ``out'' helps keep us * or hand it to nsFactoryEntry. Common exit point ``out'' helps keep us
* sane. * sane.
*/ */
nsresult nsresult
nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass, nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
const char *aClassName, const char *aClassName,
@@ -1564,12 +1644,9 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
const char *aType) const char *aType)
{ {
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsFactoryEntry* newEntry = nsnull;
nsIDKey key(aClass); nsIDKey key(aClass);
nsFactoryEntry *entry = GetFactoryEntry(aClass, !mPrePopulationDone); nsFactoryEntry *entry = GetFactoryEntry(aClass, !mPrePopulationDone);
nsCOMPtr<nsIComponentLoader> loader;
PRBool sanity;
// Normalize proid and classname // Normalize proid and classname
const char *contractID = (aContractID && *aContractID) ? aContractID : NULL; const char *contractID = (aContractID && *aContractID) ? aContractID : NULL;
@@ -1589,8 +1666,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
if (entry && !aReplace) { if (entry && !aReplace) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tFactory already registered.")); ("\t\tFactory already registered."));
rv = NS_ERROR_FACTORY_EXISTS; return NS_ERROR_FACTORY_EXISTS;
goto out;
} }
#ifdef USE_REGISTRY #ifdef USE_REGISTRY
@@ -1599,53 +1675,44 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
rv = AddComponentToRegistry(aClass, className, contractID, rv = AddComponentToRegistry(aClass, className, contractID,
aRegistryName, aType); aRegistryName, aType);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tadding %s %s to registry FAILED", className, contractID)); ("\t\tadding %s %s to registry FAILED", className, contractID));
goto out; return rv;
} }
} }
#endif #endif
nsCOMPtr<nsIComponentLoader> loader;
rv = GetLoaderForType(aType, getter_AddRefs(loader)); rv = GetLoaderForType(aType, getter_AddRefs(loader));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tgetting loader for %s FAILED\n", aType)); ("\t\tgetting loader for %s FAILED\n", aType));
goto out; return rv;
} }
newEntry = new nsFactoryEntry(aClass, aRegistryName, aType, loader); if (entry) {
if (!newEntry) { entry->ReInit(aClass, aRegistryName, aType, loader);
rv = NS_ERROR_OUT_OF_MEMORY; }
goto out; else {
entry = new nsFactoryEntry(aClass, aRegistryName, aType, loader);
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
mFactories->Put(&key, entry);
} }
if (entry) { // aReplace implicit from test above
delete entry;
}
/* unless the fabric of the universe bends, we'll get entry back */
sanity = (entry == mFactories->Put(&key, newEntry));
PR_ASSERT(sanity);
/* don't try to clean up, just drop everything and run */
if (!sanity)
return NS_ERROR_FACTORY_NOT_REGISTERED;
/* we've put the new entry in the hash table, so don't delete on error */
newEntry = nsnull;
// Update the ContractID->CLSID Map // Update the ContractID->CLSID Map
if (contractID if (contractID
#ifdef USE_REGISTRY #ifdef USE_REGISTRY
&& (mPrePopulationDone || !aPersist) && (mPrePopulationDone || !aPersist)
#endif #endif
) { ) {
rv = HashContractID(contractID, aClass); rv = HashContractID(contractID, entry);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tHashContractID(%s) FAILED\n", contractID)); ("\t\tHashContractID(%s) FAILED\n", contractID));
goto out; return rv;
} }
} }
// Let the loader do magic things now // Let the loader do magic things now
@@ -1655,17 +1722,12 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tloader->OnRegister FAILED for %s \"%s\" %s %s", aType, ("\t\tloader->OnRegister FAILED for %s \"%s\" %s %s", aType,
className, contractID, aRegistryName)); className, contractID, aRegistryName));
goto out; return rv;
} }
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS, PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
("\t\tRegisterComponentCommon() %s", ("\t\tRegisterComponentCommon() %s",
NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
out:
if (NS_FAILED(rv)) {
if (newEntry)
delete newEntry;
}
return rv; return rv;
} }
@@ -1789,7 +1851,8 @@ nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
nsIDKey key(aClass); nsIDKey key(aClass);
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED; nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
nsFactoryEntry *old = (nsFactoryEntry *) mFactories->Get(&key); nsFactoryEntry *old = GetFactoryEntry(aClass, key,
0 /* dont check registry */);
if (old != NULL) if (old != NULL)
{ {
if (old->factory.get() == aFactory) if (old->factory.get() == aFactory)
@@ -1821,7 +1884,8 @@ nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
// Remove any stored factory entries // Remove any stored factory entries
nsIDKey key(aClass); nsIDKey key(aClass);
nsFactoryEntry *entry = (nsFactoryEntry *) mFactories->Get(&key); nsFactoryEntry *entry = GetFactoryEntry(aClass, key,
0 /* dont check registry */);
if (entry && entry->location && PL_strcasecmp(entry->location, registryName)) if (entry && entry->location && PL_strcasecmp(entry->location, registryName))
{ {
mFactories->RemoveAndDelete(&key); mFactories->RemoveAndDelete(&key);
@@ -2200,7 +2264,7 @@ nsComponentManagerImpl::IsRegistered(const nsCID &aClass,
NS_ASSERTION(0, "null ptr"); NS_ASSERTION(0, "null ptr");
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
} }
*aRegistered = (nsnull != GetFactoryEntry(aClass, !mPrePopulationDone)); *aRegistered = (nsnull != GetFactoryEntry(aClass));
return NS_OK; return NS_OK;
} }

View File

@@ -84,14 +84,19 @@ protected:
const char *aType); const char *aType);
nsresult GetLoaderForType(const char *aType, nsresult GetLoaderForType(const char *aType,
nsIComponentLoader **aLoader); nsIComponentLoader **aLoader);
nsresult FindFactory(const char *contractID, nsIFactory **aFactory) ;
nsresult LoadFactory(nsFactoryEntry *aEntry, nsIFactory **aFactory); nsresult LoadFactory(nsFactoryEntry *aEntry, nsIFactory **aFactory);
nsFactoryEntry *GetFactoryEntry(const nsCID &aClass, PRBool checkRegistry);
nsFactoryEntry *GetFactoryEntry(const char *aContractID, int checkRegistry = -1);
nsFactoryEntry *GetFactoryEntry(const nsCID &aClass, int checkRegistry = -1);
nsFactoryEntry *GetFactoryEntry(const nsCID &aClass, nsIDKey &cidKey, int checkRegistry = -1);
nsresult SyncComponentsInDir(PRInt32 when, nsIFile *dirSpec); nsresult SyncComponentsInDir(PRInt32 when, nsIFile *dirSpec);
nsresult SelfRegisterDll(nsDll *dll); nsresult SelfRegisterDll(nsDll *dll);
nsresult SelfUnregisterDll(nsDll *dll); nsresult SelfUnregisterDll(nsDll *dll);
nsresult HashContractID(const char *acontractID, const nsCID &aClass); nsresult HashContractID(const char *acontractID, nsFactoryEntry *fe_ptr);
nsresult HashContractID(const char *acontractID, const nsCID &aClass, nsFactoryEntry **fe_ptr = NULL);
nsresult HashContractID(const char *acontractID, const nsCID &aClass, nsIDKey &cidKey, nsFactoryEntry **fe_ptr = NULL);
nsresult UnloadLibraries(nsIServiceManager *servmgr, PRInt32 when); nsresult UnloadLibraries(nsIServiceManager *servmgr, PRInt32 when);
// The following functions are the only ones that operate on the persistent // The following functions are the only ones that operate on the persistent
@@ -200,6 +205,11 @@ public:
nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory); nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory);
~nsFactoryEntry(); ~nsFactoryEntry();
nsresult ReInit(const nsCID &aClass, const char *location,
const char *aType, nsIComponentLoader *aLoader);
nsresult ReInit(const nsCID &aClass, nsIFactory *aFactory);
nsresult GetFactory(nsIFactory **aFactory, nsresult GetFactory(nsIFactory **aFactory,
nsComponentManagerImpl * mgr) { nsComponentManagerImpl * mgr) {
if (factory) { if (factory) {
@@ -208,6 +218,9 @@ public:
return NS_OK; return NS_OK;
} }
if (!type)
return NS_ERROR_FAILURE;
nsresult rv; nsresult rv;
if (!loader.get()) { if (!loader.get()) {
rv = mgr->GetLoaderForType(type, getter_AddRefs(loader)); rv = mgr->GetLoaderForType(type, getter_AddRefs(loader));