Bug 296430, part "xpcom" - Add a category for directory-service providers which will be registered after autoregistration but before xpcom-startup r=darin a=asa

This commit is contained in:
bsmedberg%covad.net 2005-06-07 19:35:20 +00:00
Родитель 4d1c86ee60
Коммит 591acc2faa
5 изменённых файлов: 152 добавлений и 67 удалений

Просмотреть файл

@ -258,6 +258,56 @@ NS_Realloc(void* ptr, PRSize size);
extern "C" NS_COM void
NS_Free(void* ptr);
/**
* Categories (in the category manager service) used by XPCOM:
*/
/**
* A category which is read after component registration but before
* the "xpcom-startup" notifications. Each category entry is treated
* as the contract ID of a service which implements
* nsIDirectoryServiceProvider. Each directory service provider is
* installed in the global directory service.
*
* @status FROZEN
*/
#define XPCOM_DIRECTORY_PROVIDER_CATEGORY "xpcom-directory-providers"
/**
* A category which is read after component registration but before
* NS_InitXPCOM2 returns. Each category entry is treated as the contractID of
* a service: each service is instantiated, and if it implements nsIObserver
* the nsIObserver.observe method is called with the "xpcom-startup" topic.
*
* @status FROZEN
*/
#define NS_XPCOM_STARTUP_CATEGORY "xpcom-startup"
/**
* Observer topics (in the observer service) used by XPCOM:
*/
/**
* At XPCOM startup after component registration is complete, the
* following topic is notified. In order to receive this notification,
* component must register their contract ID in the category manager,
*
* @see NS_XPCOM_STARTUP_CATEGORY
* @status FROZEN
*/
#define NS_XPCOM_STARTUP_OBSERVER_ID "xpcom-startup"
/**
* At XPCOM shutdown, this topic is notified. All components must
* release any interface references to objects in other modules when
* this topic is notified.
*
* @status FROZEN
*/
#define NS_XPCOM_SHUTDOWN_OBSERVER_ID "xpcom-shutdown"
extern "C" NS_COM nsresult
NS_GetDebug(nsIDebug* *result);

Просмотреть файл

