Index: net/http/http_proxy_client_socket_pool.cc |
=================================================================== |
--- net/http/http_proxy_client_socket_pool.cc (revision 117986) |
+++ net/http/http_proxy_client_socket_pool.cc (working copy) |
@@ -28,6 +28,15 @@ |
namespace net { |
+namespace { |
+ |
+std::string GetProxyUrl(const scoped_refptr<HttpProxySocketParams>& params) { |
cbentzel
2012/01/20 02:09:46
NOTE TO SELF: Make sure this is ok.
Ryan Hamilton
2012/01/20 04:20:04
The self there is you, not me, right? (I think it
cbentzel
2012/01/20 11:15:46
Yeah, it was a note to me while doing the review.
|
+ return (params->ssl_params() != NULL ? "https://" : "http://") |
+ + params->destination().host_port_pair().ToString(); |
+} |
+ |
+} // namespace |
+ |
HttpProxySocketParams::HttpProxySocketParams( |
const scoped_refptr<TransportSocketParams>& transport_params, |
const scoped_refptr<SSLSocketParams>& ssl_params, |
@@ -37,7 +46,8 @@ |
HttpAuthCache* http_auth_cache, |
HttpAuthHandlerFactory* http_auth_handler_factory, |
SpdySessionPool* spdy_session_pool, |
- bool tunnel) |
+ bool tunnel, |
+ TunnelAuthCallback auth_needed_callback) |
: transport_params_(transport_params), |
ssl_params_(ssl_params), |
spdy_session_pool_(spdy_session_pool), |
@@ -46,7 +56,8 @@ |
endpoint_(endpoint), |
http_auth_cache_(tunnel ? http_auth_cache : NULL), |
http_auth_handler_factory_(tunnel ? http_auth_handler_factory : NULL), |
- tunnel_(tunnel) { |
+ tunnel_(tunnel), |
+ auth_needed_callback_(auth_needed_callback) { |
DCHECK((transport_params == NULL && ssl_params != NULL) || |
(transport_params != NULL && ssl_params == NULL)); |
if (transport_params_) |
@@ -87,7 +98,14 @@ |
callback_(base::Bind(&HttpProxyConnectJob::OnIOComplete, |
base::Unretained(this)))), |
using_spdy_(false), |
- protocol_negotiated_(SSLClientSocket::kProtoUnknown) { |
+ protocol_negotiated_(SSLClientSocket::kProtoUnknown), |
+ auth_(params->tunnel() ? |
+ new HttpAuthController(HttpAuth::AUTH_PROXY, |
+ GURL(GetProxyUrl(params_)), |
+ params->http_auth_cache(), |
+ params->http_auth_handler_factory()) |
+ : NULL), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) { |
} |
HttpProxyConnectJob::~HttpProxyConnectJob() {} |
@@ -103,6 +121,8 @@ |
case STATE_HTTP_PROXY_CONNECT_COMPLETE: |
case STATE_SPDY_PROXY_CREATE_STREAM: |
case STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE: |
+ case STATE_RESTART_WITH_AUTH: |
+ case STATE_RESTART_WITH_AUTH_COMPLETE: |
return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; |
default: |
NOTREACHED(); |
@@ -159,6 +179,13 @@ |
case STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE: |
rv = DoSpdyProxyCreateStreamComplete(rv); |
break; |
+ case STATE_RESTART_WITH_AUTH: |
+ DCHECK_EQ(OK, rv); |
+ rv = DoRestartWithAuth(); |
+ break; |
+ case STATE_RESTART_WITH_AUTH_COMPLETE: |
+ rv = DoRestartWithAuthComplete(rv); |
+ break; |
default: |
NOTREACHED() << "bad state"; |
rv = ERR_FAILED; |
@@ -266,8 +293,7 @@ |
params_->user_agent(), |
params_->endpoint(), |
proxy_server, |
- params_->http_auth_cache(), |
- params_->http_auth_handler_factory(), |
+ auth_, |
params_->tunnel(), |
using_spdy_, |
protocol_negotiated_, |
@@ -275,8 +301,57 @@ |
return transport_socket_->Connect(callback_); |
} |
+void HttpProxyConnectJob::HandleProxyAuthChallenge() { |
+ next_state_ = STATE_RESTART_WITH_AUTH; |
+ params_->auth_needed_callback().Run( |
+ *transport_socket_->GetConnectResponseInfo(), |
+ transport_socket_->auth_controller(), |
+ callback_); |
+} |
+ |
+int HttpProxyConnectJob::DoRestartWithAuth() { |
+ // If no auth was added to the controller, then we should abort. |
+ next_state_ = STATE_RESTART_WITH_AUTH_COMPLETE; |
+ if (!transport_socket_->auth_controller()->HaveAuth()) { |
+ return ERR_PROXY_AUTH_REQUESTED; |
+ } |
+ |
+ return transport_socket_->RestartWithAuth(callback_); |
+} |
+ |
+int HttpProxyConnectJob::DoRestartWithAuthComplete(int result) { |
+ if (result == ERR_NO_KEEP_ALIVE_ON_AUTH_RESTART) { |
+ if (params_->transport_params()) |
+ next_state_ = STATE_TCP_CONNECT; |
+ else |
+ next_state_ = STATE_SSL_CONNECT; |
+ return OK; |
+ } |
+ |
+ if (result != OK) { |
+ if (result == ERR_PROXY_AUTH_REQUESTED || |
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { |
+ set_socket(transport_socket_.release()); |
+ } |
+ return result; |
+ } |
+ |
+ next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE; |
+ return OK; |
+} |
+ |
int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) { |
- if (result == OK || result == ERR_PROXY_AUTH_REQUESTED || |
+ // Handle a proxy auth challenge by asynchronously invoking the callback. |
+ // We do this asynchronously so that the caller is notified of job |
+ // completion only via NotifyDelegateOfCompletion. |
+ if (result == ERR_PROXY_AUTH_REQUESTED) { |
+ MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&HttpProxyConnectJob::HandleProxyAuthChallenge, |
+ ptr_factory_.GetWeakPtr())); |
+ return ERR_IO_PENDING; |
+ } |
+ if (result == OK || |
result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { |
set_socket(transport_socket_.release()); |
} |
@@ -326,8 +401,7 @@ |
params_->endpoint(), |
params_->request_url(), |
params_->destination().host_port_pair(), |
- params_->http_auth_cache(), |
- params_->http_auth_handler_factory())); |
+ auth_)); |
return transport_socket_->Connect(callback_); |
} |