Added an observer to autoregistration, which allows a callback during that

part of startup to advance a progress display, per bug 35866.

I did not get the code actually reviewed, but I discussed it, and tested it
for breakage.  Other developers must register for the observer before it can
be ascertained whether it performs as advertized.
This commit is contained in:
rayw%netscape.com 2000-05-15 19:28:12 +00:00
parent dc1f400d01
commit 3b33b094d3
3 changed files with 134 additions and 53 deletions

View File

@ -52,6 +52,8 @@
#include "nsNativeComponentLoader.h"
#include "nsXPIDLString.h"
#include "nsIObserverService.h"
#include "nsILocalFile.h"
#include "nsLocalFile.h"
#include "nsDirectoryService.h"
@ -1970,6 +1972,9 @@ RegisterDeferred_enumerate(nsHashKey *key, void *aData, void *aClosure)
return NS_SUCCEEDED(closure->status) ? PR_TRUE : PR_FALSE;
}
static const PRUnichar sARStart[] = {'S', 't', 'a', 'r', 't', ':', ' ', 0};
static const PRUnichar sAREnd[] = {'E', 'n', 'd', ':', ' ', 0};
nsresult
nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
{
@ -2009,70 +2014,102 @@ nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
nsCOMPtr<nsIInterfaceInfoManager> iim =
dont_AddRef(XPTI_GetInterfaceInfoManager());
if (!iim)
return NS_ERROR_UNEXPECTED;
// Notify observers of xpcom autoregistration start
NS_WITH_SERVICE (nsIObserverService, observerService, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_FAILED(rv))
{
nsIServiceManager *mgr; // NO COMPtr as we dont release the service manager
rv = nsServiceManager::GetGlobalServiceManager(&mgr);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic;
topic.AssignWithConversion(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID);
(void) observerService->Notify(mgr, topic.GetUnicode(), sARStart);
}
}
rv = iim->AutoRegisterInterfaces();
if (NS_FAILED(rv))
return rv;
/* do the native loader first, so we can find other loaders */
rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
if (NS_FAILED(rv))
return rv;
/* XXX eagerly instantiate all known loaders */
nsCOMPtr<nsIEnumerator> loaderEnum;
rv = mRegistry->EnumerateSubtrees(mLoadersKey, getter_AddRefs(loaderEnum));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIRegistryEnumerator> regEnum =
do_QueryInterface(loaderEnum, &rv);
if (NS_FAILED(rv))
return rv;
for (rv = regEnum->First();
NS_SUCCEEDED(rv) && (regEnum->IsDone() != NS_OK);
rv = regEnum->Next()) {
const char * type;
nsRegistryKey throwAway;
/*
* CurrentItemInPlaceUTF8 will give us back a _shared_ pointer in
* type. This is bad XPCOM practice. It is evil, and requires
* great care with the relative lifetimes of type and regEnum.
*
* It is also faster, and less painful in the allocation department.
*/
rv = regEnum->CurrentItemInPlaceUTF8(&throwAway, &type);
if (NS_FAILED(rv))
continue;
nsCOMPtr<nsIComponentLoader> loader;
/* this will create it if we haven't already */
GetLoaderForType(type, getter_AddRefs(loader));
continue;
if (NS_SUCCEEDED(rv))
{
/* do the native loader first, so we can find other loaders */
rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
}
/* iterate over all known loaders and ask them to autoregister. */
struct AutoReg_closure closure;
/* XXX convert when to nsIComponentLoader::(when) properly */
closure.when = when;
closure.spec = dir.get();
closure.status = NS_OK;
closure.native = mNativeComponentLoader; // prevent duplicate autoreg
nsCOMPtr<nsIEnumerator> loaderEnum;
if (NS_SUCCEEDED(rv))
{
/* XXX eagerly instantiate all known loaders */
rv = mRegistry->EnumerateSubtrees(mLoadersKey, getter_AddRefs(loaderEnum));
}
nsCOMPtr<nsIRegistryEnumerator> regEnum;
if (NS_SUCCEEDED(rv))
{
regEnum = do_QueryInterface(loaderEnum, &rv);
}
mLoaders->Enumerate(AutoRegister_enumerate, &closure);
if (NS_FAILED(closure.status))
return closure.status;
struct AutoReg_closure closure;
if (NS_SUCCEEDED(rv))
{
for (rv = regEnum->First();
NS_SUCCEEDED(rv) && (regEnum->IsDone() != NS_OK);
rv = regEnum->Next()) {
const char * type;
nsRegistryKey throwAway;
/*
* CurrentItemInPlaceUTF8 will give us back a _shared_ pointer in
* type. This is bad XPCOM practice. It is evil, and requires
* great care with the relative lifetimes of type and regEnum.
*
* It is also faster, and less painful in the allocation department.
*/
rv = regEnum->CurrentItemInPlaceUTF8(&throwAway, &type);
if (NS_FAILED(rv))
continue;
nsCOMPtr<nsIComponentLoader> loader;
/* this will create it if we haven't already */
GetLoaderForType(type, getter_AddRefs(loader));
do {
closure.registered = PR_FALSE;
mLoaders->Enumerate(RegisterDeferred_enumerate, &closure);
} while (NS_SUCCEEDED(closure.status) && closure.registered);
continue;
}
return closure.status;
/* iterate over all known loaders and ask them to autoregister. */
/* XXX convert when to nsIComponentLoader::(when) properly */
closure.when = when;
closure.spec = dir.get();
closure.status = NS_OK;
closure.native = mNativeComponentLoader; // prevent duplicate autoreg
mLoaders->Enumerate(AutoRegister_enumerate, &closure);
rv = closure.status;
}
if (NS_SUCCEEDED(rv))
{
do {
closure.registered = PR_FALSE;
mLoaders->Enumerate(RegisterDeferred_enumerate, &closure);
} while (NS_SUCCEEDED(closure.status) && closure.registered);
rv = closure.status;
}
nsIServiceManager *mgr; // NO COMPtr as we dont release the service manager
rv = nsServiceManager::GetGlobalServiceManager(&mgr);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic;
topic.AssignWithConversion(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID);
(void) observerService->Notify(mgr, topic.GetUnicode(), sAREnd);
}
return rv;
}
static PRBool PR_CALLBACK

