15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_proxy_client_socket_pool.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_proxy_client_socket.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_pool_base.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_client_socket.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_client_socket_pool.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/transport_client_socket_pool.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_proxy_client_socket.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session_pool.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_stream.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxySocketParams::HttpProxySocketParams(
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<TransportSocketParams>& transport_params,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<SSLSocketParams>& ssl_params,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& request_url,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_agent,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& endpoint,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthCache* http_auth_cache,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthHandlerFactory* http_auth_handler_factory,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdySessionPool* spdy_session_pool,
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool tunnel,
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ProxyDelegate* proxy_delegate)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : transport_params_(transport_params),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_params_(ssl_params),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spdy_session_pool_(spdy_session_pool),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_url_(request_url),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_agent_(user_agent),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      endpoint_(endpoint),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_auth_cache_(tunnel ? http_auth_cache : NULL),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_auth_handler_factory_(tunnel ? http_auth_handler_factory : NULL),
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      tunnel_(tunnel),
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      proxy_delegate_(proxy_delegate) {
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK((transport_params.get() == NULL && ssl_params.get() != NULL) ||
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         (transport_params.get() != NULL && ssl_params.get() == NULL));
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transport_params_.get()) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ignore_limits_ = transport_params->ignore_limits();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ignore_limits_ = ssl_params->ignore_limits();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HostResolver::RequestInfo& HttpProxySocketParams::destination() const {
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (transport_params_.get() == NULL) {
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return ssl_params_->GetDirectConnectionParams()->destination();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_params_->destination();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxySocketParams::~HttpProxySocketParams() {}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HttpProxyConnectJobs will time out after this many seconds.  Note this is on
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// top of the timeout for the transport socket.
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// TODO(kundaji): Proxy connect timeout should be independent of platform and be
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// based on proxy. Bug http://crbug.com/407446.
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_ANDROID) || defined(OS_IOS)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kHttpProxyConnectJobTimeoutInSeconds = 10;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kHttpProxyConnectJobTimeoutInSeconds = 30;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyConnectJob::HttpProxyConnectJob(
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& group_name,
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    RequestPriority priority,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<HttpProxySocketParams>& params,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::TimeDelta& timeout_duration,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportClientSocketPool* transport_pool,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLClientSocketPool* ssl_pool,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostResolver* host_resolver,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Delegate* delegate,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log)
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : ConnectJob(group_name, timeout_duration, priority, delegate,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params_(params),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_pool_(transport_pool),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_pool_(ssl_pool),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_(host_resolver),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      using_spdy_(false),
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      protocol_negotiated_(kProtoUnknown),
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_ptr_factory_(this) {
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback_= base::Bind(&HttpProxyConnectJob::OnIOComplete,
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           weak_ptr_factory_.GetWeakPtr());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyConnectJob::~HttpProxyConnectJob() {}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState HttpProxyConnectJob::GetLoadState() const {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (next_state_) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_TCP_CONNECT:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_TCP_CONNECT_COMPLETE:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_SSL_CONNECT:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_SSL_CONNECT_COMPLETE:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return transport_socket_handle_->GetLoadState();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_HTTP_PROXY_CONNECT:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_HTTP_PROXY_CONNECT_COMPLETE:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_SPDY_PROXY_CREATE_STREAM:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return LOAD_STATE_IDLE;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_response_info_.cert_request_info.get()) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handle->set_ssl_error_response_info(error_response_info_);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handle->set_is_ssl_error(true);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyConnectJob::OnIOComplete(int result) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoLoop(result);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDelegateOfCompletion(rv);  // Deletes |this|
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoLoop(int result) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(next_state_, STATE_NONE);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = result;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_state_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_NONE;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TCP_CONNECT:
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTransportConnect();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TCP_CONNECT_COMPLETE:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTransportConnectComplete(rv);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SSL_CONNECT:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSSLConnect();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SSL_CONNECT_COMPLETE:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSSLConnectComplete(rv);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HTTP_PROXY_CONNECT:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHttpProxyConnect();
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HTTP_PROXY_CONNECT_COMPLETE:
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHttpProxyConnectComplete(rv);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SPDY_PROXY_CREATE_STREAM:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSpdyProxyCreateStream();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSpdyProxyCreateStreamComplete(rv);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "bad state";
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_FAILED;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoTransportConnect() {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TCP_CONNECT_COMPLETE;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_socket_handle_.reset(new ClientSocketHandle());
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return transport_socket_handle_->Init(group_name(),
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        params_->transport_params(),
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        priority(),
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        callback_,
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        transport_pool_,
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        net_log());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoTransportConnectComplete(int result) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_PROXY_CONNECTION_FAILED;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the timer to just the length of time allowed for HttpProxy handshake
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so that a fast TCP connection plus a slow HttpProxy failure doesn't take
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // longer to timeout than it should.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetTimer(base::TimeDelta::FromSeconds(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kHttpProxyConnectJobTimeoutInSeconds));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_HTTP_PROXY_CONNECT;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoSSLConnect() {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params_->tunnel()) {
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SpdySessionKey key(params_->destination().host_port_pair(),
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       ProxyServer::Direct(),
212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                       PRIVACY_MODE_DISABLED);
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (params_->spdy_session_pool()->FindAvailableSession(key, net_log())) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      using_spdy_ = true;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_SPDY_PROXY_CREATE_STREAM;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OK;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SSL_CONNECT_COMPLETE;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_socket_handle_.reset(new ClientSocketHandle());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_handle_->Init(
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      group_name(), params_->ssl_params(), priority(), callback_,
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ssl_pool_, net_log());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoSSLConnectComplete(int result) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_response_info_ = transport_socket_handle_->ssl_error_response_info();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(error_response_info_.cert_request_info.get());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_response_info_.cert_request_info->is_proxy = true;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCertificateError(result)) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (params_->ssl_params()->load_flags() & LOAD_IGNORE_ALL_CERT_ERRORS) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = OK;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(rch): allow the user to deal with proxy cert errors in the
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // same way as server cert errors.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_socket_handle_->socket()->Disconnect();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PROXY_CERTIFICATE_INVALID;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // A SPDY session to the proxy completed prior to resolving the proxy
2446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // hostname. Surface this error, and allow the delegate to retry.
2456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // See crbug.com/334413.
2466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) {
2476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    DCHECK(!transport_socket_handle_->socket());
2486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return ERR_SPDY_SESSION_ALREADY_EXISTS;
2496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (transport_socket_handle_->socket())
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_socket_handle_->socket()->Disconnect();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_PROXY_CONNECTION_FAILED;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocket* ssl =
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<SSLClientSocket*>(transport_socket_handle_->socket());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using_spdy_ = ssl->was_spdy_negotiated();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protocol_negotiated_ = ssl->GetNegotiatedProtocol();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the timer to just the length of time allowed for HttpProxy handshake
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so that a fast SSL connection plus a slow HttpProxy failure doesn't take
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // longer to timeout than it should.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetTimer(base::TimeDelta::FromSeconds(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kHttpProxyConnectJobTimeoutInSeconds));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rch): If we ever decide to implement a "trusted" SPDY proxy
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (one that we speak SPDY over SSL to, but to which we send HTTPS
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request directly instead of through CONNECT tunnels, then we
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to add a predicate to this if statement so we fall through
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the else case. (HttpProxyClientSocket currently acts as
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a "trusted" SPDY proxy).
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (using_spdy_ && params_->tunnel()) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SPDY_PROXY_CREATE_STREAM;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_HTTP_PROXY_CONNECT;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoHttpProxyConnect() {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HostResolver::RequestInfo& tcp_destination = params_->destination();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HostPortPair& proxy_server = tcp_destination.host_port_pair();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a HttpProxy connection on top of the tcp socket.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_socket_.reset(
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new HttpProxyClientSocket(transport_socket_handle_.release(),
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->request_url(),
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->user_agent(),
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->endpoint(),
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                proxy_server,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->http_auth_cache(),
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->http_auth_handler_factory(),
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->tunnel(),
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                using_spdy_,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                protocol_negotiated_,
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                params_->proxy_delegate(),
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                params_->ssl_params().get() != NULL));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->Connect(callback_);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK || result == ERR_PROXY_AUTH_REQUESTED ||
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SetSocket(transport_socket_.PassAs<StreamSocket>());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoSpdyProxyCreateStream() {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(using_spdy_);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(params_->tunnel());
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdySessionKey key(params_->destination().host_port_pair(),
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     ProxyServer::Direct(),
316e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                     PRIVACY_MODE_DISABLED);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdySessionPool* spdy_pool = params_->spdy_session_pool();
318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> spdy_session =
3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      spdy_pool->FindAvailableSession(key, net_log());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible that a session to the proxy has recently been created
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (spdy_session) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (transport_socket_handle_.get()) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (transport_socket_handle_->socket())
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        transport_socket_handle_->socket()->Disconnect();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_socket_handle_->Reset();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a session direct to the proxy itself
329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    spdy_session =
330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        spdy_pool->CreateAvailableSessionFromSocket(
331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            key, transport_socket_handle_.Pass(),
332effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            net_log(), OK, /*using_ssl_*/ true);
333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DCHECK(spdy_session);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE;
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return spdy_stream_request_.StartRequest(SPDY_BIDIRECTIONAL_STREAM,
3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                           spdy_session,
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                           params_->request_url(),
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                           priority(),
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                           spdy_session->net_log(),
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                           callback_);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::DoSpdyProxyCreateStreamComplete(int result) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE;
350a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream = spdy_stream_request_.ReleaseStream();
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(stream.get());
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |transport_socket_| will set itself as |stream|'s delegate.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_socket_.reset(
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new SpdyProxyClientSocket(stream,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->user_agent(),
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->endpoint(),
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->request_url(),
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->destination().host_port_pair(),
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                net_log(),
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->http_auth_cache(),
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                params_->http_auth_handler_factory()));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->Connect(callback_);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyConnectJob::ConnectInternal() {
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (params_->transport_params().get()) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_TCP_CONNECT;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SSL_CONNECT;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DoLoop(OK);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocketPool::
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyConnectJobFactory::HttpProxyConnectJobFactory(
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportClientSocketPool* transport_pool,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLClientSocketPool* ssl_pool,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostResolver* host_resolver,
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ProxyDelegate* proxy_delegate,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : transport_pool_(transport_pool),
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_pool_(ssl_pool),
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_resolver_(host_resolver),
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      proxy_delegate_(proxy_delegate),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_(net_log) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta max_pool_timeout = base::TimeDelta();
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// TODO(kundaji): Proxy connect timeout should be independent of platform and be
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// based on proxy. Bug http://crbug.com/407446.
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if (defined(OS_ANDROID) || defined(OS_IOS))
391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#else
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_pool_)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_pool_timeout = transport_pool_->ConnectionTimeout();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_pool_)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_pool_timeout = std::max(max_pool_timeout,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                ssl_pool_->ConnectionTimeout());
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout_ = max_pool_timeout +
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta::FromSeconds(kHttpProxyConnectJobTimeoutInSeconds);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<ConnectJob>
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& group_name,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PoolBase::Request& request,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConnectJob::Delegate* delegate) const {
4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return scoped_ptr<ConnectJob>(new HttpProxyConnectJob(group_name,
4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        request.priority(),
4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        request.params(),
4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        ConnectionTimeout(),
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        transport_pool_,
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        ssl_pool_,
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        host_resolver_,
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        delegate,
4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                        net_log_));
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TimeDelta
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocketPool::HttpProxyConnectJobFactory::ConnectionTimeout(
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ) const {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return timeout_;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocketPool::HttpProxyClientSocketPool(
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int max_sockets,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int max_sockets_per_group,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketPoolHistograms* histograms,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostResolver* host_resolver,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportClientSocketPool* transport_pool,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLClientSocketPool* ssl_pool,
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ProxyDelegate* proxy_delegate,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : transport_pool_(transport_pool),
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_pool_(ssl_pool),
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base_(this, max_sockets, max_sockets_per_group, histograms,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ClientSocketPool::unused_idle_socket_timeout(),
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ClientSocketPool::used_idle_socket_timeout(),
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new HttpProxyConnectJobFactory(transport_pool,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           ssl_pool,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           host_resolver,
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           proxy_delegate,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           net_log)) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should always have a |transport_pool_| except in unit tests.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_pool_)
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base_.AddLowerLayeredPool(transport_pool_);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_pool_)
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base_.AddLowerLayeredPool(ssl_pool_);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocketPool::~HttpProxyClientSocketPool() {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocketPool::RequestSocket(
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& group_name, const void* socket_params,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RequestPriority priority, ClientSocketHandle* handle,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& callback, const BoundNetLog& net_log) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_refptr<HttpProxySocketParams>* casted_socket_params =
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<const scoped_refptr<HttpProxySocketParams>*>(socket_params);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_.RequestSocket(group_name, *casted_socket_params, priority,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             handle, callback, net_log);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocketPool::RequestSockets(
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& group_name,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* params,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_sockets,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_refptr<HttpProxySocketParams>* casted_params =
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<const scoped_refptr<HttpProxySocketParams>*>(params);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocketPool::CancelRequest(
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& group_name,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketHandle* handle) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base_.CancelRequest(group_name, handle);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocketPool::ReleaseSocket(const std::string& group_name,
4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              scoped_ptr<StreamSocket> socket,
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              int id) {
4853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base_.ReleaseSocket(group_name, socket.Pass(), id);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpProxyClientSocketPool::FlushWithError(int error) {
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base_.FlushWithError(error);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocketPool::CloseIdleSockets() {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base_.CloseIdleSockets();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocketPool::IdleSocketCount() const {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_.idle_socket_count();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocketPool::IdleSocketCountInGroup(
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& group_name) const {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_.IdleSocketCountInGroup(group_name);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState HttpProxyClientSocketPool::GetLoadState(
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& group_name, const ClientSocketHandle* handle) const {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_.GetLoadState(group_name, handle);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::DictionaryValue* HttpProxyClientSocketPool::GetInfoAsValue(
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name,
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& type,
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool include_nested_pools) const {
5147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* dict = base_.GetInfoAsValue(name, type);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (include_nested_pools) {
5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::ListValue* list = new base::ListValue();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (transport_pool_) {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   "transport_socket_pool",
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   true));
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ssl_pool_) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      list->Append(ssl_pool_->GetInfoAsValue("ssl_socket_pool",
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             "ssl_socket_pool",
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             true));
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set("nested_pools", list);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TimeDelta HttpProxyClientSocketPool::ConnectionTimeout() const {
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_.ConnectionTimeout();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClientSocketPoolHistograms* HttpProxyClientSocketPool::histograms() const {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base_.histograms();
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool HttpProxyClientSocketPool::IsStalled() const {
5413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return base_.IsStalled();
5423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void HttpProxyClientSocketPool::AddHigherLayeredPool(
5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    HigherLayeredPool* higher_pool) {
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base_.AddHigherLayeredPool(higher_pool);
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void HttpProxyClientSocketPool::RemoveHigherLayeredPool(
5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    HigherLayeredPool* higher_pool) {
5513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base_.RemoveHigherLayeredPool(higher_pool);
5523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocketPool::CloseOneIdleConnection() {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base_.CloseOneIdleSocket())
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return base_.CloseOneIdleConnectionInHigherLayeredPool();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
561