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.
5 #include "net/socket/ssl_client_socket_pool.h"
8 #include "base/bind_helpers.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/metrics/sparse_histogram.h"
12 #include "base/profiler/scoped_tracker.h"
13 #include "base/values.h"
14 #include "net/base/host_port_pair.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_proxy_client_socket.h"
17 #include "net/http/http_proxy_client_socket_pool.h"
18 #include "net/socket/client_socket_factory.h"
19 #include "net/socket/client_socket_handle.h"
20 #include "net/socket/socks_client_socket_pool.h"
21 #include "net/socket/ssl_client_socket.h"
22 #include "net/socket/transport_client_socket_pool.h"
23 #include "net/ssl/ssl_cert_request_info.h"
24 #include "net/ssl/ssl_cipher_suite_names.h"
25 #include "net/ssl/ssl_connection_status_flags.h"
26 #include "net/ssl/ssl_info.h"
30 SSLSocketParams::SSLSocketParams(
31 const scoped_refptr
<TransportSocketParams
>& direct_params
,
32 const scoped_refptr
<SOCKSSocketParams
>& socks_proxy_params
,
33 const scoped_refptr
<HttpProxySocketParams
>& http_proxy_params
,
34 const HostPortPair
& host_and_port
,
35 const SSLConfig
& ssl_config
,
36 PrivacyMode privacy_mode
,
39 : direct_params_(direct_params
),
40 socks_proxy_params_(socks_proxy_params
),
41 http_proxy_params_(http_proxy_params
),
42 host_and_port_(host_and_port
),
43 ssl_config_(ssl_config
),
44 privacy_mode_(privacy_mode
),
45 load_flags_(load_flags
),
46 expect_spdy_(expect_spdy
),
47 ignore_limits_(false) {
48 if (direct_params_
.get()) {
49 DCHECK(!socks_proxy_params_
.get());
50 DCHECK(!http_proxy_params_
.get());
51 ignore_limits_
= direct_params_
->ignore_limits();
52 } else if (socks_proxy_params_
.get()) {
53 DCHECK(!http_proxy_params_
.get());
54 ignore_limits_
= socks_proxy_params_
->ignore_limits();
56 DCHECK(http_proxy_params_
.get());
57 ignore_limits_
= http_proxy_params_
->ignore_limits();
61 SSLSocketParams::~SSLSocketParams() {}
63 SSLSocketParams::ConnectionType
SSLSocketParams::GetConnectionType() const {
64 if (direct_params_
.get()) {
65 DCHECK(!socks_proxy_params_
.get());
66 DCHECK(!http_proxy_params_
.get());
70 if (socks_proxy_params_
.get()) {
71 DCHECK(!http_proxy_params_
.get());
75 DCHECK(http_proxy_params_
.get());
79 const scoped_refptr
<TransportSocketParams
>&
80 SSLSocketParams::GetDirectConnectionParams() const {
81 DCHECK_EQ(GetConnectionType(), DIRECT
);
82 return direct_params_
;
85 const scoped_refptr
<SOCKSSocketParams
>&
86 SSLSocketParams::GetSocksProxyConnectionParams() const {
87 DCHECK_EQ(GetConnectionType(), SOCKS_PROXY
);
88 return socks_proxy_params_
;
91 const scoped_refptr
<HttpProxySocketParams
>&
92 SSLSocketParams::GetHttpProxyConnectionParams() const {
93 DCHECK_EQ(GetConnectionType(), HTTP_PROXY
);
94 return http_proxy_params_
;
97 // Timeout for the SSL handshake portion of the connect.
98 static const int kSSLHandshakeTimeoutInSeconds
= 30;
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 const SSLClientSocketContext
& context
,
111 : ConnectJob(group_name
,
115 BoundNetLog::Make(net_log
, NetLog::SOURCE_CONNECT_JOB
)),
117 transport_pool_(transport_pool
),
118 socks_pool_(socks_pool
),
119 http_proxy_pool_(http_proxy_pool
),
120 client_socket_factory_(client_socket_factory
),
121 context_(context
.cert_verifier
,
122 context
.channel_id_service
,
123 context
.transport_security_state
,
124 context
.cert_transparency_verifier
,
125 context
.cert_policy_enforcer
,
126 (params
->privacy_mode() == PRIVACY_MODE_ENABLED
127 ? "pm/" + context
.ssl_session_cache_shard
128 : context
.ssl_session_cache_shard
)),
130 base::Bind(&SSLConnectJob::OnIOComplete
, base::Unretained(this))) {
133 SSLConnectJob::~SSLConnectJob() {
136 LoadState
SSLConnectJob::GetLoadState() const {
137 switch (next_state_
) {
138 case STATE_TUNNEL_CONNECT_COMPLETE
:
139 if (transport_socket_handle_
->socket())
140 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL
;
141 // else, fall through.
142 case STATE_TRANSPORT_CONNECT
:
143 case STATE_TRANSPORT_CONNECT_COMPLETE
:
144 case STATE_SOCKS_CONNECT
:
145 case STATE_SOCKS_CONNECT_COMPLETE
:
146 case STATE_TUNNEL_CONNECT
:
147 return transport_socket_handle_
->GetLoadState();
148 case STATE_SSL_CONNECT
:
149 case STATE_SSL_CONNECT_COMPLETE
:
150 return LOAD_STATE_SSL_HANDSHAKE
;
153 return LOAD_STATE_IDLE
;
157 void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle
* handle
) {
158 // Headers in |error_response_info_| indicate a proxy tunnel setup
159 // problem. See DoTunnelConnectComplete.
160 if (error_response_info_
.headers
.get()) {
161 handle
->set_pending_http_proxy_connection(
162 transport_socket_handle_
.release());
164 handle
->set_ssl_error_response_info(error_response_info_
);
165 if (!connect_timing_
.ssl_start
.is_null())
166 handle
->set_is_ssl_error(true);
168 handle
->set_ssl_failure_state(ssl_socket_
->GetSSLFailureState());
170 handle
->set_connection_attempts(connection_attempts_
);
173 void SSLConnectJob::OnIOComplete(int result
) {
174 int rv
= DoLoop(result
);
175 if (rv
!= ERR_IO_PENDING
)
176 NotifyDelegateOfCompletion(rv
); // Deletes |this|.
179 int SSLConnectJob::DoLoop(int result
) {
180 DCHECK_NE(next_state_
, STATE_NONE
);
184 State state
= next_state_
;
185 next_state_
= STATE_NONE
;
187 case STATE_TRANSPORT_CONNECT
:
189 rv
= DoTransportConnect();
191 case STATE_TRANSPORT_CONNECT_COMPLETE
:
192 rv
= DoTransportConnectComplete(rv
);
194 case STATE_SOCKS_CONNECT
:
196 rv
= DoSOCKSConnect();
198 case STATE_SOCKS_CONNECT_COMPLETE
:
199 rv
= DoSOCKSConnectComplete(rv
);
201 case STATE_TUNNEL_CONNECT
:
203 rv
= DoTunnelConnect();
205 case STATE_TUNNEL_CONNECT_COMPLETE
:
206 rv
= DoTunnelConnectComplete(rv
);
208 case STATE_SSL_CONNECT
:
212 case STATE_SSL_CONNECT_COMPLETE
:
213 rv
= DoSSLConnectComplete(rv
);
216 NOTREACHED() << "bad state";
220 } while (rv
!= ERR_IO_PENDING
&& next_state_
!= STATE_NONE
);
225 int SSLConnectJob::DoTransportConnect() {
226 DCHECK(transport_pool_
);
228 next_state_
= STATE_TRANSPORT_CONNECT_COMPLETE
;
229 transport_socket_handle_
.reset(new ClientSocketHandle());
230 scoped_refptr
<TransportSocketParams
> direct_params
=
231 params_
->GetDirectConnectionParams();
232 return transport_socket_handle_
->Init(group_name(), direct_params
, priority(),
233 callback_
, transport_pool_
, net_log());
236 int SSLConnectJob::DoTransportConnectComplete(int result
) {
237 connection_attempts_
= transport_socket_handle_
->connection_attempts();
239 next_state_
= STATE_SSL_CONNECT
;
240 transport_socket_handle_
->socket()->GetPeerAddress(&server_address_
);
246 int SSLConnectJob::DoSOCKSConnect() {
248 next_state_
= STATE_SOCKS_CONNECT_COMPLETE
;
249 transport_socket_handle_
.reset(new ClientSocketHandle());
250 scoped_refptr
<SOCKSSocketParams
> socks_proxy_params
=
251 params_
->GetSocksProxyConnectionParams();
252 return transport_socket_handle_
->Init(group_name(), socks_proxy_params
,
253 priority(), callback_
, socks_pool_
,
257 int SSLConnectJob::DoSOCKSConnectComplete(int result
) {
259 next_state_
= STATE_SSL_CONNECT
;
264 int SSLConnectJob::DoTunnelConnect() {
265 DCHECK(http_proxy_pool_
);
266 next_state_
= STATE_TUNNEL_CONNECT_COMPLETE
;
268 transport_socket_handle_
.reset(new ClientSocketHandle());
269 scoped_refptr
<HttpProxySocketParams
> http_proxy_params
=
270 params_
->GetHttpProxyConnectionParams();
271 return transport_socket_handle_
->Init(group_name(), http_proxy_params
,
272 priority(), callback_
, http_proxy_pool_
,
276 int SSLConnectJob::DoTunnelConnectComplete(int result
) {
277 // Extract the information needed to prompt for appropriate proxy
278 // authentication so that when ClientSocketPoolBaseHelper calls
279 // |GetAdditionalErrorState|, we can easily set the state.
280 if (result
== ERR_SSL_CLIENT_AUTH_CERT_NEEDED
) {
281 error_response_info_
= transport_socket_handle_
->ssl_error_response_info();
282 } else if (result
== ERR_PROXY_AUTH_REQUESTED
||
283 result
== ERR_HTTPS_PROXY_TUNNEL_RESPONSE
) {
284 StreamSocket
* socket
= transport_socket_handle_
->socket();
285 ProxyClientSocket
* tunnel_socket
= static_cast<ProxyClientSocket
*>(socket
);
286 error_response_info_
= *tunnel_socket
->GetConnectResponseInfo();
291 next_state_
= STATE_SSL_CONNECT
;
295 int SSLConnectJob::DoSSLConnect() {
296 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462815 is fixed.
297 tracked_objects::ScopedTracker
tracking_profile(
298 FROM_HERE_WITH_EXPLICIT_FUNCTION("462815 SSLConnectJob::DoSSLConnect"));
300 next_state_
= STATE_SSL_CONNECT_COMPLETE
;
302 // Reset the timeout to just the time allowed for the SSL handshake.
303 ResetTimer(base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds
));
305 // If the handle has a fresh socket, get its connect start and DNS times.
306 // This should always be the case.
307 const LoadTimingInfo::ConnectTiming
& socket_connect_timing
=
308 transport_socket_handle_
->connect_timing();
309 if (!transport_socket_handle_
->is_reused() &&
310 !socket_connect_timing
.connect_start
.is_null()) {
311 // Overwriting |connect_start| serves two purposes - it adjusts timing so
312 // |connect_start| doesn't include dns times, and it adjusts the time so
313 // as not to include time spent waiting for an idle socket.
314 connect_timing_
.connect_start
= socket_connect_timing
.connect_start
;
315 connect_timing_
.dns_start
= socket_connect_timing
.dns_start
;
316 connect_timing_
.dns_end
= socket_connect_timing
.dns_end
;
319 connect_timing_
.ssl_start
= base::TimeTicks::Now();
321 ssl_socket_
= client_socket_factory_
->CreateSSLClientSocket(
322 transport_socket_handle_
.Pass(),
323 params_
->host_and_port(),
324 params_
->ssl_config(),
326 return ssl_socket_
->Connect(callback_
);
329 int SSLConnectJob::DoSSLConnectComplete(int result
) {
330 // TODO(rvargas): Remove ScopedTracker below once crbug.com/462784 is fixed.
331 tracked_objects::ScopedTracker
tracking_profile(
332 FROM_HERE_WITH_EXPLICIT_FUNCTION(
333 "462784 SSLConnectJob::DoSSLConnectComplete"));
335 connect_timing_
.ssl_end
= base::TimeTicks::Now();
337 if (result
!= OK
&& !server_address_
.address().empty()) {
338 connection_attempts_
.push_back(ConnectionAttempt(server_address_
, result
));
339 server_address_
= IPEndPoint();
342 // If we want SPDY over ALPN/NPN, make sure it succeeded.
343 if (params_
->expect_spdy() &&
344 !NextProtoIsSPDY(ssl_socket_
->GetNegotiatedProtocol())) {
345 return ERR_NPN_NEGOTIATION_FAILED
;
349 ssl_socket_
->IgnoreCertError(result
, params_
->load_flags())) {
350 DCHECK(!connect_timing_
.ssl_start
.is_null());
351 base::TimeDelta connect_duration
=
352 connect_timing_
.ssl_end
- connect_timing_
.ssl_start
;
353 if (params_
->expect_spdy()) {
354 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency_2",
356 base::TimeDelta::FromMilliseconds(1),
357 base::TimeDelta::FromMinutes(1),
361 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2",
363 base::TimeDelta::FromMilliseconds(1),
364 base::TimeDelta::FromMinutes(1),
368 bool has_ssl_info
= ssl_socket_
->GetSSLInfo(&ssl_info
);
369 DCHECK(has_ssl_info
);
371 UMA_HISTOGRAM_ENUMERATION("Net.SSLVersion", SSLConnectionStatusToVersion(
372 ssl_info
.connection_status
),
373 SSL_CONNECTION_VERSION_MAX
);
375 uint16 cipher_suite
=
376 SSLConnectionStatusToCipherSuite(ssl_info
.connection_status
);
377 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite", cipher_suite
);
379 const char *str
, *cipher_str
, *mac_str
;
381 SSLCipherSuiteToStrings(&str
, &cipher_str
, &mac_str
, &is_aead
,
383 // UMA_HISTOGRAM_... macros cache the Histogram instance and thus only work
384 // if the histogram name is constant, so don't generate it dynamically.
385 if (strcmp(str
, "RSA") == 0) {
386 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.RSA",
387 ssl_info
.key_exchange_info
);
388 } else if (strncmp(str
, "DHE_", 4) == 0) {
389 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.DHE",
390 ssl_info
.key_exchange_info
);
391 } else if (strncmp(str
, "ECDHE_", 6) == 0) {
392 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.ECDHE",
393 ssl_info
.key_exchange_info
);
398 if (ssl_info
.handshake_type
== SSLInfo::HANDSHAKE_RESUME
) {
399 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Resume_Handshake",
401 base::TimeDelta::FromMilliseconds(1),
402 base::TimeDelta::FromMinutes(1),
404 } else if (ssl_info
.handshake_type
== SSLInfo::HANDSHAKE_FULL
) {
405 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Full_Handshake",
407 base::TimeDelta::FromMilliseconds(1),
408 base::TimeDelta::FromMinutes(1),
412 const std::string
& host
= params_
->host_and_port().host();
414 host
== "google.com" ||
415 (host
.size() > 11 && host
.rfind(".google.com") == host
.size() - 11);
417 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2",
419 base::TimeDelta::FromMilliseconds(1),
420 base::TimeDelta::FromMinutes(1),
422 if (ssl_info
.handshake_type
== SSLInfo::HANDSHAKE_RESUME
) {
423 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
426 base::TimeDelta::FromMilliseconds(1),
427 base::TimeDelta::FromMinutes(1),
429 } else if (ssl_info
.handshake_type
== SSLInfo::HANDSHAKE_FULL
) {
430 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
433 base::TimeDelta::FromMilliseconds(1),
434 base::TimeDelta::FromMinutes(1),
440 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error", std::abs(result
));
442 if (result
== OK
|| IsCertificateError(result
)) {
443 SetSocket(ssl_socket_
.Pass());
444 } else if (result
== ERR_SSL_CLIENT_AUTH_CERT_NEEDED
) {
445 error_response_info_
.cert_request_info
= new SSLCertRequestInfo
;
446 ssl_socket_
->GetSSLCertRequestInfo(
447 error_response_info_
.cert_request_info
.get());
453 SSLConnectJob::State
SSLConnectJob::GetInitialState(
454 SSLSocketParams::ConnectionType connection_type
) {
455 switch (connection_type
) {
456 case SSLSocketParams::DIRECT
:
457 return STATE_TRANSPORT_CONNECT
;
458 case SSLSocketParams::HTTP_PROXY
:
459 return STATE_TUNNEL_CONNECT
;
460 case SSLSocketParams::SOCKS_PROXY
:
461 return STATE_SOCKS_CONNECT
;
467 int SSLConnectJob::ConnectInternal() {
468 next_state_
= GetInitialState(params_
->GetConnectionType());
472 SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
473 TransportClientSocketPool
* transport_pool
,
474 SOCKSClientSocketPool
* socks_pool
,
475 HttpProxyClientSocketPool
* http_proxy_pool
,
476 ClientSocketFactory
* client_socket_factory
,
477 const SSLClientSocketContext
& context
,
479 : transport_pool_(transport_pool
),
480 socks_pool_(socks_pool
),
481 http_proxy_pool_(http_proxy_pool
),
482 client_socket_factory_(client_socket_factory
),
485 base::TimeDelta max_transport_timeout
= base::TimeDelta();
486 base::TimeDelta pool_timeout
;
488 max_transport_timeout
= transport_pool_
->ConnectionTimeout();
490 pool_timeout
= socks_pool_
->ConnectionTimeout();
491 if (pool_timeout
> max_transport_timeout
)
492 max_transport_timeout
= pool_timeout
;
494 if (http_proxy_pool_
) {
495 pool_timeout
= http_proxy_pool_
->ConnectionTimeout();
496 if (pool_timeout
> max_transport_timeout
)
497 max_transport_timeout
= pool_timeout
;
499 timeout_
= max_transport_timeout
+
500 base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds
);
503 SSLClientSocketPool::SSLConnectJobFactory::~SSLConnectJobFactory() {
506 SSLClientSocketPool::SSLClientSocketPool(
508 int max_sockets_per_group
,
509 CertVerifier
* cert_verifier
,
510 ChannelIDService
* channel_id_service
,
511 TransportSecurityState
* transport_security_state
,
512 CTVerifier
* cert_transparency_verifier
,
513 CertPolicyEnforcer
* cert_policy_enforcer
,
514 const std::string
& ssl_session_cache_shard
,
515 ClientSocketFactory
* client_socket_factory
,
516 TransportClientSocketPool
* transport_pool
,
517 SOCKSClientSocketPool
* socks_pool
,
518 HttpProxyClientSocketPool
* http_proxy_pool
,
519 SSLConfigService
* ssl_config_service
,
521 : transport_pool_(transport_pool
),
522 socks_pool_(socks_pool
),
523 http_proxy_pool_(http_proxy_pool
),
526 max_sockets_per_group
,
527 ClientSocketPool::unused_idle_socket_timeout(),
528 ClientSocketPool::used_idle_socket_timeout(),
529 new SSLConnectJobFactory(
533 client_socket_factory
,
534 SSLClientSocketContext(cert_verifier
,
536 transport_security_state
,
537 cert_transparency_verifier
,
538 cert_policy_enforcer
,
539 ssl_session_cache_shard
),
541 ssl_config_service_(ssl_config_service
) {
542 if (ssl_config_service_
.get())
543 ssl_config_service_
->AddObserver(this);
545 base_
.AddLowerLayeredPool(transport_pool_
);
547 base_
.AddLowerLayeredPool(socks_pool_
);
548 if (http_proxy_pool_
)
549 base_
.AddLowerLayeredPool(http_proxy_pool_
);
552 SSLClientSocketPool::~SSLClientSocketPool() {
553 if (ssl_config_service_
.get())
554 ssl_config_service_
->RemoveObserver(this);
557 scoped_ptr
<ConnectJob
> SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
558 const std::string
& group_name
,
559 const PoolBase::Request
& request
,
560 ConnectJob::Delegate
* delegate
) const {
561 return scoped_ptr
<ConnectJob
>(new SSLConnectJob(group_name
,
568 client_socket_factory_
,
574 base::TimeDelta
SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout()
579 int SSLClientSocketPool::RequestSocket(const std::string
& group_name
,
580 const void* socket_params
,
581 RequestPriority priority
,
582 ClientSocketHandle
* handle
,
583 const CompletionCallback
& callback
,
584 const BoundNetLog
& net_log
) {
585 const scoped_refptr
<SSLSocketParams
>* casted_socket_params
=
586 static_cast<const scoped_refptr
<SSLSocketParams
>*>(socket_params
);
588 return base_
.RequestSocket(group_name
, *casted_socket_params
, priority
,
589 handle
, callback
, net_log
);
592 void SSLClientSocketPool::RequestSockets(
593 const std::string
& group_name
,
596 const BoundNetLog
& net_log
) {
597 const scoped_refptr
<SSLSocketParams
>* casted_params
=
598 static_cast<const scoped_refptr
<SSLSocketParams
>*>(params
);
600 base_
.RequestSockets(group_name
, *casted_params
, num_sockets
, net_log
);
603 void SSLClientSocketPool::CancelRequest(const std::string
& group_name
,
604 ClientSocketHandle
* handle
) {
605 base_
.CancelRequest(group_name
, handle
);
608 void SSLClientSocketPool::ReleaseSocket(const std::string
& group_name
,
609 scoped_ptr
<StreamSocket
> socket
,
611 base_
.ReleaseSocket(group_name
, socket
.Pass(), id
);
614 void SSLClientSocketPool::FlushWithError(int error
) {
615 base_
.FlushWithError(error
);
618 void SSLClientSocketPool::CloseIdleSockets() {
619 base_
.CloseIdleSockets();
622 int SSLClientSocketPool::IdleSocketCount() const {
623 return base_
.idle_socket_count();
626 int SSLClientSocketPool::IdleSocketCountInGroup(
627 const std::string
& group_name
) const {
628 return base_
.IdleSocketCountInGroup(group_name
);
631 LoadState
SSLClientSocketPool::GetLoadState(
632 const std::string
& group_name
, const ClientSocketHandle
* handle
) const {
633 return base_
.GetLoadState(group_name
, handle
);
636 scoped_ptr
<base::DictionaryValue
> SSLClientSocketPool::GetInfoAsValue(
637 const std::string
& name
,
638 const std::string
& type
,
639 bool include_nested_pools
) const {
640 scoped_ptr
<base::DictionaryValue
> dict(base_
.GetInfoAsValue(name
, type
));
641 if (include_nested_pools
) {
642 base::ListValue
* list
= new base::ListValue();
643 if (transport_pool_
) {
644 list
->Append(transport_pool_
->GetInfoAsValue("transport_socket_pool",
645 "transport_socket_pool",
649 list
->Append(socks_pool_
->GetInfoAsValue("socks_pool",
653 if (http_proxy_pool_
) {
654 list
->Append(http_proxy_pool_
->GetInfoAsValue("http_proxy_pool",
658 dict
->Set("nested_pools", list
);
663 base::TimeDelta
SSLClientSocketPool::ConnectionTimeout() const {
664 return base_
.ConnectionTimeout();
667 bool SSLClientSocketPool::IsStalled() const {
668 return base_
.IsStalled();
671 void SSLClientSocketPool::AddHigherLayeredPool(HigherLayeredPool
* higher_pool
) {
672 base_
.AddHigherLayeredPool(higher_pool
);
675 void SSLClientSocketPool::RemoveHigherLayeredPool(
676 HigherLayeredPool
* higher_pool
) {
677 base_
.RemoveHigherLayeredPool(higher_pool
);
680 bool SSLClientSocketPool::CloseOneIdleConnection() {
681 if (base_
.CloseOneIdleSocket())
683 return base_
.CloseOneIdleConnectionInHigherLayeredPool();
686 void SSLClientSocketPool::OnSSLConfigChanged() {
687 FlushWithError(ERR_NETWORK_CHANGED
);