bug 420187, hang in nsNSSHttpRequestSession::internal_send_receive_attempt r=rrelyea, pending more comments blocking1.9=shaver approval1.9b5=beltzner

This commit is contained in:
kaie@kuix.de 2008-03-25 12:34:48 -07:00
Родитель bfdb68b9a2
Коммит cfd263a72b
8 изменённых файлов: 209 добавлений и 75 удалений

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

@ -162,6 +162,7 @@ nsSecureBrowserUIImpl::nsSecureBrowserUIImpl()
mMonitor = PR_NewMonitor(); mMonitor = PR_NewMonitor();
mOnStateLocationChangeReentranceDetection = 0; mOnStateLocationChangeReentranceDetection = 0;
mTransferringRequests.ops = nsnull; mTransferringRequests.ops = nsnull;
mInconsistency = PR_FALSE;
mNewToplevelSecurityState = STATE_IS_INSECURE; mNewToplevelSecurityState = STATE_IS_INSECURE;
mNewToplevelIsEV = PR_FALSE; mNewToplevelIsEV = PR_FALSE;
mNewToplevelSecurityStateKnown = PR_TRUE; mNewToplevelSecurityStateKnown = PR_TRUE;
@ -596,10 +597,6 @@ nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress,
PRUint32 aProgressStateFlags, PRUint32 aProgressStateFlags,
nsresult aStatus) nsresult aStatus)
{ {
nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection);
NS_ASSERTION(mOnStateLocationChangeReentranceDetection == 1,
"unexpected parallel nsIWebProgress OnStateChange and/or OnLocationChange notification");
/* /*
All discussion, unless otherwise mentioned, only refers to All discussion, unless otherwise mentioned, only refers to
http, https, file or wyciwig requests. http, https, file or wyciwig requests.
@ -690,19 +687,43 @@ nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress,
regardless of whether the load flags indicate a top level document. regardless of whether the load flags indicate a top level document.
*/ */
nsCOMPtr<nsIDOMWindow> windowForProgress; nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection);
aWebProgress->GetDOMWindow(getter_AddRefs(windowForProgress)); if (mOnStateLocationChangeReentranceDetection > 1)
{
nsAutoMonitor lock(mMonitor);
mInconsistency = PR_TRUE;
// we ignore all events until the reentrance is gone
return NS_ERROR_FAILURE;
}
PRBool mustResetAfterInconsistency = PR_FALSE;
nsCOMPtr<nsIDOMWindow> windowForProgress;
nsCOMPtr<nsIDOMWindow> window; nsCOMPtr<nsIDOMWindow> window;
PRBool isViewSource; PRBool isViewSource;
{ {
nsAutoMonitor lock(mMonitor); nsAutoMonitor lock(mMonitor);
if (mInconsistency) {
mInconsistency = PR_FALSE;
mustResetAfterInconsistency = PR_TRUE;
}
window = do_QueryReferent(mWindow); window = do_QueryReferent(mWindow);
NS_ASSERTION(window, "Window has gone away?!"); NS_ASSERTION(window, "Window has gone away?!");
isViewSource = mIsViewSource; isViewSource = mIsViewSource;
} }
if (mustResetAfterInconsistency) {
mNewToplevelSecurityState = STATE_IS_INSECURE;
mNewToplevelIsEV = PR_FALSE;
mNewToplevelSecurityStateKnown = PR_TRUE;
mSSLStatus = nsnull;
ResetStateTracking();
}
aWebProgress->GetDOMWindow(getter_AddRefs(windowForProgress));
const PRBool isToplevelProgress = (windowForProgress.get() == window.get()); const PRBool isToplevelProgress = (windowForProgress.get() == window.get());
#ifdef PR_LOGGING #ifdef PR_LOGGING
@ -1251,8 +1272,8 @@ void nsSecureBrowserUIImpl::UpdateMyFlags(PRBool &showWarning, lockIconState &wa
mNotifiedToplevelIsEV = mNewToplevelIsEV; mNotifiedToplevelIsEV = mNewToplevelIsEV;
} }
nsresult nsSecureBrowserUIImpl::TellTheWorld(PRBool &showWarning, nsresult nsSecureBrowserUIImpl::TellTheWorld(PRBool showWarning,
lockIconState &warnSecurityState, lockIconState warnSecurityState,
nsIRequest* aRequest) nsIRequest* aRequest)
{ {
nsCOMPtr<nsISecurityEventSink> temp_ToplevelEventSink; nsCOMPtr<nsISecurityEventSink> temp_ToplevelEventSink;
@ -1319,8 +1340,20 @@ nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress,
nsIURI* aLocation) nsIURI* aLocation)
{ {
nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection); nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection);
NS_ASSERTION(mOnStateLocationChangeReentranceDetection == 1, if (mOnStateLocationChangeReentranceDetection > 1)
"unexpected parallel nsIWebProgress OnStateChange and/or OnLocationChange notification"); {
nsAutoMonitor lock(mMonitor);
mInconsistency = PR_TRUE;
// We ignore all events until the reentrance is gone
// and has been reset by ::OnStateChange.
return NS_ERROR_FAILURE;
}
// We could test for mInconsistency right here and exit,
// but let's avoid another lock to mMonitor.
// We'll do the preparation work based on the parameters,
// and once we are ready to lock the monitor, we'll do
// the inconsistency check.
PRBool updateIsViewSource = PR_FALSE; PRBool updateIsViewSource = PR_FALSE;
PRBool temp_IsViewSource = PR_FALSE; PRBool temp_IsViewSource = PR_FALSE;
@ -1344,6 +1377,9 @@ nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress,
{ {
nsAutoMonitor lock(mMonitor); nsAutoMonitor lock(mMonitor);
if (mInconsistency) {
return NS_ERROR_FAILURE;
}
if (updateIsViewSource) { if (updateIsViewSource) {
mIsViewSource = temp_IsViewSource; mIsViewSource = temp_IsViewSource;
} }

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

@ -114,6 +114,7 @@ protected:
void ResetStateTracking(); void ResetStateTracking();
PRUint32 mNewToplevelSecurityState; PRUint32 mNewToplevelSecurityState;
PRPackedBool mInconsistency;
PRPackedBool mNewToplevelIsEV; PRPackedBool mNewToplevelIsEV;
PRPackedBool mNewToplevelSecurityStateKnown; PRPackedBool mNewToplevelSecurityStateKnown;
PRPackedBool mIsViewSource; PRPackedBool mIsViewSource;
@ -129,8 +130,8 @@ protected:
static nsresult MapInternalToExternalState(PRUint32* aState, lockIconState lock, PRBool ev); static nsresult MapInternalToExternalState(PRUint32* aState, lockIconState lock, PRBool ev);
nsresult UpdateSecurityState(nsIRequest* aRequest); nsresult UpdateSecurityState(nsIRequest* aRequest);
void UpdateMyFlags(PRBool &showWarning, lockIconState &warnSecurityState); void UpdateMyFlags(PRBool &showWarning, lockIconState &warnSecurityState);
nsresult TellTheWorld(PRBool &showWarning, nsresult TellTheWorld(PRBool showWarning,
lockIconState &warnSecurityState, lockIconState warnSecurityState,
nsIRequest* aRequest); nsIRequest* aRequest);
nsresult EvaluateAndUpdateSecurityState(nsIRequest *aRequest); nsresult EvaluateAndUpdateSecurityState(nsIRequest *aRequest);

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

@ -80,20 +80,35 @@ NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
extern PRLogModuleInfo* gPIPNSSLog; extern PRLogModuleInfo* gPIPNSSLog;
#endif #endif
struct nsHTTPDownloadEvent : nsRunnable { class nsHTTPDownloadEvent : public nsRunnable {
public:
nsHTTPDownloadEvent(); nsHTTPDownloadEvent();
~nsHTTPDownloadEvent(); ~nsHTTPDownloadEvent();
NS_IMETHOD Run(); NS_IMETHOD Run();
void Cancel();
nsNSSHttpRequestSession *mRequestSession; // no ownership nsNSSHttpRequestSession *mRequestSession; // no ownership
nsCOMPtr<nsHTTPListener> mListener; nsCOMPtr<nsHTTPListener> mListener;
PRBool mResponsibleForDoneSignal; PRBool mResponsibleForDoneSignal;
protected:
PRLock *mLock;
// no nsCOMPtr. When I use it, I get assertions about
// loadgroup not being thread safe.
// So, let's use a raw pointer and ensure we only create and destroy
// it on the network thread ourselves.
nsILoadGroup *mLoadGroup;
PRThread *mLoadGroupOwnerThread;
}; };
nsHTTPDownloadEvent::nsHTTPDownloadEvent() nsHTTPDownloadEvent::nsHTTPDownloadEvent()
:mResponsibleForDoneSignal(PR_TRUE) :mResponsibleForDoneSignal(PR_TRUE)
,mLock(nsnull)
,mLoadGroup(nsnull)
,mLoadGroupOwnerThread(nsnull)
{ {
} }
@ -101,11 +116,17 @@ nsHTTPDownloadEvent::~nsHTTPDownloadEvent()
{ {
if (mResponsibleForDoneSignal && mListener) if (mResponsibleForDoneSignal && mListener)
mListener->send_done_signal(); mListener->send_done_signal();
if (mLock)
PR_DestroyLock(mLock);
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTTPDownloadEvent::Run() nsHTTPDownloadEvent::Run()
{ {
mLock = PR_NewLock();
if (!mLock)
return NS_ERROR_OUT_OF_MEMORY;
if (!mListener) if (!mListener)
return NS_OK; return NS_OK;
@ -120,9 +141,16 @@ nsHTTPDownloadEvent::Run()
// Create a loadgroup for this new channel. This way if the channel // Create a loadgroup for this new channel. This way if the channel
// is redirected, we'll have a way to cancel the resulting channel. // is redirected, we'll have a way to cancel the resulting channel.
nsCOMPtr<nsILoadGroup> loadGroup = nsCOMPtr<nsILoadGroup> lg;
do_CreateInstance(NS_LOADGROUP_CONTRACTID); {
chan->SetLoadGroup(loadGroup); nsAutoLock locker(mLock);
lg = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
mLoadGroup = lg.get();
NS_ADDREF(mLoadGroup);
mLoadGroupOwnerThread = PR_GetCurrentThread();
}
chan->SetLoadGroup(lg);
lg = nsnull;
if (mRequestSession->mHasPostData) if (mRequestSession->mHasPostData)
{ {
@ -148,8 +176,6 @@ nsHTTPDownloadEvent::Run()
rv = hchan->SetRequestMethod(mRequestSession->mRequestMethod); rv = hchan->SetRequestMethod(mRequestSession->mRequestMethod);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsSSLThread::rememberPendingHTTPRequest(loadGroup);
mResponsibleForDoneSignal = PR_FALSE; mResponsibleForDoneSignal = PR_FALSE;
mListener->mResponsibleForDoneSignal = PR_TRUE; mListener->mResponsibleForDoneSignal = PR_TRUE;
@ -162,20 +188,47 @@ nsHTTPDownloadEvent::Run()
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mListener->mResponsibleForDoneSignal = PR_FALSE; mListener->mResponsibleForDoneSignal = PR_FALSE;
mResponsibleForDoneSignal = PR_TRUE; mResponsibleForDoneSignal = PR_TRUE;
nsSSLThread::rememberPendingHTTPRequest(nsnull);
} }
return NS_OK; return NS_OK;
} }
struct nsCancelHTTPDownloadEvent : nsRunnable { struct nsCancelHTTPDownloadEvent : nsRunnable {
nsRefPtr<nsHTTPDownloadEvent> mEvent;
NS_IMETHOD Run() { NS_IMETHOD Run() {
nsSSLThread::cancelPendingHTTPRequest(); mEvent->Cancel();
mEvent = nsnull;
return NS_OK; return NS_OK;
} }
}; };
void
nsHTTPDownloadEvent::Cancel()
{
nsILoadGroup *lg = nsnull;
if (mLock) {
nsAutoLock locker(mLock);
if (mLoadGroup) {
if (mLoadGroupOwnerThread != PR_GetCurrentThread()) {
NS_ASSERTION(PR_FALSE,
"attempt to access nsHTTPDownloadEvent::mLoadGroup on multiple threads");
}
else {
lg = mLoadGroup;
mLoadGroup = nsnull;
}
}
}
if (lg) {
lg->Cancel(NS_ERROR_ABORT);
NS_RELEASE(lg);
}
}
SECStatus nsNSSHttpServerSession::createSessionFcn(const char *host, SECStatus nsNSSHttpServerSession::createSessionFcn(const char *host,
PRUint16 portnum, PRUint16 portnum,
SEC_HTTP_SERVER_SESSION *pSession) SEC_HTTP_SERVER_SESSION *pSession)
@ -367,7 +420,6 @@ nsNSSHttpRequestSession::internal_send_receive_attempt(PRBool &retryable_error,
} }
PRBool request_canceled = PR_FALSE; PRBool request_canceled = PR_FALSE;
PRBool aborted_wait = PR_FALSE;
{ {
nsAutoLock locker(waitLock); nsAutoLock locker(waitLock);
@ -410,30 +462,26 @@ nsNSSHttpRequestSession::internal_send_receive_attempt(PRBool &retryable_error,
if (!request_canceled) if (!request_canceled)
{ {
if ((PRIntervalTime)(PR_IntervalNow() - start_time) > mTimeoutInterval) PRBool wantExit = nsSSLThread::exitRequested();
PRBool timeout =
(PRIntervalTime)(PR_IntervalNow() - start_time) > mTimeoutInterval;
if (wantExit || timeout)
{ {
request_canceled = PR_TRUE; request_canceled = PR_TRUE;
// but we'll to continue to wait for waitFlag
nsRefPtr<nsCancelHTTPDownloadEvent> cancelevent = new nsCancelHTTPDownloadEvent;
nsCOMPtr<nsIRunnable> cancelevent = new nsCancelHTTPDownloadEvent; cancelevent->mEvent = event;
rv = NS_DispatchToMainThread(cancelevent); rv = NS_DispatchToMainThread(cancelevent);
if (NS_FAILED(rv)) if (NS_FAILED(rv)) {
{
NS_WARNING("cannot post cancel event"); NS_WARNING("cannot post cancel event");
aborted_wait = PR_TRUE;
break;
} }
break;
} }
} }
} }
} }
if (aborted_wait)
{
// we couldn't cancel it, let's no longer reference it
nsSSLThread::rememberPendingHTTPRequest(nsnull);
}
if (request_canceled) if (request_canceled)
return SECFailure; return SECFailure;
@ -628,8 +676,6 @@ nsHTTPListener::OnStreamComplete(nsIStreamLoader* aLoader,
void nsHTTPListener::send_done_signal() void nsHTTPListener::send_done_signal()
{ {
nsSSLThread::rememberPendingHTTPRequest(nsnull);
mResponsibleForDoneSignal = PR_FALSE; mResponsibleForDoneSignal = PR_FALSE;
{ {

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

@ -1722,6 +1722,19 @@ nsNSSComponent::Init()
return rv; return rv;
} }
// Access our string bundles now, this prevents assertions from I/O
// - nsStandardURL not thread-safe
// - wrong thread: 'NS_IsMainThread()' in nsIOService.cpp
// when loading error strings on the SSL threads.
{
NS_NAMED_LITERAL_STRING(dummy_name, "dummy");
nsXPIDLString result;
mPIPNSSBundle->GetStringFromName(dummy_name.get(),
getter_Copies(result));
mNSSErrorsBundle->GetStringFromName(dummy_name.get(),
getter_Copies(result));
}
if (!mPrefBranch) { if (!mPrefBranch) {
mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID); mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
NS_ASSERTION(mPrefBranch, "Unable to get pref service"); NS_ASSERTION(mPrefBranch, "Unable to get pref service");

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

@ -204,6 +204,7 @@ nsNSSSocketInfo::nsNSSSocketInfo()
: mFd(nsnull), : mFd(nsnull),
mBlockingState(blocking_state_unknown), mBlockingState(blocking_state_unknown),
mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE), mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE),
mDocShellDependentStuffKnown(PR_FALSE),
mExternalErrorReporting(PR_FALSE), mExternalErrorReporting(PR_FALSE),
mForSTARTTLS(PR_FALSE), mForSTARTTLS(PR_FALSE),
mHandshakePending(PR_TRUE), mHandshakePending(PR_TRUE),
@ -319,15 +320,30 @@ nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
return NS_OK; return NS_OK;
} }
mCallbacks = aCallbacks;
mDocShellDependentStuffKnown = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsNSSSocketInfo::EnsureDocShellDependentStuffKnown()
{
if (mDocShellDependentStuffKnown)
return NS_OK;
if (!mCallbacks || nsSSLThread::exitRequested())
return NS_ERROR_FAILURE;
mDocShellDependentStuffKnown = PR_TRUE;
nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks; nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIInterfaceRequestor), NS_GET_IID(nsIInterfaceRequestor),
static_cast<nsIInterfaceRequestor*>(aCallbacks), static_cast<nsIInterfaceRequestor*>(mCallbacks),
NS_PROXY_SYNC, NS_PROXY_SYNC,
getter_AddRefs(proxiedCallbacks)); getter_AddRefs(proxiedCallbacks));
mCallbacks = proxiedCallbacks;
// Are we running within a context that wants external SSL error reporting? // Are we running within a context that wants external SSL error reporting?
// We'll look at the presence of a security UI object inside docshell. // We'll look at the presence of a security UI object inside docshell.
// If the docshell wants the lock icon, you'll get the ssl error pages, too. // If the docshell wants the lock icon, you'll get the ssl error pages, too.
@ -339,7 +355,7 @@ nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
nsCOMPtr<nsIDocShell> docshell; nsCOMPtr<nsIDocShell> docshell;
nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(mCallbacks)); nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(proxiedCallbacks));
if (item) if (item)
{ {
nsCOMPtr<nsIDocShellTreeItem> proxiedItem; nsCOMPtr<nsIDocShellTreeItem> proxiedItem;
@ -395,6 +411,8 @@ nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
nsresult nsresult
nsNSSSocketInfo::GetExternalErrorReporting(PRBool* state) nsNSSSocketInfo::GetExternalErrorReporting(PRBool* state)
{ {
nsresult rv = EnsureDocShellDependentStuffKnown();
NS_ENSURE_SUCCESS(rv, rv);
*state = mExternalErrorReporting; *state = mExternalErrorReporting;
return NS_OK; return NS_OK;
} }
@ -465,10 +483,17 @@ NS_IMETHODIMP nsNSSSocketInfo::GetInterface(const nsIID & uuid, void * *result)
rv = ir->GetInterface(uuid, result); rv = ir->GetInterface(uuid, result);
} else { } else {
// Proxy of the channel callbacks should probably go here, rather if (nsSSLThread::exitRequested())
// than in the password callback code return NS_ERROR_FAILURE;
rv = mCallbacks->GetInterface(uuid, result); nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIInterfaceRequestor),
mCallbacks,
NS_PROXY_SYNC,
getter_AddRefs(proxiedCallbacks));
rv = proxiedCallbacks->GetInterface(uuid, result);
} }
return rv; return rv;
} }
@ -619,6 +644,8 @@ nsresult nsNSSSocketInfo::SetFileDescPtr(PRFileDesc* aFilePtr)
nsresult nsNSSSocketInfo::GetPreviousCert(nsIX509Cert** _result) nsresult nsNSSSocketInfo::GetPreviousCert(nsIX509Cert** _result)
{ {
NS_ENSURE_ARG_POINTER(_result); NS_ENSURE_ARG_POINTER(_result);
nsresult rv = EnsureDocShellDependentStuffKnown();
NS_ENSURE_SUCCESS(rv, rv);
*_result = mPreviousCert; *_result = mPreviousCert;
NS_IF_ADDREF(*_result); NS_IF_ADDREF(*_result);
@ -1139,6 +1166,9 @@ displayAlert(nsAFlatString &formattedString, nsNSSSocketInfo *infoObject)
// The interface requestor object may not be safe, so proxy the call to get // The interface requestor object may not be safe, so proxy the call to get
// the nsIPrompt. // the nsIPrompt.
if (nsSSLThread::exitRequested())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks; nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIInterfaceRequestor), NS_GET_IID(nsIInterfaceRequestor),
@ -1173,6 +1203,10 @@ nsHandleSSLError(nsNSSSocketInfo *socketInfo, PRInt32 err)
return NS_OK; return NS_OK;
} }
if (nsSSLThread::exitRequested()) {
return NS_ERROR_FAILURE;
}
nsresult rv; nsresult rv;
NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID); NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID);
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(nssComponentCID, &rv)); nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(nssComponentCID, &rv));
@ -1187,9 +1221,16 @@ nsHandleSSLError(nsNSSSocketInfo *socketInfo, PRInt32 err)
socketInfo->GetPort(&port); socketInfo->GetPort(&port);
// Try to get a nsISSLErrorListener implementation from the socket consumer. // Try to get a nsISSLErrorListener implementation from the socket consumer.
nsCOMPtr<nsIInterfaceRequestor> callbacks; nsCOMPtr<nsIInterfaceRequestor> cb;
socketInfo->GetNotificationCallbacks(getter_AddRefs(callbacks)); socketInfo->GetNotificationCallbacks(getter_AddRefs(cb));
if (callbacks) { if (cb) {
nsCOMPtr<nsIInterfaceRequestor> callbacks;
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIInterfaceRequestor),
cb,
NS_PROXY_SYNC,
getter_AddRefs(callbacks));
nsCOMPtr<nsISSLErrorListener> sel = do_GetInterface(callbacks); nsCOMPtr<nsISSLErrorListener> sel = do_GetInterface(callbacks);
if (sel) { if (sel) {
nsISSLErrorListener *proxy_sel = nsnull; nsISSLErrorListener *proxy_sel = nsnull;
@ -2743,6 +2784,9 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket)
if (!infoObject) if (!infoObject)
return SECFailure; return SECFailure;
if (nsSSLThread::exitRequested())
return cancel_and_failure(infoObject);
CERTCertificate *peerCert = nsnull; CERTCertificate *peerCert = nsnull;
CERTCertificateCleaner peerCertCleaner(peerCert); CERTCertificateCleaner peerCertCleaner(peerCert);
peerCert = SSL_PeerCertificate(sslSocket); peerCert = SSL_PeerCertificate(sslSocket);
@ -2911,9 +2955,16 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket)
nsresult rv; nsresult rv;
// Try to get a nsIBadCertListener2 implementation from the socket consumer. // Try to get a nsIBadCertListener2 implementation from the socket consumer.
nsCOMPtr<nsIInterfaceRequestor> callbacks; nsCOMPtr<nsIInterfaceRequestor> cb;
infoObject->GetNotificationCallbacks(getter_AddRefs(callbacks)); infoObject->GetNotificationCallbacks(getter_AddRefs(cb));
if (callbacks) { if (cb) {
nsCOMPtr<nsIInterfaceRequestor> callbacks;
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIInterfaceRequestor),
cb,
NS_PROXY_SYNC,
getter_AddRefs(callbacks));
nsCOMPtr<nsIBadCertListener2> bcl = do_GetInterface(callbacks); nsCOMPtr<nsIBadCertListener2> bcl = do_GetInterface(callbacks);
if (bcl) { if (bcl) {
nsIBadCertListener2 *proxy_bcl = nsnull; nsIBadCertListener2 *proxy_bcl = nsnull;

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

@ -198,14 +198,15 @@ protected:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks; nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
PRFileDesc* mFd; PRFileDesc* mFd;
nsCOMPtr<nsIX509Cert> mCert; nsCOMPtr<nsIX509Cert> mCert;
nsCOMPtr<nsIX509Cert> mPreviousCert; nsCOMPtr<nsIX509Cert> mPreviousCert; // DocShellDependent
enum { enum {
blocking_state_unknown, is_nonblocking_socket, is_blocking_socket blocking_state_unknown, is_nonblocking_socket, is_blocking_socket
} mBlockingState; } mBlockingState;
PRUint32 mSecurityState; PRUint32 mSecurityState;
nsString mShortDesc; nsString mShortDesc;
nsString mErrorMessage; nsString mErrorMessage;
PRPackedBool mExternalErrorReporting; PRPackedBool mDocShellDependentStuffKnown;
PRPackedBool mExternalErrorReporting; // DocShellDependent
PRPackedBool mForSTARTTLS; PRPackedBool mForSTARTTLS;
PRPackedBool mHandshakePending; PRPackedBool mHandshakePending;
PRPackedBool mCanceled; PRPackedBool mCanceled;
@ -223,6 +224,8 @@ protected:
nsSSLSocketThreadData *mThreadData; nsSSLSocketThreadData *mThreadData;
nsresult EnsureDocShellDependentStuffKnown();
private: private:
virtual void virtualDestroyNSSReference(); virtual void virtualDestroyNSSReference();
void destructorSafeDestroyNSSReference(); void destructorSafeDestroyNSSReference();

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

@ -1120,28 +1120,14 @@ void nsSSLThread::Run(void)
} }
} }
void nsSSLThread::rememberPendingHTTPRequest(nsIRequest *aRequest) PRBool nsSSLThread::exitRequested()
{ {
if (!ssl_thread_singleton) if (!ssl_thread_singleton)
return; return PR_FALSE;
nsAutoLock threadLock(ssl_thread_singleton->mMutex); // no lock
ssl_thread_singleton->mPendingHTTPRequest = aRequest; return ssl_thread_singleton->mExitRequested;
}
void nsSSLThread::cancelPendingHTTPRequest()
{
if (!ssl_thread_singleton)
return;
nsAutoLock threadLock(ssl_thread_singleton->mMutex);
if (ssl_thread_singleton->mPendingHTTPRequest)
{
ssl_thread_singleton->mPendingHTTPRequest->Cancel(NS_ERROR_ABORT);
ssl_thread_singleton->mPendingHTTPRequest = nsnull;
}
} }
nsSSLThread *nsSSLThread::ssl_thread_singleton = nsnull; nsSSLThread *nsSSLThread::ssl_thread_singleton = nsnull;

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

@ -152,9 +152,7 @@ public:
static nsresult requestActivateSSL(nsNSSSocketInfo *si); static nsresult requestActivateSSL(nsNSSSocketInfo *si);
// Called from either Necko or SSL thread. static PRBool exitRequested();
static void rememberPendingHTTPRequest(nsIRequest *aRequest);
static void cancelPendingHTTPRequest();
}; };
#endif //_NSSSLTHREAD_H_ #endif //_NSSSLTHREAD_H_