diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp index 632359ffc80..9be70475c4c 100644 --- a/xpcom/components/nsComponentManager.cpp +++ b/xpcom/components/nsComponentManager.cpp @@ -1770,56 +1770,35 @@ nsresult nsComponentManagerImpl::UnregisterComponentSpec(const nsCID &aClass, nsIFile *aLibrarySpec) { - char *aLibrary; - nsresult rv = aLibrarySpec->GetPath(&aLibrary); - if (NS_FAILED(rv)) - return NS_ERROR_INVALID_ARG; + nsXPIDLCString registryName; + nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName)); + if (NS_FAILED(rv)) return NS_ERROR_INVALID_ARG; - if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS)) - { - char *buf = aClass.ToString(); - PR_LogPrint("nsComponentManager: UnregisterComponentSpec(%s, %s)", buf, - aLibrary); - delete [] buf; - } - - nsIDKey key(aClass); - nsFactoryEntry *old = (nsFactoryEntry *) mFactories->Get(&key); - - nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED; - PR_EnterMonitor(mMon); - - if (old != NULL) + + // Remove any stored factory entries + nsIDKey key(aClass); + nsFactoryEntry *entry = (nsFactoryEntry *) mFactories->Get(&key); + if (entry && entry->location && PL_strcasecmp(entry->location, registryName)) { -#if 0 /* use nsFactoryEntry->location */ - if (old->dll->GetPersistentDescriptorString() != NULL && -#if defined(XP_UNIX) || defined(XP_BEOS) - PL_strcasecmp(old->dll->GetPersistentDescriptorString(), aLibrary) -#else - PL_strcmp(old->dll->GetPersistentDescriptorString(), aLibrary) -#endif - ) - { - mFactories->RemoveAndDelete(&key); - old = NULL; - res = NS_OK; - } -#ifdef USE_REGISTRY - char *cidString = aClass.ToString(); - res = PlatformUnregister(cidString, aLibrary); - delete [] cidString; -#endif -#endif + mFactories->RemoveAndDelete(&key); + entry = NULL; } + +#ifdef USE_REGISTRY + // Remove registry entries for this cid + char *cidString = aClass.ToString(); + rv = PlatformUnregister(cidString, registryName); + delete [] cidString; +#endif PR_ExitMonitor(mMon); PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, - ("nsComponentManager: ! Factory unregister %s.", - NS_SUCCEEDED(res) ? "succeeded" : "failed")); - - return res; + ("nsComponentManager: Factory unregister(%s) %s.", (const char *)registryName, + NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); + + return rv; } struct CanUnload_closure { @@ -2037,10 +2016,25 @@ AutoRegisterComponent_enumerate(nsHashKey *key, void *aData, void *aClosure) &didRegister); if (NS_SUCCEEDED(closure->status) && didRegister) - return PR_FALSE; - if (didRegister) - return PR_TRUE; - return PR_FALSE; + return PR_FALSE; // Stop enumeration as we are done + return PR_TRUE; +} + +static PRBool +AutoUnregisterComponent_enumerate(nsHashKey *key, void *aData, void *aClosure) +{ + PRBool didUnregister; + nsIComponentLoader *loader = (nsIComponentLoader *)aData; + struct AutoReg_closure *closure = + (struct AutoReg_closure *)aClosure; + + closure->status = loader->AutoUnregisterComponent(closure->when, + closure->spec, + &didUnregister); + if (NS_SUCCEEDED(closure->status) && didUnregister) + return PR_FALSE; // Stop enumeration as we are done + return PR_TRUE; // Let enumeration continue + } nsresult @@ -2064,6 +2058,24 @@ nsComponentManagerImpl::AutoRegisterComponent(PRInt32 when, } +nsresult +nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 when, + nsIFile *component) +{ + struct AutoReg_closure closure; + + /* XXX convert when to nsIComponentLoader::(when) properly */ + closure.when = (PRInt32)when; + closure.spec = component; + closure.status = NS_OK; + + mLoaders->Enumerate(AutoUnregisterComponent_enumerate, &closure); + + return NS_FAILED(closure.status) + ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK; + +} + nsresult nsComponentManagerImpl::IsRegistered(const nsCID &aClass, PRBool *aRegistered) diff --git a/xpcom/components/nsComponentManagerUtils.h b/xpcom/components/nsComponentManagerUtils.h index c265f2bcd8f..a57f95ff9c2 100644 --- a/xpcom/components/nsComponentManagerUtils.h +++ b/xpcom/components/nsComponentManagerUtils.h @@ -161,6 +161,7 @@ public: // in the default components directory. static nsresult AutoRegister(PRInt32 when, nsIFile* directory); static nsresult AutoRegisterComponent(PRInt32 when, nsIFile *component); + static nsresult AutoUnregisterComponent(PRInt32 when, nsIFile *component); // Is the given CID currently registered? static nsresult IsRegistered(const nsCID &aClass, diff --git a/xpcom/components/nsIComponentLoader.idl b/xpcom/components/nsIComponentLoader.idl index ee3943d0dae..cb6cb3b8318 100644 --- a/xpcom/components/nsIComponentLoader.idl +++ b/xpcom/components/nsIComponentLoader.idl @@ -1,4 +1,4 @@ -/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.1 (the "NPL"); you may not use this file except in @@ -68,6 +68,13 @@ interface nsIComponentLoader : nsISupports { */ boolean autoRegisterComponent(in long aWhen, in nsIFile aComponent); + /** + * AutoUnregister the given component. + * Returns true if the component was unregistered, false if it coudln't + * attempt to unregister the component (not found, wrong type). + */ + boolean autoUnregisterComponent(in long aWhen, in nsIFile aComponent); + /** * Register any deferred (NS_ERROR_FACTORY_REGISTER_AGAIN) components. * Return registered-any-components? diff --git a/xpcom/components/nsIComponentManager.idl b/xpcom/components/nsIComponentManager.idl index a1c656e6c5e..863f2b24504 100644 --- a/xpcom/components/nsIComponentManager.idl +++ b/xpcom/components/nsIComponentManager.idl @@ -86,6 +86,7 @@ interface nsIComponentManager : nsISupports void autoRegister(in long when, in nsIFile directory); void autoRegisterComponent(in long when, in nsIFile component); + void autoUnregisterComponent(in long when, in nsIFile component); boolean isRegistered(in nsCIDRef aClass); nsIEnumerator enumerateCLSIDs(); diff --git a/xpcom/components/nsNativeComponentLoader.cpp b/xpcom/components/nsNativeComponentLoader.cpp index c9b997c28de..b33a430f83c 100644 --- a/xpcom/components/nsNativeComponentLoader.cpp +++ b/xpcom/components/nsNativeComponentLoader.cpp @@ -579,9 +579,6 @@ nsNativeComponentLoader::DumpLoadError(nsDll *dll, nsresult nsNativeComponentLoader::SelfUnregisterDll(nsDll *dll) { - // Precondition: dll is not loaded - PR_ASSERT(dll->IsLoaded() == PR_FALSE); - nsIServiceManager* serviceMgr = NULL; nsresult res = nsServiceManager::GetGlobalServiceManager(&serviceMgr); if (NS_FAILED(res)) return res; @@ -623,10 +620,39 @@ nsNativeComponentLoader::SelfUnregisterDll(nsDll *dll) } } #endif /* OBSOLETE_MODULE_LOADING */ - dll->Unload(); return res; } +nsresult +nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when, + nsIFile *component, + PRBool *unregistered) +{ + nsresult rv = NS_ERROR_FAILURE; + + nsXPIDLCString persistentDescriptor; + rv = mCompMgr->RegistryLocationForSpec(component, + getter_Copies(persistentDescriptor)); + if (NS_FAILED(rv)) return rv; + + nsDll *dll = NULL; + PRInt64 mod = LL_Zero(), size = LL_Zero(); + rv = CreateDll(component, persistentDescriptor, &mod, &size, &dll); + if (NS_FAILED(rv) || dll == NULL) return rv; + + rv = SelfUnregisterDll(dll); + + // Remove any autoreg info about this dll + if (NS_SUCCEEDED(rv)) + RemoveRegistryDllInfo(persistentDescriptor); + + PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, + ("nsNativeComponentLoader: AutoUnregistration for %s %s.", + (NS_FAILED(rv) ? "FAILED" : "succeeded"), dll->GetDisplayPath())); + return rv; +} + + nsresult nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when, nsIFile *component, @@ -940,6 +966,12 @@ nsNativeComponentLoader::SetRegistryDllInfo(const char *aLocation, return rv; } +nsresult +nsNativeComponentLoader::RemoveRegistryDllInfo(const char *aLocation) +{ + return mRegistry->RemoveSubtree(mXPCOMKey, aLocation); +} + // // CreateDll // The only way to create a dll or get it from the dll cache. This will diff --git a/xpcom/components/nsNativeComponentLoader.h b/xpcom/components/nsNativeComponentLoader.h index 8625d41196c..957a642e243 100644 --- a/xpcom/components/nsNativeComponentLoader.h +++ b/xpcom/components/nsNativeComponentLoader.h @@ -64,6 +64,7 @@ class nsNativeComponentLoader : public nsIComponentLoader { PRInt64 *fileSize); nsresult SetRegistryDllInfo(const char *aLocation, PRInt64 *lastModifiedTime, PRInt64 *fileSize); + nsresult RemoveRegistryDllInfo(const char *aLocation); nsresult GetFactoryFromModule(nsDll *aDll, const nsCID &aCID, nsIFactory **aFactory); /* obsolete! already! */ diff --git a/xpcom/components/nsRepository.cpp b/xpcom/components/nsRepository.cpp index fa0603d8125..84e11bfb18c 100644 --- a/xpcom/components/nsRepository.cpp +++ b/xpcom/components/nsRepository.cpp @@ -210,6 +210,16 @@ nsComponentManager::AutoRegisterComponent(PRInt32 when, return cm->AutoRegisterComponent(when, fullname); } +nsresult +nsComponentManager::AutoUnregisterComponent(PRInt32 when, + nsIFile *fullname) +{ + nsIComponentManager* cm; + nsresult rv = NS_GetGlobalComponentManager(&cm); + if (NS_FAILED(rv)) return rv; + return cm->AutoUnregisterComponent(when, fullname); +} + nsresult nsComponentManager::IsRegistered(const nsCID &aClass, PRBool *aRegistered) diff --git a/xpcom/glue/nsComponentManagerUtils.h b/xpcom/glue/nsComponentManagerUtils.h index c265f2bcd8f..a57f95ff9c2 100644 --- a/xpcom/glue/nsComponentManagerUtils.h +++ b/xpcom/glue/nsComponentManagerUtils.h @@ -161,6 +161,7 @@ public: // in the default components directory. static nsresult AutoRegister(PRInt32 when, nsIFile* directory); static nsresult AutoRegisterComponent(PRInt32 when, nsIFile *component); + static nsresult AutoUnregisterComponent(PRInt32 when, nsIFile *component); // Is the given CID currently registered? static nsresult IsRegistered(const nsCID &aClass,