@ -242,18 +242,10 @@ RegisterGenericFactory(nsIComponentRegistrar* registrar,
static PRBool CheckUpdateFile()
{
nsresult rv;
nsCOMPtr<nsIProperties> directoryService;
nsDirectoryService::Create(nsnull,
NS_GET_IID(nsIProperties),
getter_AddRefs(directoryService));
if (!directoryService)
return PR_FALSE;
nsCOMPtr<nsIFile> file;
rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(file));
rv = nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(file));
if (NS_FAILED(rv)) {
NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
@ -268,9 +260,9 @@ static PRBool CheckUpdateFile()
return PR_FALSE;
nsCOMPtr<nsIFile> compregFile;
rv = directoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
NS_GET_IID(nsIFile),
getter_AddRefs(compregFile));
rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
NS_GET_IID(nsIFile),
getter_AddRefs(compregFile));
if (NS_FAILED(rv)) {
@ -290,7 +282,6 @@ static PRBool CheckUpdateFile()
nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
nsIProperties *gDirectoryService = NULL;
PRBool gXPCOMShuttingDown = PR_FALSE;
// For each class that wishes to support nsIClassInfo, add a line like this
@ -481,17 +472,7 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
StartupSpecialSystemDirectory();
// Start the directory service so that the component manager init can use it.
rv = nsDirectoryService::Create(nsnull,
NS_GET_IID(nsIProperties),
(void**)&gDirectoryService);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIDirectoryService> dirService = do_QueryInterface(gDirectoryService, &rv);
if (NS_FAILED(rv))
return rv;
rv = dirService->Init();
rv = nsDirectoryService::RealInit();
if (NS_FAILED(rv))
return rv;
@ -513,23 +494,23 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
rv = binDirectory->IsDirectory(&value);
if (NS_SUCCEEDED(rv) && value) {
gDirectoryService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory);
nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory);
binDirectory->Clone(getter_AddRefs(xpcomLib));
}
}
else {
gDirectoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(xpcomLib));
nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(xpcomLib));
}
if (xpcomLib) {
xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
gDirectoryService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
}
if (appFileLocationProvider) {
rv = dirService->RegisterProvider(appFileLocationProvider);
rv = nsDirectoryService::gService->RegisterProvider(appFileLocationProvider);
if (NS_FAILED(rv)) return rv;
}
@ -621,9 +602,9 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
#ifdef DEBUG_dougt
printf("start - Registering GRE components\n");
#endif
rv = gDirectoryService->Get(NS_GRE_COMPONENT_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(greDir));
rv = nsDirectoryService::gService->Get(NS_GRE_COMPONENT_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(greDir));
if (NS_FAILED(rv)) {
NS_ERROR("Could not get GRE components directory!");
return rv;
@ -653,9 +634,9 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
//
nsCOMPtr<nsISimpleEnumerator> dirList;
gDirectoryService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
NS_GET_IID(nsISimpleEnumerator),
getter_AddRefs(dirList));
nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
NS_GET_IID(nsISimpleEnumerator),
getter_AddRefs(dirList));
if (dirList) {
PRBool hasMore;
while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
@ -675,9 +656,9 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
// Make sure the compreg file's mod time is current.
nsCOMPtr<nsIFile> compregFile;
rv = gDirectoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
NS_GET_IID(nsIFile),
getter_AddRefs(compregFile));
rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
NS_GET_IID(nsIFile),
getter_AddRefs(compregFile));
compregFile->SetLastModifiedTime(PR_Now() / 1000);
}
@ -685,6 +666,11 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
nsIInterfaceInfoManager* iim = XPTI_GetInterfaceInfoManager();
NS_IF_RELEASE(iim);
// After autoreg, but before we actually instantiate any components,
// add any services listed in the "xpcom-directory-providers" category
// to the directory service.
nsDirectoryService::gService->RegisterCategoryProviders();
// Notify observers of xpcom autoregistration start
NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_OBSERVER_ID,
nsnull,
@ -813,7 +799,7 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
nsProxyObjectManager::Shutdown();
// Release the directory service
NS_IF_RELEASE(gDirectoryService);
NS_IF_RELEASE(nsDirectoryService::gService);
// Shutdown nsLocalFile string conversion
NS_ShutdownLocalFile();

Просмотреть файл

@ -101,12 +101,6 @@ interface nsIServiceManager : nsISupports
*/
#define NS_ERROR_SERVICE_IN_USE NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 23)
// Observing xpcom startup. If you component has not been created, it will be.
#define NS_XPCOM_STARTUP_OBSERVER_ID "xpcom-startup"
// Observing xpcom shutdown
#define NS_XPCOM_SHUTDOWN_OBSERVER_ID "xpcom-shutdown"
// Observing xpcom autoregistration. Topics will be 'start' and 'stop'.
#define NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID "xpcom-autoregistration"

Просмотреть файл

