diff --git a/extensions/psm-glue/src/nsPSMComponent.cpp b/extensions/psm-glue/src/nsPSMComponent.cpp index ffd33c387d9b..e6f60adf8dc4 100644 --- a/extensions/psm-glue/src/nsPSMComponent.cpp +++ b/extensions/psm-glue/src/nsPSMComponent.cpp @@ -64,6 +64,9 @@ #include "nsIDOMWindow.h" +#include "nsIObserverService.h" +#include "nsIProfileChangeStatus.h" + #define PSM_VERSION_REG_KEY "/Netscape/Personal Security Manager" #if defined(WIN32) || defined(XP_OS2) @@ -74,7 +77,6 @@ #define PSM_FILE_NAME "psm" #endif - static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); static NS_DEFINE_CID(kProfileCID, NS_PROFILE_CID); static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); @@ -87,6 +89,7 @@ nsPSMComponent::nsPSMComponent() NS_INIT_REFCNT(); mControl = nsnull; mCertContentListener = nsnull; + mEventLoopThread = nsnull; } nsPSMComponent::~nsPSMComponent() @@ -123,8 +126,10 @@ nsPSMComponent::CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aR if (mInstance == nsnull) { mInstance = new nsPSMComponent(); - if (mInstance) + if (mInstance) { mInstance->RegisterCertContentListener(); + mInstance->RegisterProfileChangeObserver(); + } } if (mInstance == nsnull) @@ -152,13 +157,31 @@ nsPSMComponent::RegisterCertContentListener() return rv; } +nsresult +nsPSMComponent::RegisterProfileChangeObserver() +{ + nsresult rv; + NS_WITH_SERVICE(nsIObserverService, observerService, NS_OBSERVERSERVICE_CONTRACTID, &rv); + NS_ASSERTION(observerService, "could not get observer service"); + if (observerService) { + // Our refcnt must be > 0 when we call AddObserver or we'll get deleted. + ++mRefCnt; + observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC); + --mRefCnt; + } + return rv; +} + + /* nsISupports Implementation for the class */ -NS_IMPL_THREADSAFE_ISUPPORTS5(nsPSMComponent, +NS_IMPL_THREADSAFE_ISUPPORTS7(nsPSMComponent, nsIPSMComponent, nsISecurityManagerComponent, nsIContentHandler, nsISignatureVerifier, - nsIEntropyCollector); + nsIEntropyCollector, + nsIObserver, + nsISupportsWeakReference); #define INIT_NUM_PREFS 100 /* preference types */ @@ -612,7 +635,7 @@ nsPSMComponent::GetControlConnection( CMT_CONTROL * *_retval ) if (psmStatus == CMTFailure) goto failure; - if (InitPSMEventLoop(mControl) != PR_SUCCESS) + if (InitPSMEventLoop(mControl, &mEventLoopThread) != PR_SUCCESS) goto failure; if (NS_FAILED(PassPrefs())) @@ -1194,3 +1217,23 @@ nsPSMComponent::RandomUpdate(void *entropy, PRInt32 bufLen) } return NS_OK; } + +NS_IMETHODIMP +nsPSMComponent::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData) +{ + if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) { + + // The profile is about to change - close our control connection if we have one. + // Next time PSM is needed, we'll make a new control connection which + // will use the new profile dir. + if (mEventLoopThread) { + PR_Interrupt(mEventLoopThread); + mEventLoopThread = nsnull; + } + if (mControl) { + CMT_CloseControlConnection(mControl); + mControl = nsnull; + } + } + return NS_OK; +} diff --git a/extensions/psm-glue/src/nsPSMComponent.h b/extensions/psm-glue/src/nsPSMComponent.h index d227918606e1..7b1a0da9c410 100644 --- a/extensions/psm-glue/src/nsPSMComponent.h +++ b/extensions/psm-glue/src/nsPSMComponent.h @@ -24,6 +24,7 @@ #ifndef _NSPSMCOMPONENT_H #define _NSPSMCOMPONENT_H #include "nscore.h" +#include "prthread.h" #include "nsIPSMComponent.h" #include "nsISignatureVerifier.h" #include "nsIStringBundle.h" @@ -32,6 +33,9 @@ #include "nsIURIContentListener.h" #include "nsIEntropyCollector.h" +#include "nsIObserver.h" +#include "nsWeakReference.h" + #define SECURITY_STRING_BUNDLE_URL "chrome://communicator/locale/security.properties" #define NS_PSMCOMPONENT_CID {0xddcae170, 0x5412, 0x11d3, {0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37}} @@ -60,7 +64,9 @@ private: class nsPSMComponent : public nsIPSMComponent, public nsIContentHandler, public nsISignatureVerifier, - public nsIEntropyCollector + public nsIEntropyCollector, + public nsIObserver, + public nsSupportsWeakReference { public: NS_DEFINE_STATIC_CID_ACCESSOR( NS_PSMCOMPONENT_CID ); @@ -74,12 +80,15 @@ public: NS_DECL_NSICONTENTHANDLER NS_DECL_NSISIGNATUREVERIFIER NS_DECL_NSIENTROPYCOLLECTOR + NS_DECL_NSIOBSERVER static NS_METHOD CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aResult); nsresult RegisterCertContentListener(); + nsresult RegisterProfileChangeObserver(); private: PCMT_CONTROL mControl; + PRThread *mEventLoopThread; nsCOMPtr mSecureBrowserIU; nsCOMPtr mCertContentListener; diff --git a/extensions/psm-glue/src/nsPSMUICallbacks.cpp b/extensions/psm-glue/src/nsPSMUICallbacks.cpp index 4515602f7678..ed6833ffc173 100644 --- a/extensions/psm-glue/src/nsPSMUICallbacks.cpp +++ b/extensions/psm-glue/src/nsPSMUICallbacks.cpp @@ -207,9 +207,12 @@ extern "C" void CARTMAN_UIEventLoop(void *data) CMT_EventLoop((PCMT_CONTROL)data); } -PRStatus InitPSMEventLoop(PCMT_CONTROL control) +PRStatus InitPSMEventLoop(PCMT_CONTROL control, PRThread **aThread) { - PR_CreateThread(PR_USER_THREAD, + if (!aThread) + return PR_FAILURE; + + *aThread = PR_CreateThread(PR_USER_THREAD, CARTMAN_UIEventLoop, control, PR_PRIORITY_NORMAL, @@ -217,7 +220,7 @@ PRStatus InitPSMEventLoop(PCMT_CONTROL control) PR_UNJOINABLE_THREAD, 0); - return PR_SUCCESS; + return *aThread ? PR_SUCCESS : PR_FAILURE; } PRStatus InitPSMUICallbacks(PCMT_CONTROL control) diff --git a/extensions/psm-glue/src/nsPSMUICallbacks.h b/extensions/psm-glue/src/nsPSMUICallbacks.h index 9ef5d7bb5619..3ffad2636996 100644 --- a/extensions/psm-glue/src/nsPSMUICallbacks.h +++ b/extensions/psm-glue/src/nsPSMUICallbacks.h @@ -27,12 +27,13 @@ #include "prtypes.h" #include "cmtcmn.h" +#include "prthread.h" #include "nsIPSMUIHandler.h" #include "nsIDOMWindow.h" PRStatus InitPSMUICallbacks(PCMT_CONTROL gControl); -PRStatus InitPSMEventLoop(PCMT_CONTROL gControl); +PRStatus InitPSMEventLoop(PCMT_CONTROL gControl, PRThread **aThread); PRStatus DisplayPSMUIDialog(PCMT_CONTROL control, const char* pickledStatus, const char *hostName, nsIDOMWindow * window);