View File

@ -354,4 +354,7 @@ NS_ShutdownXPCOM(nsIServiceManager* servMgr);
#define NS_XPCOM_SHUTDOWN_OBSERVER_ID "xpcom-shutdown"
#define NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID "xpcom-autoregistration"
#endif /* nsIServiceManager_h___ */

View File

@ -42,6 +42,8 @@
#include "nsXPIDLString.h"
#include "nsCRT.h"
#include "nsIObserverService.h"
#ifdef XP_MAC // sdagley dougt fix
#include <Files.h>
#include <Errors.h>
@ -649,6 +651,14 @@ nsNativeComponentLoader::SelfUnregisterDll(nsDll *dll)
return res;
}
static const PRUnichar sNativeComponentReg[] = {'R','e','g','i','s','t','e','r',
'i','n','g',' ','n', 'a', 't', 'i', 'v', 'e', ' ', 'c', 'o', 'm', 'p', 'o',
'n', 'e', 'n', 't',':',' ', 0};
static const PRUnichar sNativeComponentUnreg[] = {'U','n','r','e','g','i','s','t','e','r',
'i','n','g',' ','n', 'a', 't', 'i', 'v', 'e', ' ', 'c', 'o', 'm', 'p', 'o',
'n', 'e', 'n', 't',':',' ', 0};
nsresult
nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when,
nsIFile *component,
@ -661,6 +671,21 @@ nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when,
getter_Copies(persistentDescriptor));
if (NS_FAILED(rv)) return rv;
// Notify observers, if any, of autoregistration work
NS_WITH_SERVICE (nsIObserverService, observerService, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv))
{
nsIServiceManager *mgr; // NO COMPtr as we dont release the service manager
rv = nsServiceManager::GetGlobalServiceManager(&mgr);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic; // This is quite ineficient, but is how it is
// done in every other example.
topic.AssignWithConversion(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID);
(void) observerService->Notify(mgr, topic.GetUnicode(), sNativeComponentUnreg);
}
}
nsDll *dll = NULL;
PRInt64 mod = LL_Zero(), size = LL_Zero();
rv = CreateDll(component, persistentDescriptor, &mod, &size, &dll);
@ -678,7 +703,6 @@ nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when,
return rv;
}
nsresult
nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
nsIFile *component,
@ -806,6 +830,23 @@ nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
// Aagh! the dll has changed since the last time we saw it.
// re-register dll
// Notify observers, if any, of autoregistration work
NS_WITH_SERVICE (nsIObserverService, observerService, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv))
{
nsIServiceManager *mgr; // NO COMPtr as we dont release the service manager
rv = nsServiceManager::GetGlobalServiceManager(&mgr);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic; // This is quite ineficient, but is how it is
// done in every other example.
topic.AssignWithConversion(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID);
(void) observerService->Notify(mgr, topic.GetUnicode(), sNativeComponentReg);
}
}
if (dll->IsLoaded())
{
// We loaded the old version of the dll and now we find that the