@ -38,6 +38,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsLocalFile.h"
@ -45,6 +46,10 @@
#include "nsStaticAtom.h"
#include "nsEnumeratorUtils.h"
#include "nsICategoryManager.h"
#include "nsISimpleEnumerator.h"
#include "nsIStringEnumerator.h"
#if defined(XP_MAC)
#include <Folders.h>
#include <Files.h>
@ -120,7 +125,7 @@ nsDirectoryService::GetCurrentProcessDirectory(nsILocalFile** aFile)
*aFile = nsnull;
// Set the component registry location:
if (!mService)
if (!gService)
return NS_ERROR_FAILURE;
nsresult rv;
@ -399,7 +404,7 @@ nsIAtom* nsDirectoryService::sSystemDirectory = nsnull;
#endif
nsDirectoryService* nsDirectoryService::mService = nsnull;
nsDirectoryService* nsDirectoryService::gService = nsnull;
nsDirectoryService::nsDirectoryService() :
mHashtable(256, PR_TRUE)
@ -410,13 +415,14 @@ NS_METHOD
nsDirectoryService::Create(nsISupports *outer, REFNSIID aIID, void **aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
if (!mService)
NS_ENSURE_NO_AGGREGATION(outer);
if (!gService)
{
mService = new nsDirectoryService();
if (!mService)
return NS_ERROR_OUT_OF_MEMORY;
return NS_ERROR_NOT_INITIALIZED;
}
return mService->QueryInterface(aIID, aResult);
return gService->QueryInterface(aIID, aResult);
}
static const nsStaticAtom directory_atoms[] = {
@ -503,13 +509,27 @@ static const nsStaticAtom directory_atoms[] = {
#endif
};
nsresult
NS_IMETHODIMP
nsDirectoryService::Init()
{
NS_NOTREACHED("Don't call me, I was for internal use only!");
return NS_OK;
}
nsresult
nsDirectoryService::RealInit()
{
NS_ASSERTION(!gService, "Mustn't initialize twice!");
nsresult rv;
rv = NS_NewISupportsArray(getter_AddRefs(mProviders));
if (NS_FAILED(rv)) return rv;
nsRefPtr<nsDirectoryService> self = new nsDirectoryService();
if (!self)
return NS_ERROR_OUT_OF_MEMORY;
rv = NS_NewISupportsArray(getter_AddRefs(self->mProviders));
if (NS_FAILED(rv))
return rv;
NS_RegisterStaticAtoms(directory_atoms, NS_ARRAY_LENGTH(directory_atoms));
@ -518,9 +538,12 @@ nsDirectoryService::Init()
if (!defaultProvider)
return NS_ERROR_OUT_OF_MEMORY;
// AppendElement returns PR_TRUE for success.
rv = mProviders->AppendElement(defaultProvider) ? NS_OK : NS_ERROR_FAILURE;
rv = self->mProviders->AppendElement(defaultProvider) ? NS_OK : NS_ERROR_FAILURE;
if (NS_FAILED(rv))
return rv;
return rv;
self.swap(gService);
return NS_OK;
}
PRBool
@ -533,9 +556,6 @@ nsDirectoryService::ReleaseValues(nsHashKey* key, void* data, void* closure)
nsDirectoryService::~nsDirectoryService()
{
// clear the global
mService = nsnull;
}
NS_IMPL_THREADSAFE_ISUPPORTS4(nsDirectoryService, nsIProperties, nsIDirectoryService, nsIDirectoryServiceProvider, nsIDirectoryServiceProvider2)
@ -720,6 +740,38 @@ nsDirectoryService::RegisterProvider(nsIDirectoryServiceProvider *prov)
return mProviders->AppendElement(supports) ? NS_OK : NS_ERROR_FAILURE;
}
void
nsDirectoryService::RegisterCategoryProviders()
{
nsCOMPtr<nsICategoryManager> catman
(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
if (!catman)
return;
nsCOMPtr<nsISimpleEnumerator> entries;
catman->EnumerateCategory(XPCOM_DIRECTORY_PROVIDER_CATEGORY,
getter_AddRefs(entries));
nsCOMPtr<nsIUTF8StringEnumerator> strings(do_QueryInterface(entries));
if (!strings)
return;
PRBool more;
while (NS_SUCCEEDED(strings->HasMore(&more)) && more) {
nsCAutoString entry;
strings->GetNext(entry);
nsXPIDLCString contractID;
catman->GetCategoryEntry(XPCOM_DIRECTORY_PROVIDER_CATEGORY, entry.get(), getter_Copies(contractID));
if (contractID) {
nsCOMPtr<nsIDirectoryServiceProvider> provider = do_GetService(contractID.get());
if (provider)
RegisterProvider(provider);
}
}
}
NS_IMETHODIMP
nsDirectoryService::UnregisterProvider(nsIDirectoryServiceProvider *prov)
{

Просмотреть файл

@ -67,16 +67,19 @@ class nsDirectoryService : public nsIDirectoryService,
NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
nsDirectoryService();
~nsDirectoryService();
static nsresult RealInit();
void RegisterCategoryProviders();
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
private:
~nsDirectoryService();
static nsDirectoryService* gService;
private:
nsresult GetCurrentProcessDirectory(nsILocalFile** aFile);
static nsDirectoryService* mService;
static PRBool PR_CALLBACK ReleaseValues(nsHashKey* key, void* data, void* closure);
nsSupportsHashtable mHashtable;
nsCOMPtr<nsISupportsArray> mProviders;