From 126369b22df4189f718ee46ca883bbb849486992 Mon Sep 17 00:00:00 2001 From: "rayw%netscape.com" Date: Mon, 15 May 2000 19:28:12 +0000 Subject: [PATCH] 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. git-svn-id: svn://10.0.0.236/trunk@69818 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xpcom/components/nsComponentManager.cpp | 141 +++++++++++------- mozilla/xpcom/components/nsIServiceManager.h | 3 + .../components/nsNativeComponentLoader.cpp | 43 +++++- 3 files changed, 134 insertions(+), 53 deletions(-) diff --git a/mozilla/xpcom/components/nsComponentManager.cpp b/mozilla/xpcom/components/nsComponentManager.cpp index c2ad5966460..4e3128da402 100644 --- a/mozilla/xpcom/components/nsComponentManager.cpp +++ b/mozilla/xpcom/components/nsComponentManager.cpp @@ -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 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 loaderEnum; - rv = mRegistry->EnumerateSubtrees(mLoadersKey, getter_AddRefs(loaderEnum)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr 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 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 loaderEnum; + if (NS_SUCCEEDED(rv)) + { + /* XXX eagerly instantiate all known loaders */ + rv = mRegistry->EnumerateSubtrees(mLoadersKey, getter_AddRefs(loaderEnum)); + } + + nsCOMPtr 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 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 diff --git a/mozilla/xpcom/components/nsIServiceManager.h b/mozilla/xpcom/components/nsIServiceManager.h index 1c8dc20378b..a65ef7449a2 100644 --- a/mozilla/xpcom/components/nsIServiceManager.h +++ b/mozilla/xpcom/components/nsIServiceManager.h @@ -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___ */ diff --git a/mozilla/xpcom/components/nsNativeComponentLoader.cpp b/mozilla/xpcom/components/nsNativeComponentLoader.cpp index 723e5db0c56..ac5bf5a1eb9 100644 --- a/mozilla/xpcom/components/nsNativeComponentLoader.cpp +++ b/mozilla/xpcom/components/nsNativeComponentLoader.cpp @@ -42,6 +42,8 @@ #include "nsXPIDLString.h" #include "nsCRT.h" +#include "nsIObserverService.h" + #ifdef XP_MAC // sdagley dougt fix #include #include @@ -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