OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_stream_factory_impl_job.h" | 5 #include "net/http/http_stream_factory_impl_job.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
16 #include "base/metrics/sparse_histogram.h" | 16 #include "base/metrics/sparse_histogram.h" |
17 #include "base/profiler/scoped_tracker.h" | 17 #include "base/profiler/scoped_tracker.h" |
18 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
20 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
21 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
22 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
23 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
24 #include "base/trace_event/trace_event.h" | 24 #include "base/trace_event/trace_event.h" |
25 #include "base/values.h" | 25 #include "base/values.h" |
26 #include "build/build_config.h" | 26 #include "build/build_config.h" |
27 #include "net/base/port_util.h" | 27 #include "net/base/port_util.h" |
| 28 #include "net/base/proxy_delegate.h" |
28 #include "net/cert/cert_verifier.h" | 29 #include "net/cert/cert_verifier.h" |
29 #include "net/http/bidirectional_stream_impl.h" | 30 #include "net/http/bidirectional_stream_impl.h" |
30 #include "net/http/http_basic_stream.h" | 31 #include "net/http/http_basic_stream.h" |
31 #include "net/http/http_network_session.h" | 32 #include "net/http/http_network_session.h" |
32 #include "net/http/http_proxy_client_socket.h" | 33 #include "net/http/http_proxy_client_socket.h" |
33 #include "net/http/http_proxy_client_socket_pool.h" | 34 #include "net/http/http_proxy_client_socket_pool.h" |
34 #include "net/http/http_request_info.h" | 35 #include "net/http/http_request_info.h" |
35 #include "net/http/http_server_properties.h" | 36 #include "net/http/http_server_properties.h" |
36 #include "net/http/http_stream_factory.h" | 37 #include "net/http/http_stream_factory.h" |
37 #include "net/http/http_stream_factory_impl_request.h" | 38 #include "net/http/http_stream_factory_impl_request.h" |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 : Job(delegate, | 155 : Job(delegate, |
155 job_type, | 156 job_type, |
156 session, | 157 session, |
157 request_info, | 158 request_info, |
158 priority, | 159 priority, |
159 server_ssl_config, | 160 server_ssl_config, |
160 proxy_ssl_config, | 161 proxy_ssl_config, |
161 destination, | 162 destination, |
162 origin_url, | 163 origin_url, |
163 AlternativeService(), | 164 AlternativeService(), |
| 165 ProxyServer(), |
164 net_log) {} | 166 net_log) {} |
165 | 167 |
166 HttpStreamFactoryImpl::Job::Job(Delegate* delegate, | 168 HttpStreamFactoryImpl::Job::Job(Delegate* delegate, |
167 JobType job_type, | 169 JobType job_type, |
168 HttpNetworkSession* session, | 170 HttpNetworkSession* session, |
169 const HttpRequestInfo& request_info, | 171 const HttpRequestInfo& request_info, |
170 RequestPriority priority, | 172 RequestPriority priority, |
171 const SSLConfig& server_ssl_config, | 173 const SSLConfig& server_ssl_config, |
172 const SSLConfig& proxy_ssl_config, | 174 const SSLConfig& proxy_ssl_config, |
173 HostPortPair destination, | 175 HostPortPair destination, |
174 GURL origin_url, | 176 GURL origin_url, |
175 AlternativeService alternative_service, | 177 AlternativeService alternative_service, |
| 178 const ProxyServer& alternative_proxy_server, |
176 NetLog* net_log) | 179 NetLog* net_log) |
177 : request_info_(request_info), | 180 : request_info_(request_info), |
178 priority_(priority), | 181 priority_(priority), |
179 server_ssl_config_(server_ssl_config), | 182 server_ssl_config_(server_ssl_config), |
180 proxy_ssl_config_(proxy_ssl_config), | 183 proxy_ssl_config_(proxy_ssl_config), |
181 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP_STREAM_JOB)), | 184 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP_STREAM_JOB)), |
182 io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))), | 185 io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))), |
183 connection_(new ClientSocketHandle), | 186 connection_(new ClientSocketHandle), |
184 session_(session), | 187 session_(session), |
185 next_state_(STATE_NONE), | 188 next_state_(STATE_NONE), |
186 pac_request_(NULL), | 189 pac_request_(NULL), |
187 destination_(destination), | 190 destination_(destination), |
188 origin_url_(origin_url), | 191 origin_url_(origin_url), |
189 alternative_service_(alternative_service), | 192 alternative_service_(alternative_service), |
190 delegate_(delegate), | 193 delegate_(delegate), |
| 194 alternative_proxy_server_(alternative_proxy_server), |
191 job_type_(job_type), | 195 job_type_(job_type), |
192 using_ssl_(false), | 196 using_ssl_(false), |
193 using_spdy_(false), | 197 using_spdy_(false), |
194 using_quic_(false), | 198 using_quic_(false), |
195 quic_request_(session_->quic_stream_factory()), | 199 quic_request_(session_->quic_stream_factory()), |
196 using_existing_quic_session_(false), | 200 using_existing_quic_session_(false), |
197 spdy_certificate_error_(OK), | 201 spdy_certificate_error_(OK), |
198 establishing_tunnel_(false), | 202 establishing_tunnel_(false), |
199 was_npn_negotiated_(false), | 203 was_npn_negotiated_(false), |
200 negotiated_protocol_(kProtoUnknown), | 204 negotiated_protocol_(kProtoUnknown), |
201 num_streams_(0), | 205 num_streams_(0), |
202 spdy_session_direct_(false), | 206 spdy_session_direct_(false), |
203 job_status_(STATUS_RUNNING), | 207 job_status_(STATUS_RUNNING), |
204 other_job_status_(STATUS_RUNNING), | 208 other_job_status_(STATUS_RUNNING), |
205 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), | 209 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), |
206 ptr_factory_(this) { | 210 ptr_factory_(this) { |
207 DCHECK(session); | 211 DCHECK(session); |
| 212 // The job can't have alternative service and alternative proxy server set at |
| 213 // the same time since alternative services are used for requests that are |
| 214 // fetched directly, while the alternative proxy server is used for requests |
| 215 // that should be fetched using proxy. |
| 216 DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL || |
| 217 !alternative_proxy_server_.is_valid()); |
| 218 DCHECK(!alternative_proxy_server_.is_valid() || |
| 219 !(IsSpdyAlternative() || IsQuicAlternative())); |
| 220 // If either the alternative service protocol is specified or if the |
| 221 // alternative proxy server is valid, then the job type must be set to |
| 222 // either ALTERNATIVE or PRECONNECT. |
| 223 DCHECK((alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL && |
| 224 !alternative_proxy_server_.is_valid()) || |
| 225 (job_type_ == ALTERNATIVE || job_type_ == PRECONNECT)); |
| 226 // If the alternative proxy server is valid, then the job type must be |
| 227 // set to ALTERNATIVE. |
| 228 DCHECK(!alternative_proxy_server_.is_valid() || job_type_ == ALTERNATIVE); |
| 229 |
208 if (IsSpdyAlternative()) { | 230 if (IsSpdyAlternative()) { |
209 DCHECK(origin_url_.SchemeIs("https")); | 231 DCHECK(origin_url_.SchemeIs("https")); |
210 } | 232 } |
211 if (IsQuicAlternative()) { | 233 if (IsQuicAlternative()) { |
212 DCHECK(session_->params().enable_quic); | 234 DCHECK(session_->params().enable_quic); |
213 using_quic_ = true; | 235 using_quic_ = true; |
214 } | 236 } |
215 } | 237 } |
216 | 238 |
217 HttpStreamFactoryImpl::Job::~Job() { | 239 HttpStreamFactoryImpl::Job::~Job() { |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 DCHECK(!pac_request_); | 716 DCHECK(!pac_request_); |
695 DCHECK(session_); | 717 DCHECK(session_); |
696 | 718 |
697 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | 719 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; |
698 | 720 |
699 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { | 721 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { |
700 proxy_info_.UseDirect(); | 722 proxy_info_.UseDirect(); |
701 return OK; | 723 return OK; |
702 } | 724 } |
703 | 725 |
| 726 // If an alternative proxy server was provided, use that. |
| 727 if (alternative_proxy_server_.is_valid()) { |
| 728 proxy_info_.UseProxyServer(alternative_proxy_server_); |
| 729 return OK; |
| 730 } |
| 731 |
704 return session_->proxy_service()->ResolveProxy( | 732 return session_->proxy_service()->ResolveProxy( |
705 origin_url_, request_info_.method, &proxy_info_, io_callback_, | 733 origin_url_, request_info_.method, &proxy_info_, io_callback_, |
706 &pac_request_, session_->params().proxy_delegate, net_log_); | 734 &pac_request_, session_->params().proxy_delegate, net_log_); |
707 } | 735 } |
708 | 736 |
709 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { | 737 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { |
710 pac_request_ = NULL; | 738 pac_request_ = NULL; |
711 | 739 |
712 if (result == OK) { | 740 if (result == OK) { |
713 // Remove unsupported proxies from the list. | 741 // Remove unsupported proxies from the list. |
(...skipping 17 matching lines...) Expand all Loading... |
731 // user visible, because the non-alternative Job should be resumed. | 759 // user visible, because the non-alternative Job should be resumed. |
732 result = ERR_NO_SUPPORTED_PROXIES; | 760 result = ERR_NO_SUPPORTED_PROXIES; |
733 } | 761 } |
734 } | 762 } |
735 | 763 |
736 if (result != OK) { | 764 if (result != OK) { |
737 return result; | 765 return result; |
738 } | 766 } |
739 | 767 |
740 next_state_ = STATE_WAIT; | 768 next_state_ = STATE_WAIT; |
| 769 |
| 770 delegate_->OnResolveProxyComplete(this, request_info_, priority_, |
| 771 server_ssl_config_, proxy_ssl_config_, |
| 772 stream_type_); |
| 773 |
741 return OK; | 774 return OK; |
742 } | 775 } |
743 | 776 |
744 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { | 777 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { |
745 return session_->params().enable_quic && | 778 return session_->params().enable_quic && |
746 (base::ContainsKey(session_->params().origins_to_force_quic_on, | 779 (base::ContainsKey(session_->params().origins_to_force_quic_on, |
747 HostPortPair()) || | 780 HostPortPair()) || |
748 base::ContainsKey(session_->params().origins_to_force_quic_on, | 781 base::ContainsKey(session_->params().origins_to_force_quic_on, |
749 destination_)) && | 782 destination_)) && |
750 proxy_info_.is_direct() && origin_url_.SchemeIs("https"); | 783 proxy_info_.is_direct() && origin_url_.SchemeIs("https"); |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 return error; | 1420 return error; |
1388 } | 1421 } |
1389 | 1422 |
1390 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. | 1423 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. |
1391 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) | 1424 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) |
1392 return error; | 1425 return error; |
1393 | 1426 |
1394 if (request_info_.load_flags & LOAD_BYPASS_PROXY) | 1427 if (request_info_.load_flags & LOAD_BYPASS_PROXY) |
1395 return error; | 1428 return error; |
1396 | 1429 |
| 1430 // Alternative proxy server job should not use fallback proxies, and instead |
| 1431 // return. This would resume the main job (if possible) which may try the |
| 1432 // fallback proxies. |
| 1433 if (alternative_proxy_server_.is_valid()) { |
| 1434 DCHECK_EQ(STATE_NONE, next_state_); |
| 1435 return error; |
| 1436 } |
| 1437 |
1397 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { | 1438 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { |
1398 session_->ssl_client_auth_cache()->Remove( | 1439 session_->ssl_client_auth_cache()->Remove( |
1399 proxy_info_.proxy_server().host_port_pair()); | 1440 proxy_info_.proxy_server().host_port_pair()); |
1400 } | 1441 } |
1401 | 1442 |
1402 int rv = session_->proxy_service()->ReconsiderProxyAfterError( | 1443 int rv = session_->proxy_service()->ReconsiderProxyAfterError( |
1403 request_info_.url, request_info_.method, error, &proxy_info_, | 1444 request_info_.url, request_info_.method, error, &proxy_info_, |
1404 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_); | 1445 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_); |
1405 if (rv == OK || rv == ERR_IO_PENDING) { | 1446 if (rv == OK || rv == ERR_IO_PENDING) { |
1406 // If the error was during connection setup, there is no socket to | 1447 // If the error was during connection setup, there is no socket to |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1467 // This Job was the alternative Job, and hence won the race. | 1508 // This Job was the alternative Job, and hence won the race. |
1468 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); | 1509 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); |
1469 } else { | 1510 } else { |
1470 // This Job was the normal Job, and hence the alternative Job lost the race. | 1511 // This Job was the normal Job, and hence the alternative Job lost the race. |
1471 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); | 1512 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); |
1472 } | 1513 } |
1473 } | 1514 } |
1474 | 1515 |
1475 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) { | 1516 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) { |
1476 DCHECK_EQ(STATUS_RUNNING, other_job_status_); | 1517 DCHECK_EQ(STATUS_RUNNING, other_job_status_); |
| 1518 DCHECK(!other_job_alternative_proxy_server_.is_valid()); |
| 1519 |
1477 other_job_status_ = job.job_status_; | 1520 other_job_status_ = job.job_status_; |
1478 other_job_alternative_service_ = job.alternative_service_; | 1521 other_job_alternative_service_ = job.alternative_service_; |
| 1522 other_job_alternative_proxy_server_ = job.alternative_proxy_server_; |
| 1523 |
| 1524 // At most one job can have a valid |alternative_proxy_server_|. |
| 1525 DCHECK(!alternative_proxy_server_.is_valid() || |
| 1526 !other_job_alternative_proxy_server_.is_valid()); |
| 1527 |
1479 MaybeMarkAlternativeServiceBroken(); | 1528 MaybeMarkAlternativeServiceBroken(); |
1480 } | 1529 } |
1481 | 1530 |
1482 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() { | 1531 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() { |
| 1532 // At least one job should not be an alternative job. |
| 1533 DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL || |
| 1534 other_job_alternative_service_.protocol == |
| 1535 UNINITIALIZED_ALTERNATE_PROTOCOL); |
| 1536 |
1483 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING) | 1537 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING) |
1484 return; | 1538 return; |
1485 | 1539 |
| 1540 MaybeNotifyAlternativeProxyServerBroken(); |
| 1541 |
1486 if (IsSpdyAlternative() || IsQuicAlternative()) { | 1542 if (IsSpdyAlternative() || IsQuicAlternative()) { |
1487 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) { | 1543 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) { |
1488 HistogramBrokenAlternateProtocolLocation( | 1544 HistogramBrokenAlternateProtocolLocation( |
1489 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | 1545 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); |
1490 session_->http_server_properties()->MarkAlternativeServiceBroken( | 1546 session_->http_server_properties()->MarkAlternativeServiceBroken( |
1491 alternative_service_); | 1547 alternative_service_); |
1492 } | 1548 } |
1493 return; | 1549 return; |
1494 } | 1550 } |
1495 | 1551 |
1496 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ == | 1552 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ == |
1497 STATUS_SUCCEEDED); | 1553 STATUS_SUCCEEDED); |
1498 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) { | 1554 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) { |
1499 HistogramBrokenAlternateProtocolLocation( | 1555 HistogramBrokenAlternateProtocolLocation( |
1500 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN); | 1556 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN); |
1501 session_->http_server_properties()->MarkAlternativeServiceBroken( | 1557 session_->http_server_properties()->MarkAlternativeServiceBroken( |
1502 other_job_alternative_service_); | 1558 other_job_alternative_service_); |
1503 } | 1559 } |
1504 } | 1560 } |
1505 | 1561 |
| 1562 void HttpStreamFactoryImpl::Job::MaybeNotifyAlternativeProxyServerBroken() |
| 1563 const { |
| 1564 if (!alternative_proxy_server_.is_valid() && |
| 1565 !other_job_alternative_proxy_server_.is_valid()) { |
| 1566 // Neither of the two jobs used an alternative proxy server. |
| 1567 return; |
| 1568 } |
| 1569 |
| 1570 // Neither this job, nor the other job should have used the alternative |
| 1571 // service. |
| 1572 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service_.protocol); |
| 1573 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL, |
| 1574 other_job_alternative_service_.protocol); |
| 1575 |
| 1576 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
| 1577 if (!proxy_delegate) |
| 1578 return; |
| 1579 |
| 1580 if (alternative_proxy_server_.is_valid()) { |
| 1581 // |this| connected to the alternative proxy server. |
| 1582 if ((job_status_ == STATUS_BROKEN || job_status_ == STATUS_FAILED) && |
| 1583 other_job_status_ == STATUS_SUCCEEDED) { |
| 1584 // Notify ProxyDelegate. |
| 1585 proxy_delegate->OnAlternativeProxyBroken(alternative_proxy_server_); |
| 1586 } |
| 1587 return; |
| 1588 } |
| 1589 |
| 1590 if (other_job_alternative_proxy_server_.is_valid()) { |
| 1591 // Other job connected to the alternative proxy server. |
| 1592 if (job_status_ == STATUS_SUCCEEDED && |
| 1593 (other_job_status_ == STATUS_BROKEN || |
| 1594 other_job_status_ == STATUS_FAILED)) { |
| 1595 // Notify ProxyDelegate. |
| 1596 proxy_delegate->OnAlternativeProxyBroken( |
| 1597 other_job_alternative_proxy_server_); |
| 1598 } |
| 1599 return; |
| 1600 } |
| 1601 } |
| 1602 |
1506 ClientSocketPoolManager::SocketGroupType | 1603 ClientSocketPoolManager::SocketGroupType |
1507 HttpStreamFactoryImpl::Job::GetSocketGroup() const { | 1604 HttpStreamFactoryImpl::Job::GetSocketGroup() const { |
1508 std::string scheme = origin_url_.scheme(); | 1605 std::string scheme = origin_url_.scheme(); |
1509 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative()) | 1606 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative()) |
1510 return ClientSocketPoolManager::SSL_GROUP; | 1607 return ClientSocketPoolManager::SSL_GROUP; |
1511 | 1608 |
1512 if (scheme == "ftp") | 1609 if (scheme == "ftp") |
1513 return ClientSocketPoolManager::FTP_GROUP; | 1610 return ClientSocketPoolManager::FTP_GROUP; |
1514 | 1611 |
1515 return ClientSocketPoolManager::NORMAL_GROUP; | 1612 return ClientSocketPoolManager::NORMAL_GROUP; |
(...skipping 11 matching lines...) Expand all Loading... |
1527 | 1624 |
1528 ConnectionAttempts socket_attempts = connection_->connection_attempts(); | 1625 ConnectionAttempts socket_attempts = connection_->connection_attempts(); |
1529 if (connection_->socket()) { | 1626 if (connection_->socket()) { |
1530 connection_->socket()->GetConnectionAttempts(&socket_attempts); | 1627 connection_->socket()->GetConnectionAttempts(&socket_attempts); |
1531 } | 1628 } |
1532 | 1629 |
1533 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); | 1630 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); |
1534 } | 1631 } |
1535 | 1632 |
1536 } // namespace net | 1633 } // namespace net |
OLD | NEW |