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