зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
bfdb68b9a2
Коммит
cfd263a72b
|
@ -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_
|
||||||
|
|
Загрузка…
Ссылка в новой задаче