mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
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:
parent
dc1f400d01
commit
3b33b094d3
@ -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
|
||||
|
@ -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___ */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user