Make PSM make sure to shut down NSS before trying to start it up with theinitial profile on app startup. Fix leak of one of the user modules that waspreventing a clean shutdown. Bug 379582, r=rrelyea, kaie, sr=biesi.

This commit is contained in:
bzbarsky@mit.edu 2007-05-14 14:09:58 -07:00
Родитель 383c82c5d9
Коммит 76c4fecf5f
2 изменённых файлов: 118 добавлений и 66 удалений

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

@ -770,6 +770,7 @@ nsNSSComponent::InstallLoadableRoots()
if (RootsModule) {
// found a module, no need to try other directories
SECMOD_DestroyModule(RootsModule);
break;
}
}
@ -1863,69 +1864,34 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *someData)
{
if (nsCRT::strcmp(aTopic, PROFILE_APPROVE_CHANGE_TOPIC) == 0) {
if (mShutdownObjectList->isUIActive()) {
ShowAlert(ai_crypto_ui_active);
nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
if (status) {
status->VetoChange();
}
}
DoProfileApproveChange(aSubject);
}
else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_TOPIC) == 0) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("in PSM code, receiving change-teardown\n"));
PRBool callVeto = PR_FALSE;
if (!mShutdownObjectList->ifPossibleDisallowUI()) {
callVeto = PR_TRUE;
ShowAlert(ai_crypto_ui_active);
}
else if (mShutdownObjectList->areSSLSocketsActive()) {
callVeto = PR_TRUE;
ShowAlert(ai_sockets_still_active);
}
if (callVeto) {
nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
if (status) {
status->VetoChange();
}
}
DoProfileChangeTeardown(aSubject);
}
else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC) == 0) {
mShutdownObjectList->allowUI();
}
else if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving profile change topic\n"));
NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
PRBool needsCleanup = PR_TRUE;
{
nsAutoLock lock(mutex);
if (!mNSSInitialized) {
// Make sure we don't try to cleanup if we have already done so.
// This makes sure we behave safely, in case we are notified
// multiple times.
needsCleanup = PR_FALSE;
}
}
StopCRLUpdateTimer();
if (needsCleanup) {
if (NS_FAILED(ShutdownNSS())) {
nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
if (status) {
status->ChangeFailed();
}
}
}
mShutdownObjectList->allowUI();
DoProfileBeforeChange(aSubject);
}
else if (nsCRT::strcmp(aTopic, PROFILE_AFTER_CHANGE_TOPIC) == 0) {
if (someData && NS_LITERAL_STRING("startup").Equals(someData)) {
// The application is initializing against a known profile directory for
// the first time during process execution.
// However, earlier code execution might have already triggered NSS init.
// We must ensure that NSS gets shut down prior to any attempt to init
// it again. We use the same cleanup functionality used when switching
// profiles. The order of function calls must correspond to the order
// of notifications sent by Profile Manager (nsProfile).
DoProfileApproveChange(aSubject);
DoProfileChangeNetTeardown();
DoProfileChangeTeardown(aSubject);
DoProfileBeforeChange(aSubject);
DoProfileChangeNetRestore();
}
PRBool needsInit = PR_TRUE;
@ -2021,23 +1987,11 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
}
else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
if (mSSLThread)
mSSLThread->requestExit();
if (mCertVerificationThread)
mCertVerificationThread->requestExit();
mIsNetworkDown = PR_TRUE;
DoProfileChangeNetTeardown();
}
else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_RESTORE_TOPIC) == 0) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network restore topic\n"));
delete mSSLThread;
mSSLThread = new nsSSLThread();
if (mSSLThread)
mSSLThread->startThread();
delete mCertVerificationThread;
mCertVerificationThread = new nsCertVerificationThread();
if (mCertVerificationThread)
mCertVerificationThread->startThread();
mIsNetworkDown = PR_FALSE;
DoProfileChangeNetRestore();
}
return NS_OK;
@ -2232,6 +2186,95 @@ nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessa
return rv;
}
void
nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
{
if (mShutdownObjectList->isUIActive()) {
ShowAlert(ai_crypto_ui_active);
nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
if (status) {
status->VetoChange();
}
}
}
void
nsNSSComponent::DoProfileChangeNetTeardown()
{
if (mSSLThread)
mSSLThread->requestExit();
if (mCertVerificationThread)
mCertVerificationThread->requestExit();
mIsNetworkDown = PR_TRUE;
}
void
nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
{
PRBool callVeto = PR_FALSE;
if (!mShutdownObjectList->ifPossibleDisallowUI()) {
callVeto = PR_TRUE;
ShowAlert(ai_crypto_ui_active);
}
else if (mShutdownObjectList->areSSLSocketsActive()) {
callVeto = PR_TRUE;
ShowAlert(ai_sockets_still_active);
}
if (callVeto) {
nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
if (status) {
status->VetoChange();
}
}
}
void
nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
{
NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
PRBool needsCleanup = PR_TRUE;
{
nsAutoLock lock(mutex);
if (!mNSSInitialized) {
// Make sure we don't try to cleanup if we have already done so.
// This makes sure we behave safely, in case we are notified
// multiple times.
needsCleanup = PR_FALSE;
}
}
StopCRLUpdateTimer();
if (needsCleanup) {
if (NS_FAILED(ShutdownNSS())) {
nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
if (status) {
status->ChangeFailed();
}
}
}
mShutdownObjectList->allowUI();
}
void
nsNSSComponent::DoProfileChangeNetRestore()
{
delete mSSLThread;
mSSLThread = new nsSSLThread();
if (mSSLThread)
mSSLThread->startThread();
delete mCertVerificationThread;
mCertVerificationThread = new nsCertVerificationThread();
if (mCertVerificationThread)
mCertVerificationThread->startThread();
mIsNetworkDown = PR_FALSE;
}
//---------------------------------------------
// Implementing nsICryptoHash
//---------------------------------------------

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

@ -257,6 +257,15 @@ private:
nsresult PostCRLImportEvent(const nsCSubstring &urlString, nsIStreamListener *psmDownloader);
nsresult getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key);
nsresult DispatchEventToWindow(nsIDOMWindow *domWin, const nsAString &eventType, const nsAString &token);
// Methods that we use to handle the profile change notifications (and to
// synthesize a full profile change when we're just doing a profile startup):
void DoProfileApproveChange(nsISupports* aSubject);
void DoProfileChangeNetTeardown();
void DoProfileChangeTeardown(nsISupports* aSubject);
void DoProfileBeforeChange(nsISupports* aSubject);
void DoProfileChangeNetRestore();
PRLock *mutex;
nsCOMPtr<nsIScriptSecurityManager> mScriptSecurityManager;