From 078a401ea51c639073cbbff35135d7fc563a95bd Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Wed, 9 Jan 2013 10:17:32 -0500 Subject: [PATCH] bug 796475 - proxy auth cancelation rendering fix r=jduell --HG-- extra : rebase_source : 83d6ad3d15bae973c8a09bca02a8d86578467345 --- netwerk/protocol/http/nsHttpChannel.cpp | 21 +++++++++-- netwerk/protocol/http/nsHttpChannel.h | 1 + netwerk/test/unit/test_auth_proxy.js | 4 ++- .../passwordmgr/test/test_prompt_async.html | 36 ++++++++++++------- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index eeb7e4086c3e..c36905e19052 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -291,6 +291,7 @@ nsHttpChannel::nsHttpChannel() , mCachedContentIsPartial(false) , mTransactionReplaced(false) , mAuthRetryPending(false) + , mProxyAuthPending(false) , mResuming(false) , mInitedCacheEntry(false) , mFallbackChannel(false) @@ -1277,6 +1278,9 @@ nsHttpChannel::ProcessResponse() // authentication prompt has been invoked and result // is expected asynchronously mAuthRetryPending = true; + if (httpStatus == 407 || mTransaction->ProxyConnectFailed()) + mProxyAuthPending = true; + // suspend the transaction pump to stop receiving the // unauthenticated content data. We will throw that data // away when user provides credentials or resume the pump @@ -4134,6 +4138,7 @@ NS_IMETHODIMP nsHttpChannel::OnAuthAvailable() // triggers process of throwing away the unauthenticated data already // coming from the network mAuthRetryPending = true; + mProxyAuthPending = false; LOG(("Resuming the transaction, we got credentials from user")); mTransactionPump->Resume(); @@ -4145,12 +4150,23 @@ NS_IMETHODIMP nsHttpChannel::OnAuthCancelled(bool userCancel) LOG(("nsHttpChannel::OnAuthCancelled [this=%p]", this)); if (mTransactionPump) { + // If the channel is trying to authenticate to a proxy and + // that was canceled we cannot show the http response body + // from the 40x as that might mislead the user into thinking + // it was a end host response instead of a proxy reponse. + // This must check explicitly whether a proxy auth was being done + // because we do want to show the content if this is an error from + // the origin server. + if (mProxyAuthPending) + Cancel(NS_ERROR_PROXY_CONNECTION_REFUSED); + // ensure call of OnStartRequest of the current listener here, // it would not be called otherwise at all nsresult rv = CallOnStartRequest(); // drop mAuthRetryPending flag and resume the transaction - // this resumes load of the unauthenticated content data + // this resumes load of the unauthenticated content data (which + // may have been canceled if we don't want to show it) mAuthRetryPending = false; LOG(("Resuming the transaction, user cancelled the auth dialog")); mTransactionPump->Resume(); @@ -4158,7 +4174,8 @@ NS_IMETHODIMP nsHttpChannel::OnAuthCancelled(bool userCancel) if (NS_FAILED(rv)) mTransactionPump->Cancel(rv); } - + + mProxyAuthPending = false; return NS_OK; } diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index 8825816ae8e5..b2ef1e929bd4 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -331,6 +331,7 @@ private: uint32_t mCachedContentIsPartial : 1; uint32_t mTransactionReplaced : 1; uint32_t mAuthRetryPending : 1; + uint32_t mProxyAuthPending : 1; uint32_t mResuming : 1; uint32_t mInitedCacheEntry : 1; // True if we are loading a fallback cache entry from the diff --git a/netwerk/test/unit/test_auth_proxy.js b/netwerk/test/unit/test_auth_proxy.js index 3f6adfdc0c7c..888dc541638f 100644 --- a/netwerk/test/unit/test_auth_proxy.js +++ b/netwerk/test/unit/test_auth_proxy.js @@ -165,7 +165,9 @@ var listener = { onStartRequest: function test_onStartR(request, ctx) { try { - if (!Components.isSuccessCode(request.status)) + // Proxy auth cancellation return failures to avoid spoofing + if (!Components.isSuccessCode(request.status) && + (this.expectedCode != 407)) do_throw("Channel should have a success code!"); if (!(request instanceof Ci.nsIHttpChannel)) diff --git a/toolkit/components/passwordmgr/test/test_prompt_async.html b/toolkit/components/passwordmgr/test/test_prompt_async.html index eab918c4b17a..716476289bb1 100644 --- a/toolkit/components/passwordmgr/test/test_prompt_async.html +++ b/toolkit/components/passwordmgr/test/test_prompt_async.html @@ -266,7 +266,15 @@ ok(true, "doTest testNum 4"); expectedLoads = 1; expectedDialogs = 2; - iframe1Doc.location.reload(); + iframe1.src = exampleCom + "authenticate.sjs?"+ + "user=user4name&"+ + "pass=user4pass&"+ + "realm=mochirealm4&"+ + "proxy_user=proxy_user3&"+ + "proxy_pass=proxy_pass3&"+ + "proxy_realm=proxy_realm3"; + + break; case 5: @@ -295,7 +303,14 @@ ok(true, "doTest testNum 6"); expectedLoads = 1; expectedDialogs = 2; - iframe1Doc.location.reload(); + iframe1.src = exampleCom + "authenticate.sjs?"+ + "user=user5name&"+ + "pass=user5pass&"+ + "realm=mochirealm5&"+ + "proxy_user=proxy_user4&"+ + "proxy_pass=proxy_pass4&"+ + "proxy_realm=proxy_realm4&"+ + "huge=1"; break; case 7: @@ -346,6 +361,7 @@ case 3: dialog.cancelDialog(); + setTimeout(onFrameLoad(), 10); // there are no successful frames for test 3 break; case 4: @@ -357,6 +373,7 @@ case 5: dialog.cancelDialog(); + setTimeout(onFrameLoad(), 10); // there are no successful frames for test 5 break; case 6: @@ -435,11 +452,9 @@ case 3: ok(true, "doCheck testNum 3"); is(monitor.windowsRegistered, 1, "Registered 1 open dialog"); - var authok1 = iframe1Doc.getElementById("ok").textContent; - var proxyok1 = iframe1Doc.getElementById("proxy").textContent; - is(authok1, "FAIL", "WWW Authorization FAILED, frame1"); - is(proxyok1, "FAIL", "Proxy Authorization FAILED, frame1"); + // ensure that the page content is not displayed on failed proxy auth + is(iframe1Doc.getElementById("ok"), undefined, "frame did not load"); break; case 4: @@ -455,14 +470,9 @@ case 5: ok(true, "doCheck testNum 5"); is(monitor.windowsRegistered, 1, "Registered 1 open dialog"); - var authok1 = iframe1Doc.getElementById("ok").textContent; - var proxyok1 = iframe1Doc.getElementById("proxy").textContent; - var footnote = iframe1Doc.getElementById("footnote").textContent; - is(authok1, "FAIL", "WWW Authorization FAILED, frame1"); - is(proxyok1, "FAIL", "Proxy Authorization FAILED, frame1"); - is(footnote, "This is a footnote after the huge content fill", - "Footnote present and loaded completely"); + // ensure that the page content is not displayed on failed proxy auth + is(iframe1Doc.getElementById("footnote"), undefined, "frame did not load"); break; case 6: