Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/socket/ssl_client_socket_pool.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/metrics/field_trial.h"
     10 #include "base/metrics/histogram.h"
     11 #include "base/metrics/sparse_histogram.h"
     12 #include "base/values.h"
     13 #include "net/base/host_port_pair.h"
     14 #include "net/base/net_errors.h"
     15 #include "net/http/http_proxy_client_socket.h"
     16 #include "net/http/http_proxy_client_socket_pool.h"
     17 #include "net/socket/client_socket_factory.h"
     18 #include "net/socket/client_socket_handle.h"
     19 #include "net/socket/socks_client_socket_pool.h"
     20 #include "net/socket/ssl_client_socket.h"
     21 #include "net/socket/transport_client_socket_pool.h"
     22 #include "net/ssl/ssl_cert_request_info.h"
     23 #include "net/ssl/ssl_connection_status_flags.h"
     24 #include "net/ssl/ssl_info.h"
     25 
     26 namespace net {
     27 
     28 SSLSocketParams::SSLSocketParams(
     29     const scoped_refptr<TransportSocketParams>& direct_params,
     30     const scoped_refptr<SOCKSSocketParams>& socks_proxy_params,
     31     const scoped_refptr<HttpProxySocketParams>& http_proxy_params,
     32     const HostPortPair& host_and_port,
     33     const SSLConfig& ssl_config,
     34     PrivacyMode privacy_mode,
     35     int load_flags,
     36     bool force_spdy_over_ssl,
     37     bool want_spdy_over_npn)
     38     : direct_params_(direct_params),
     39       socks_proxy_params_(socks_proxy_params),
     40       http_proxy_params_(http_proxy_params),
     41       host_and_port_(host_and_port),
     42       ssl_config_(ssl_config),
     43       privacy_mode_(privacy_mode),
     44       load_flags_(load_flags),
     45       force_spdy_over_ssl_(force_spdy_over_ssl),
     46       want_spdy_over_npn_(want_spdy_over_npn),
     47       ignore_limits_(false) {
     48   if (direct_params_) {
     49     DCHECK(!socks_proxy_params_);
     50     DCHECK(!http_proxy_params_);
     51     ignore_limits_ = direct_params_->ignore_limits();
     52   } else if (socks_proxy_params_) {
     53     DCHECK(!http_proxy_params_);
     54     ignore_limits_ = socks_proxy_params_->ignore_limits();
     55   } else {
     56     DCHECK(http_proxy_params_);
     57     ignore_limits_ = http_proxy_params_->ignore_limits();
     58   }
     59 }
     60 
     61 SSLSocketParams::~SSLSocketParams() {}
     62 
     63 SSLSocketParams::ConnectionType SSLSocketParams::GetConnectionType() const {
     64   if (direct_params_) {
     65     DCHECK(!socks_proxy_params_);
     66     DCHECK(!http_proxy_params_);
     67     return DIRECT;
     68   }
     69 
     70   if (socks_proxy_params_) {
     71     DCHECK(!http_proxy_params_);
     72     return SOCKS_PROXY;
     73   }
     74 
     75   DCHECK(http_proxy_params_);
     76   return HTTP_PROXY;
     77 }
     78 
     79 const scoped_refptr<TransportSocketParams>&
     80 SSLSocketParams::GetDirectConnectionParams() const {
     81   DCHECK_EQ(GetConnectionType(), DIRECT);
     82   return direct_params_;
     83 }
     84 
     85 const scoped_refptr<SOCKSSocketParams>&
     86 SSLSocketParams::GetSocksProxyConnectionParams() const {
     87   DCHECK_EQ(GetConnectionType(), SOCKS_PROXY);
     88   return socks_proxy_params_;
     89 }
     90 
     91 const scoped_refptr<HttpProxySocketParams>&
     92 SSLSocketParams::GetHttpProxyConnectionParams() const {
     93   DCHECK_EQ(GetConnectionType(), HTTP_PROXY);
     94   return http_proxy_params_;
     95 }
     96 
     97 // Timeout for the SSL handshake portion of the connect.
     98 static const int kSSLHandshakeTimeoutInSeconds = 30;
     99 
    100 SSLConnectJob::SSLConnectJob(const std::string& group_name,
    101                              RequestPriority priority,
    102                              const scoped_refptr<SSLSocketParams>& params,
    103                              const base::TimeDelta& timeout_duration,
    104                              TransportClientSocketPool* transport_pool,
    105                              SOCKSClientSocketPool* socks_pool,
    106                              HttpProxyClientSocketPool* http_proxy_pool,
    107                              ClientSocketFactory* client_socket_factory,
    108                              HostResolver* host_resolver,
    109                              const SSLClientSocketContext& context,
    110                              Delegate* delegate,
    111                              NetLog* net_log)
    112     : ConnectJob(group_name,
    113                  timeout_duration,
    114                  priority,
    115                  delegate,
    116                  BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
    117       params_(params),
    118       transport_pool_(transport_pool),
    119       socks_pool_(socks_pool),
    120       http_proxy_pool_(http_proxy_pool),
    121       client_socket_factory_(client_socket_factory),
    122       host_resolver_(host_resolver),
    123       context_(context.cert_verifier,
    124                context.server_bound_cert_service,
    125                context.transport_security_state,
    126                context.cert_transparency_verifier,
    127                (params->privacy_mode() == PRIVACY_MODE_ENABLED
    128                     ? "pm/" + context.ssl_session_cache_shard
    129                     : context.ssl_session_cache_shard)),
    130       callback_(base::Bind(&SSLConnectJob::OnIOComplete,
    131                            base::Unretained(this))) {}
    132 
    133 SSLConnectJob::~SSLConnectJob() {}
    134 
    135 LoadState SSLConnectJob::GetLoadState() const {
    136   switch (next_state_) {
    137     case STATE_TUNNEL_CONNECT_COMPLETE:
    138       if (transport_socket_handle_->socket())
    139         return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
    140       // else, fall through.
    141     case STATE_TRANSPORT_CONNECT:
    142     case STATE_TRANSPORT_CONNECT_COMPLETE:
    143     case STATE_SOCKS_CONNECT:
    144     case STATE_SOCKS_CONNECT_COMPLETE:
    145     case STATE_TUNNEL_CONNECT:
    146       return transport_socket_handle_->GetLoadState();
    147     case STATE_SSL_CONNECT:
    148     case STATE_SSL_CONNECT_COMPLETE:
    149       return LOAD_STATE_SSL_HANDSHAKE;
    150     default:
    151       NOTREACHED();
    152       return LOAD_STATE_IDLE;
    153   }
    154 }
    155 
    156 void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle* handle) {
    157   // Headers in |error_response_info_| indicate a proxy tunnel setup
    158   // problem. See DoTunnelConnectComplete.
    159   if (error_response_info_.headers.get()) {
    160     handle->set_pending_http_proxy_connection(
    161         transport_socket_handle_.release());
    162   }
    163   handle->set_ssl_error_response_info(error_response_info_);
    164   if (!connect_timing_.ssl_start.is_null())
    165     handle->set_is_ssl_error(true);
    166 }
    167 
    168 void SSLConnectJob::OnIOComplete(int result) {
    169   int rv = DoLoop(result);
    170   if (rv != ERR_IO_PENDING)
    171     NotifyDelegateOfCompletion(rv);  // Deletes |this|.
    172 }
    173 
    174 int SSLConnectJob::DoLoop(int result) {
    175   DCHECK_NE(next_state_, STATE_NONE);
    176 
    177   int rv = result;
    178   do {
    179     State state = next_state_;
    180     next_state_ = STATE_NONE;
    181     switch (state) {
    182       case STATE_TRANSPORT_CONNECT:
    183         DCHECK_EQ(OK, rv);
    184         rv = DoTransportConnect();
    185         break;
    186       case STATE_TRANSPORT_CONNECT_COMPLETE:
    187         rv = DoTransportConnectComplete(rv);
    188         break;
    189       case STATE_SOCKS_CONNECT:
    190         DCHECK_EQ(OK, rv);
    191         rv = DoSOCKSConnect();
    192         break;
    193       case STATE_SOCKS_CONNECT_COMPLETE:
    194         rv = DoSOCKSConnectComplete(rv);
    195         break;
    196       case STATE_TUNNEL_CONNECT:
    197         DCHECK_EQ(OK, rv);
    198         rv = DoTunnelConnect();
    199         break;
    200       case STATE_TUNNEL_CONNECT_COMPLETE:
    201         rv = DoTunnelConnectComplete(rv);
    202         break;
    203       case STATE_SSL_CONNECT:
    204         DCHECK_EQ(OK, rv);
    205         rv = DoSSLConnect();
    206         break;
    207       case STATE_SSL_CONNECT_COMPLETE:
    208         rv = DoSSLConnectComplete(rv);
    209         break;
    210       default:
    211         NOTREACHED() << "bad state";
    212         rv = ERR_FAILED;
    213         break;
    214     }
    215   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    216 
    217   return rv;
    218 }
    219 
    220 int SSLConnectJob::DoTransportConnect() {
    221   DCHECK(transport_pool_);
    222 
    223   next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
    224   transport_socket_handle_.reset(new ClientSocketHandle());
    225   scoped_refptr<TransportSocketParams> direct_params =
    226       params_->GetDirectConnectionParams();
    227   return transport_socket_handle_->Init(group_name(),
    228                                         direct_params,
    229                                         priority(),
    230                                         callback_,
    231                                         transport_pool_,
    232                                         net_log());
    233 }
    234 
    235 int SSLConnectJob::DoTransportConnectComplete(int result) {
    236   if (result == OK)
    237     next_state_ = STATE_SSL_CONNECT;
    238 
    239   return result;
    240 }
    241 
    242 int SSLConnectJob::DoSOCKSConnect() {
    243   DCHECK(socks_pool_);
    244   next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
    245   transport_socket_handle_.reset(new ClientSocketHandle());
    246   scoped_refptr<SOCKSSocketParams> socks_proxy_params =
    247       params_->GetSocksProxyConnectionParams();
    248   return transport_socket_handle_->Init(group_name(),
    249                                         socks_proxy_params,
    250                                         priority(),
    251                                         callback_,
    252                                         socks_pool_,
    253                                         net_log());
    254 }
    255 
    256 int SSLConnectJob::DoSOCKSConnectComplete(int result) {
    257   if (result == OK)
    258     next_state_ = STATE_SSL_CONNECT;
    259 
    260   return result;
    261 }
    262 
    263 int SSLConnectJob::DoTunnelConnect() {
    264   DCHECK(http_proxy_pool_);
    265   next_state_ = STATE_TUNNEL_CONNECT_COMPLETE;
    266 
    267   transport_socket_handle_.reset(new ClientSocketHandle());
    268   scoped_refptr<HttpProxySocketParams> http_proxy_params =
    269       params_->GetHttpProxyConnectionParams();
    270   return transport_socket_handle_->Init(group_name(),
    271                                         http_proxy_params,
    272                                         priority(),
    273                                         callback_,
    274                                         http_proxy_pool_,
    275                                         net_log());
    276 }
    277 
    278 int SSLConnectJob::DoTunnelConnectComplete(int result) {
    279   // Extract the information needed to prompt for appropriate proxy
    280   // authentication so that when ClientSocketPoolBaseHelper calls
    281   // |GetAdditionalErrorState|, we can easily set the state.
    282   if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
    283     error_response_info_ = transport_socket_handle_->ssl_error_response_info();
    284   } else if (result == ERR_PROXY_AUTH_REQUESTED ||
    285              result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
    286     StreamSocket* socket = transport_socket_handle_->socket();
    287     HttpProxyClientSocket* tunnel_socket =
    288         static_cast<HttpProxyClientSocket*>(socket);
    289     error_response_info_ = *tunnel_socket->GetConnectResponseInfo();
    290   }
    291   if (result < 0)
    292     return result;
    293 
    294   next_state_ = STATE_SSL_CONNECT;
    295   return result;
    296 }
    297 
    298 int SSLConnectJob::DoSSLConnect() {
    299   next_state_ = STATE_SSL_CONNECT_COMPLETE;
    300   // Reset the timeout to just the time allowed for the SSL handshake.
    301   ResetTimer(base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds));
    302 
    303   // If the handle has a fresh socket, get its connect start and DNS times.
    304   // This should always be the case.
    305   const LoadTimingInfo::ConnectTiming& socket_connect_timing =
    306       transport_socket_handle_->connect_timing();
    307   if (!transport_socket_handle_->is_reused() &&
    308       !socket_connect_timing.connect_start.is_null()) {
    309     // Overwriting |connect_start| serves two purposes - it adjusts timing so
    310     // |connect_start| doesn't include dns times, and it adjusts the time so
    311     // as not to include time spent waiting for an idle socket.
    312     connect_timing_.connect_start = socket_connect_timing.connect_start;
    313     connect_timing_.dns_start = socket_connect_timing.dns_start;
    314     connect_timing_.dns_end = socket_connect_timing.dns_end;
    315   }
    316 
    317   connect_timing_.ssl_start = base::TimeTicks::Now();
    318 
    319   ssl_socket_ = client_socket_factory_->CreateSSLClientSocket(
    320       transport_socket_handle_.Pass(),
    321       params_->host_and_port(),
    322       params_->ssl_config(),
    323       context_);
    324   return ssl_socket_->Connect(callback_);
    325 }
    326 
    327 int SSLConnectJob::DoSSLConnectComplete(int result) {
    328   connect_timing_.ssl_end = base::TimeTicks::Now();
    329 
    330   SSLClientSocket::NextProtoStatus status =
    331       SSLClientSocket::kNextProtoUnsupported;
    332   std::string proto;
    333   std::string server_protos;
    334   // GetNextProto will fail and and trigger a NOTREACHED if we pass in a socket
    335   // that hasn't had SSL_ImportFD called on it. If we get a certificate error
    336   // here, then we know that we called SSL_ImportFD.
    337   if (result == OK || IsCertificateError(result))
    338     status = ssl_socket_->GetNextProto(&proto, &server_protos);
    339 
    340   // If we want spdy over npn, make sure it succeeded.
    341   if (status == SSLClientSocket::kNextProtoNegotiated) {
    342     ssl_socket_->set_was_npn_negotiated(true);
    343     NextProto protocol_negotiated =
    344         SSLClientSocket::NextProtoFromString(proto);
    345     ssl_socket_->set_protocol_negotiated(protocol_negotiated);
    346     // If we negotiated a SPDY version, it must have been present in
    347     // SSLConfig::next_protos.
    348     // TODO(mbelshe): Verify this.
    349     if (protocol_negotiated >= kProtoSPDYMinimumVersion &&
    350         protocol_negotiated <= kProtoSPDYMaximumVersion) {
    351       ssl_socket_->set_was_spdy_negotiated(true);
    352     }
    353   }
    354   if (params_->want_spdy_over_npn() && !ssl_socket_->was_spdy_negotiated())
    355     return ERR_NPN_NEGOTIATION_FAILED;
    356 
    357   // Spdy might be turned on by default, or it might be over npn.
    358   bool using_spdy = params_->force_spdy_over_ssl() ||
    359       params_->want_spdy_over_npn();
    360 
    361   if (result == OK ||
    362       ssl_socket_->IgnoreCertError(result, params_->load_flags())) {
    363     DCHECK(!connect_timing_.ssl_start.is_null());
    364     base::TimeDelta connect_duration =
    365         connect_timing_.ssl_end - connect_timing_.ssl_start;
    366     if (using_spdy) {
    367       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency_2",
    368                                  connect_duration,
    369                                  base::TimeDelta::FromMilliseconds(1),
    370                                  base::TimeDelta::FromMinutes(1),
    371                                  100);
    372     }
    373 #if defined(SPDY_PROXY_AUTH_ORIGIN)
    374     bool using_data_reduction_proxy = params_->host_and_port().Equals(
    375         HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)));
    376     if (using_data_reduction_proxy) {
    377       UMA_HISTOGRAM_CUSTOM_TIMES(
    378           "Net.SSL_Connection_Latency_DataReductionProxy",
    379           connect_duration,
    380           base::TimeDelta::FromMilliseconds(1),
    381           base::TimeDelta::FromMinutes(1),
    382           100);
    383     }
    384 #endif
    385 
    386     UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2",
    387                                connect_duration,
    388                                base::TimeDelta::FromMilliseconds(1),
    389                                base::TimeDelta::FromMinutes(1),
    390                                100);
    391 
    392     SSLInfo ssl_info;
    393     ssl_socket_->GetSSLInfo(&ssl_info);
    394 
    395     UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite",
    396                                 SSLConnectionStatusToCipherSuite(
    397                                     ssl_info.connection_status));
    398 
    399     if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
    400       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Resume_Handshake",
    401                                  connect_duration,
    402                                  base::TimeDelta::FromMilliseconds(1),
    403                                  base::TimeDelta::FromMinutes(1),
    404                                  100);
    405     } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
    406       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Full_Handshake",
    407                                  connect_duration,
    408                                  base::TimeDelta::FromMilliseconds(1),
    409                                  base::TimeDelta::FromMinutes(1),
    410                                  100);
    411     }
    412 
    413     const std::string& host = params_->host_and_port().host();
    414     bool is_google = host == "google.com" ||
    415                      (host.size() > 11 &&
    416                       host.rfind(".google.com") == host.size() - 11);
    417     if (is_google) {
    418       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2",
    419                                  connect_duration,
    420                                  base::TimeDelta::FromMilliseconds(1),
    421                                  base::TimeDelta::FromMinutes(1),
    422                                  100);
    423       if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
    424         UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
    425                                        "Resume_Handshake",
    426                                    connect_duration,
    427                                    base::TimeDelta::FromMilliseconds(1),
    428                                    base::TimeDelta::FromMinutes(1),
    429                                    100);
    430       } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
    431         UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
    432                                        "Full_Handshake",
    433                                    connect_duration,
    434                                    base::TimeDelta::FromMilliseconds(1),
    435                                    base::TimeDelta::FromMinutes(1),
    436                                    100);
    437       }
    438     }
    439   }
    440 
    441   if (result == OK || IsCertificateError(result)) {
    442     SetSocket(ssl_socket_.PassAs<StreamSocket>());
    443   } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
    444     error_response_info_.cert_request_info = new SSLCertRequestInfo;
    445     ssl_socket_->GetSSLCertRequestInfo(
    446         error_response_info_.cert_request_info.get());
    447   }
    448 
    449   return result;
    450 }
    451 
    452 SSLConnectJob::State SSLConnectJob::GetInitialState(
    453     SSLSocketParams::ConnectionType connection_type) {
    454   switch (connection_type) {
    455     case SSLSocketParams::DIRECT:
    456       return STATE_TRANSPORT_CONNECT;
    457     case SSLSocketParams::HTTP_PROXY:
    458       return STATE_TUNNEL_CONNECT;
    459     case SSLSocketParams::SOCKS_PROXY:
    460       return STATE_SOCKS_CONNECT;
    461   }
    462   NOTREACHED();
    463   return STATE_NONE;
    464 }
    465 
    466 int SSLConnectJob::ConnectInternal() {
    467   next_state_ = GetInitialState(params_->GetConnectionType());
    468   return DoLoop(OK);
    469 }
    470 
    471 SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
    472     TransportClientSocketPool* transport_pool,
    473     SOCKSClientSocketPool* socks_pool,
    474     HttpProxyClientSocketPool* http_proxy_pool,
    475     ClientSocketFactory* client_socket_factory,
    476     HostResolver* host_resolver,
    477     const SSLClientSocketContext& context,
    478     NetLog* net_log)
    479     : transport_pool_(transport_pool),
    480       socks_pool_(socks_pool),
    481       http_proxy_pool_(http_proxy_pool),
    482       client_socket_factory_(client_socket_factory),
    483       host_resolver_(host_resolver),
    484       context_(context),
    485       net_log_(net_log) {
    486   base::TimeDelta max_transport_timeout = base::TimeDelta();
    487   base::TimeDelta pool_timeout;
    488   if (transport_pool_)
    489     max_transport_timeout = transport_pool_->ConnectionTimeout();
    490   if (socks_pool_) {
    491     pool_timeout = socks_pool_->ConnectionTimeout();
    492     if (pool_timeout > max_transport_timeout)
    493       max_transport_timeout = pool_timeout;
    494   }
    495   if (http_proxy_pool_) {
    496     pool_timeout = http_proxy_pool_->ConnectionTimeout();
    497     if (pool_timeout > max_transport_timeout)
    498       max_transport_timeout = pool_timeout;
    499   }
    500   timeout_ = max_transport_timeout +
    501       base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds);
    502 }
    503 
    504 SSLClientSocketPool::SSLClientSocketPool(
    505     int max_sockets,
    506     int max_sockets_per_group,
    507     ClientSocketPoolHistograms* histograms,
    508     HostResolver* host_resolver,
    509     CertVerifier* cert_verifier,
    510     ServerBoundCertService* server_bound_cert_service,
    511     TransportSecurityState* transport_security_state,
    512     CTVerifier* cert_transparency_verifier,
    513     const std::string& ssl_session_cache_shard,
    514     ClientSocketFactory* client_socket_factory,
    515     TransportClientSocketPool* transport_pool,
    516     SOCKSClientSocketPool* socks_pool,
    517     HttpProxyClientSocketPool* http_proxy_pool,
    518     SSLConfigService* ssl_config_service,
    519     NetLog* net_log)
    520     : transport_pool_(transport_pool),
    521       socks_pool_(socks_pool),
    522       http_proxy_pool_(http_proxy_pool),
    523       base_(this, max_sockets, max_sockets_per_group, histograms,
    524             ClientSocketPool::unused_idle_socket_timeout(),
    525             ClientSocketPool::used_idle_socket_timeout(),
    526             new SSLConnectJobFactory(transport_pool,
    527                                      socks_pool,
    528                                      http_proxy_pool,
    529                                      client_socket_factory,
    530                                      host_resolver,
    531                                      SSLClientSocketContext(
    532                                          cert_verifier,
    533                                          server_bound_cert_service,
    534                                          transport_security_state,
    535                                          cert_transparency_verifier,
    536                                          ssl_session_cache_shard),
    537                                      net_log)),
    538       ssl_config_service_(ssl_config_service) {
    539   if (ssl_config_service_.get())
    540     ssl_config_service_->AddObserver(this);
    541   if (transport_pool_)
    542     base_.AddLowerLayeredPool(transport_pool_);
    543   if (socks_pool_)
    544     base_.AddLowerLayeredPool(socks_pool_);
    545   if (http_proxy_pool_)
    546     base_.AddLowerLayeredPool(http_proxy_pool_);
    547 }
    548 
    549 SSLClientSocketPool::~SSLClientSocketPool() {
    550   if (ssl_config_service_.get())
    551     ssl_config_service_->RemoveObserver(this);
    552 }
    553 
    554 scoped_ptr<ConnectJob>
    555 SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
    556     const std::string& group_name,
    557     const PoolBase::Request& request,
    558     ConnectJob::Delegate* delegate) const {
    559   return scoped_ptr<ConnectJob>(
    560       new SSLConnectJob(group_name, request.priority(), request.params(),
    561                         ConnectionTimeout(), transport_pool_, socks_pool_,
    562                         http_proxy_pool_, client_socket_factory_,
    563                         host_resolver_, context_, delegate, net_log_));
    564 }
    565 
    566 base::TimeDelta
    567 SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout() const {
    568   return timeout_;
    569 }
    570 
    571 int SSLClientSocketPool::RequestSocket(const std::string& group_name,
    572                                        const void* socket_params,
    573                                        RequestPriority priority,
    574                                        ClientSocketHandle* handle,
    575                                        const CompletionCallback& callback,
    576                                        const BoundNetLog& net_log) {
    577   const scoped_refptr<SSLSocketParams>* casted_socket_params =
    578       static_cast<const scoped_refptr<SSLSocketParams>*>(socket_params);
    579 
    580   return base_.RequestSocket(group_name, *casted_socket_params, priority,
    581                              handle, callback, net_log);
    582 }
    583 
    584 void SSLClientSocketPool::RequestSockets(
    585     const std::string& group_name,
    586     const void* params,
    587     int num_sockets,
    588     const BoundNetLog& net_log) {
    589   const scoped_refptr<SSLSocketParams>* casted_params =
    590       static_cast<const scoped_refptr<SSLSocketParams>*>(params);
    591 
    592   base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
    593 }
    594 
    595 void SSLClientSocketPool::CancelRequest(const std::string& group_name,
    596                                         ClientSocketHandle* handle) {
    597   base_.CancelRequest(group_name, handle);
    598 }
    599 
    600 void SSLClientSocketPool::ReleaseSocket(const std::string& group_name,
    601                                         scoped_ptr<StreamSocket> socket,
    602                                         int id) {
    603   base_.ReleaseSocket(group_name, socket.Pass(), id);
    604 }
    605 
    606 void SSLClientSocketPool::FlushWithError(int error) {
    607   base_.FlushWithError(error);
    608 }
    609 
    610 void SSLClientSocketPool::CloseIdleSockets() {
    611   base_.CloseIdleSockets();
    612 }
    613 
    614 int SSLClientSocketPool::IdleSocketCount() const {
    615   return base_.idle_socket_count();
    616 }
    617 
    618 int SSLClientSocketPool::IdleSocketCountInGroup(
    619     const std::string& group_name) const {
    620   return base_.IdleSocketCountInGroup(group_name);
    621 }
    622 
    623 LoadState SSLClientSocketPool::GetLoadState(
    624     const std::string& group_name, const ClientSocketHandle* handle) const {
    625   return base_.GetLoadState(group_name, handle);
    626 }
    627 
    628 base::DictionaryValue* SSLClientSocketPool::GetInfoAsValue(
    629     const std::string& name,
    630     const std::string& type,
    631     bool include_nested_pools) const {
    632   base::DictionaryValue* dict = base_.GetInfoAsValue(name, type);
    633   if (include_nested_pools) {
    634     base::ListValue* list = new base::ListValue();
    635     if (transport_pool_) {
    636       list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
    637                                                    "transport_socket_pool",
    638                                                    false));
    639     }
    640     if (socks_pool_) {
    641       list->Append(socks_pool_->GetInfoAsValue("socks_pool",
    642                                                "socks_pool",
    643                                                true));
    644     }
    645     if (http_proxy_pool_) {
    646       list->Append(http_proxy_pool_->GetInfoAsValue("http_proxy_pool",
    647                                                     "http_proxy_pool",
    648                                                     true));
    649     }
    650     dict->Set("nested_pools", list);
    651   }
    652   return dict;
    653 }
    654 
    655 base::TimeDelta SSLClientSocketPool::ConnectionTimeout() const {
    656   return base_.ConnectionTimeout();
    657 }
    658 
    659 ClientSocketPoolHistograms* SSLClientSocketPool::histograms() const {
    660   return base_.histograms();
    661 }
    662 
    663 bool SSLClientSocketPool::IsStalled() const {
    664   return base_.IsStalled();
    665 }
    666 
    667 void SSLClientSocketPool::AddHigherLayeredPool(HigherLayeredPool* higher_pool) {
    668   base_.AddHigherLayeredPool(higher_pool);
    669 }
    670 
    671 void SSLClientSocketPool::RemoveHigherLayeredPool(
    672     HigherLayeredPool* higher_pool) {
    673   base_.RemoveHigherLayeredPool(higher_pool);
    674 }
    675 
    676 bool SSLClientSocketPool::CloseOneIdleConnection() {
    677   if (base_.CloseOneIdleSocket())
    678     return true;
    679   return base_.CloseOneIdleConnectionInHigherLayeredPool();
    680 }
    681 
    682 void SSLClientSocketPool::OnSSLConfigChanged() {
    683   FlushWithError(ERR_NETWORK_CHANGED);
    684 }
    685 
    686 }  // namespace net
    687