bug 796475 - proxy auth cancelation rendering fix r=jduell

--HG--
extra : rebase_source : 83d6ad3d15bae973c8a09bca02a8d86578467345
This commit is contained in:
Patrick McManus 2013-01-09 10:17:32 -05:00
parent 7faecaa2b1
commit 078a401ea5
4 changed files with 46 additions and 16 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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))

View File

@ -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: