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 DCHECK_EQ(alternative_service_.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL || |
| 221 alternative_proxy_server_.is_valid(), |
| 222 job_type_ == ALTERNATIVE); |
| 223 |
208 if (IsSpdyAlternative()) { | 224 if (IsSpdyAlternative()) { |
209 DCHECK(origin_url_.SchemeIs("https")); | 225 DCHECK(origin_url_.SchemeIs("https")); |
210 } | 226 } |
211 if (IsQuicAlternative()) { | 227 if (IsQuicAlternative()) { |
212 DCHECK(session_->params().enable_quic); | 228 DCHECK(session_->params().enable_quic); |
213 using_quic_ = true; | 229 using_quic_ = true; |
214 } | 230 } |
215 } | 231 } |
216 | 232 |
217 HttpStreamFactoryImpl::Job::~Job() { | 233 HttpStreamFactoryImpl::Job::~Job() { |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 DCHECK(!pac_request_); | 710 DCHECK(!pac_request_); |
695 DCHECK(session_); | 711 DCHECK(session_); |
696 | 712 |
697 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | 713 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; |
698 | 714 |
699 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { | 715 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { |
700 proxy_info_.UseDirect(); | 716 proxy_info_.UseDirect(); |
701 return OK; | 717 return OK; |
702 } | 718 } |
703 | 719 |
| 720 // If an alternative proxy server was provided, use that. |
| 721 if (alternative_proxy_server_.is_valid()) { |
| 722 proxy_info_.UseProxyServer(alternative_proxy_server_); |
| 723 return OK; |
| 724 } |
| 725 |
704 return session_->proxy_service()->ResolveProxy( | 726 return session_->proxy_service()->ResolveProxy( |
705 origin_url_, request_info_.method, &proxy_info_, io_callback_, | 727 origin_url_, request_info_.method, &proxy_info_, io_callback_, |
706 &pac_request_, session_->params().proxy_delegate, net_log_); | 728 &pac_request_, session_->params().proxy_delegate, net_log_); |
707 } | 729 } |
708 | 730 |
709 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { | 731 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { |
710 pac_request_ = NULL; | 732 pac_request_ = NULL; |
711 | 733 |
712 if (result == OK) { | 734 if (result == OK) { |
713 // Remove unsupported proxies from the list. | 735 // Remove unsupported proxies from the list. |
(...skipping 17 matching lines...) Expand all Loading... |
731 // user visible, because the non-alternative Job should be resumed. | 753 // user visible, because the non-alternative Job should be resumed. |
732 result = ERR_NO_SUPPORTED_PROXIES; | 754 result = ERR_NO_SUPPORTED_PROXIES; |
733 } | 755 } |
734 } | 756 } |
735 | 757 |
736 if (result != OK) { | 758 if (result != OK) { |
737 return result; | 759 return result; |
738 } | 760 } |
739 | 761 |
740 next_state_ = STATE_WAIT; | 762 next_state_ = STATE_WAIT; |
| 763 |
| 764 delegate_->OnResolveProxyComplete(this, request_info_, priority_, |
| 765 server_ssl_config_, proxy_ssl_config_, |
| 766 stream_type_); |
| 767 |
741 return OK; | 768 return OK; |
742 } | 769 } |
743 | 770 |
744 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { | 771 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { |
745 return session_->params().enable_quic && | 772 return session_->params().enable_quic && |
746 (base::ContainsKey(session_->params().origins_to_force_quic_on, | 773 (base::ContainsKey(session_->params().origins_to_force_quic_on, |
747 HostPortPair()) || | 774 HostPortPair()) || |
748 base::ContainsKey(session_->params().origins_to_force_quic_on, | 775 base::ContainsKey(session_->params().origins_to_force_quic_on, |
749 destination_)) && | 776 destination_)) && |
750 proxy_info_.is_direct() && origin_url_.SchemeIs("https"); | 777 proxy_info_.is_direct() && origin_url_.SchemeIs("https"); |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 return error; | 1414 return error; |
1388 } | 1415 } |
1389 | 1416 |
1390 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. | 1417 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. |
1391 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) | 1418 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) |
1392 return error; | 1419 return error; |
1393 | 1420 |
1394 if (request_info_.load_flags & LOAD_BYPASS_PROXY) | 1421 if (request_info_.load_flags & LOAD_BYPASS_PROXY) |
1395 return error; | 1422 return error; |
1396 | 1423 |
| 1424 // Alternative proxy server job should not use fallback proxies, and instead |
| 1425 // return. This would resume the main job (if possible) which may try the |
| 1426 // fallback proxies. |
| 1427 if (alternative_proxy_server_.is_valid()) { |
| 1428 DCHECK_EQ(STATE_NONE, next_state_); |
| 1429 return error; |
| 1430 } |
| 1431 |
1397 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { | 1432 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { |
1398 session_->ssl_client_auth_cache()->Remove( | 1433 session_->ssl_client_auth_cache()->Remove( |
1399 proxy_info_.proxy_server().host_port_pair()); | 1434 proxy_info_.proxy_server().host_port_pair()); |
1400 } | 1435 } |
1401 | 1436 |
1402 int rv = session_->proxy_service()->ReconsiderProxyAfterError( | 1437 int rv = session_->proxy_service()->ReconsiderProxyAfterError( |
1403 request_info_.url, request_info_.method, error, &proxy_info_, | 1438 request_info_.url, request_info_.method, error, &proxy_info_, |
1404 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_); | 1439 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_); |
1405 if (rv == OK || rv == ERR_IO_PENDING) { | 1440 if (rv == OK || rv == ERR_IO_PENDING) { |
1406 // If the error was during connection setup, there is no socket to | 1441 // 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. | 1502 // This Job was the alternative Job, and hence won the race. |
1468 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); | 1503 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); |
1469 } else { | 1504 } else { |
1470 // This Job was the normal Job, and hence the alternative Job lost the race. | 1505 // This Job was the normal Job, and hence the alternative Job lost the race. |
1471 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); | 1506 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); |
1472 } | 1507 } |
1473 } | 1508 } |
1474 | 1509 |
1475 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) { | 1510 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) { |
1476 DCHECK_EQ(STATUS_RUNNING, other_job_status_); | 1511 DCHECK_EQ(STATUS_RUNNING, other_job_status_); |
| 1512 DCHECK(!other_job_alternative_proxy_server_.is_valid()); |
| 1513 |
1477 other_job_status_ = job.job_status_; | 1514 other_job_status_ = job.job_status_; |
1478 other_job_alternative_service_ = job.alternative_service_; | 1515 other_job_alternative_service_ = job.alternative_service_; |
| 1516 other_job_alternative_proxy_server_ = job.alternative_proxy_server_; |
| 1517 |
| 1518 // At most one job can have a valid |alternative_proxy_server_|. |
| 1519 DCHECK(!alternative_proxy_server_.is_valid() || |
| 1520 !other_job_alternative_proxy_server_.is_valid()); |
| 1521 |
1479 MaybeMarkAlternativeServiceBroken(); | 1522 MaybeMarkAlternativeServiceBroken(); |
1480 } | 1523 } |
1481 | 1524 |
1482 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() { | 1525 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() { |
1483 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING) | 1526 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING) |
1484 return; | 1527 return; |
1485 | 1528 |
| 1529 MaybeNotifyAlternativeProxyServerBroken(); |
| 1530 |
1486 if (IsSpdyAlternative() || IsQuicAlternative()) { | 1531 if (IsSpdyAlternative() || IsQuicAlternative()) { |
1487 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) { | 1532 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) { |
1488 HistogramBrokenAlternateProtocolLocation( | 1533 HistogramBrokenAlternateProtocolLocation( |
1489 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); | 1534 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); |
1490 session_->http_server_properties()->MarkAlternativeServiceBroken( | 1535 session_->http_server_properties()->MarkAlternativeServiceBroken( |
1491 alternative_service_); | 1536 alternative_service_); |
1492 } | 1537 } |
1493 return; | 1538 return; |
1494 } | 1539 } |
1495 | 1540 |
1496 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ == | 1541 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ == |
1497 STATUS_SUCCEEDED); | 1542 STATUS_SUCCEEDED); |
1498 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) { | 1543 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) { |
1499 HistogramBrokenAlternateProtocolLocation( | 1544 HistogramBrokenAlternateProtocolLocation( |
1500 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN); | 1545 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN); |
1501 session_->http_server_properties()->MarkAlternativeServiceBroken( | 1546 session_->http_server_properties()->MarkAlternativeServiceBroken( |
1502 other_job_alternative_service_); | 1547 other_job_alternative_service_); |
1503 } | 1548 } |
1504 } | 1549 } |
1505 | 1550 |
| 1551 void HttpStreamFactoryImpl::Job::MaybeNotifyAlternativeProxyServerBroken() |
| 1552 const { |
| 1553 if (!alternative_proxy_server_.is_valid() && |
| 1554 !other_job_alternative_proxy_server_.is_valid()) { |
| 1555 // Neither of the two jobs used an alternative proxy server. |
| 1556 return; |
| 1557 } |
| 1558 |
| 1559 // Neither this job, nor the other job should have used the alternative |
| 1560 // service. |
| 1561 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service_.protocol); |
| 1562 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL, |
| 1563 other_job_alternative_service_.protocol); |
| 1564 |
| 1565 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate; |
| 1566 if (!proxy_delegate) |
| 1567 return; |
| 1568 |
| 1569 if (alternative_proxy_server_.is_valid()) { |
| 1570 // |this| connected to the alternative proxy server. |
| 1571 if ((job_status_ == STATUS_BROKEN || job_status_ == STATUS_FAILED) && |
| 1572 other_job_status_ == STATUS_SUCCEEDED) { |
| 1573 // Notify ProxyDelegate. |
| 1574 proxy_delegate->OnAlternativeProxyBroken(alternative_proxy_server_); |
| 1575 } |
| 1576 return; |
| 1577 } |
| 1578 |
| 1579 if (other_job_alternative_proxy_server_.is_valid()) { |
| 1580 // Other job connected to the alternative proxy server. |
| 1581 if (job_status_ == STATUS_SUCCEEDED && |
| 1582 (other_job_status_ == STATUS_BROKEN || |
| 1583 other_job_status_ == STATUS_FAILED)) { |
| 1584 // Notify ProxyDelegate. |
| 1585 proxy_delegate->OnAlternativeProxyBroken( |
| 1586 other_job_alternative_proxy_server_); |
| 1587 } |
| 1588 return; |
| 1589 } |
| 1590 } |
| 1591 |
1506 ClientSocketPoolManager::SocketGroupType | 1592 ClientSocketPoolManager::SocketGroupType |
1507 HttpStreamFactoryImpl::Job::GetSocketGroup() const { | 1593 HttpStreamFactoryImpl::Job::GetSocketGroup() const { |
1508 std::string scheme = origin_url_.scheme(); | 1594 std::string scheme = origin_url_.scheme(); |
1509 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative()) | 1595 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative()) |
1510 return ClientSocketPoolManager::SSL_GROUP; | 1596 return ClientSocketPoolManager::SSL_GROUP; |
1511 | 1597 |
1512 if (scheme == "ftp") | 1598 if (scheme == "ftp") |
1513 return ClientSocketPoolManager::FTP_GROUP; | 1599 return ClientSocketPoolManager::FTP_GROUP; |
1514 | 1600 |
1515 return ClientSocketPoolManager::NORMAL_GROUP; | 1601 return ClientSocketPoolManager::NORMAL_GROUP; |
(...skipping 11 matching lines...) Expand all Loading... |
1527 | 1613 |
1528 ConnectionAttempts socket_attempts = connection_->connection_attempts(); | 1614 ConnectionAttempts socket_attempts = connection_->connection_attempts(); |
1529 if (connection_->socket()) { | 1615 if (connection_->socket()) { |
1530 connection_->socket()->GetConnectionAttempts(&socket_attempts); | 1616 connection_->socket()->GetConnectionAttempts(&socket_attempts); |
1531 } | 1617 } |
1532 | 1618 |
1533 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); | 1619 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); |
1534 } | 1620 } |
1535 | 1621 |
1536 } // namespace net | 1622 } // namespace net |
OLD | NEW |