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