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> | |
10 | 9 |
11 #include "base/bind.h" | 10 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
13 #include "base/location.h" | 12 #include "base/location.h" |
14 #include "base/logging.h" | 13 #include "base/logging.h" |
15 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
16 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
17 #include "base/profiler/scoped_tracker.h" | 16 #include "base/profiler/scoped_tracker.h" |
18 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
19 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
(...skipping 27 matching lines...) Expand all Loading... |
47 #include "net/socket/ssl_client_socket.h" | 46 #include "net/socket/ssl_client_socket.h" |
48 #include "net/socket/ssl_client_socket_pool.h" | 47 #include "net/socket/ssl_client_socket_pool.h" |
49 #include "net/spdy/bidirectional_stream_spdy_impl.h" | 48 #include "net/spdy/bidirectional_stream_spdy_impl.h" |
50 #include "net/spdy/spdy_http_stream.h" | 49 #include "net/spdy/spdy_http_stream.h" |
51 #include "net/spdy/spdy_protocol.h" | 50 #include "net/spdy/spdy_protocol.h" |
52 #include "net/spdy/spdy_session.h" | 51 #include "net/spdy/spdy_session.h" |
53 #include "net/spdy/spdy_session_pool.h" | 52 #include "net/spdy/spdy_session_pool.h" |
54 #include "net/ssl/channel_id_service.h" | 53 #include "net/ssl/channel_id_service.h" |
55 #include "net/ssl/ssl_cert_request_info.h" | 54 #include "net/ssl/ssl_cert_request_info.h" |
56 #include "net/ssl/ssl_connection_status_flags.h" | 55 #include "net/ssl/ssl_connection_status_flags.h" |
| 56 #include "url/url_constants.h" |
57 | 57 |
58 namespace net { | 58 namespace net { |
59 | 59 |
60 namespace { | 60 namespace { |
61 | 61 |
62 void DoNothingAsyncCallback(int result){}; | 62 void DoNothingAsyncCallback(int result) {} |
63 void RecordChannelIDKeyMatch(SSLClientSocket* ssl_socket, | 63 void RecordChannelIDKeyMatch(SSLClientSocket* ssl_socket, |
64 ChannelIDService* channel_id_service, | 64 ChannelIDService* channel_id_service, |
65 std::string host) { | 65 std::string host) { |
66 SSLInfo ssl_info; | 66 SSLInfo ssl_info; |
67 ssl_socket->GetSSLInfo(&ssl_info); | 67 ssl_socket->GetSSLInfo(&ssl_info); |
68 if (!ssl_info.channel_id_sent) | 68 if (!ssl_info.channel_id_sent) |
69 return; | 69 return; |
70 std::unique_ptr<crypto::ECPrivateKey> request_key; | 70 std::unique_ptr<crypto::ECPrivateKey> request_key; |
71 ChannelIDService::Request request; | 71 ChannelIDService::Request request; |
72 int result = channel_id_service->GetOrCreateChannelID( | 72 int result = channel_id_service->GetOrCreateChannelID( |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 origin_url_(origin_url), | 194 origin_url_(origin_url), |
195 alternative_service_(alternative_service), | 195 alternative_service_(alternative_service), |
196 alternative_proxy_server_(alternative_proxy_server), | 196 alternative_proxy_server_(alternative_proxy_server), |
197 delegate_(delegate), | 197 delegate_(delegate), |
198 job_type_(job_type), | 198 job_type_(job_type), |
199 using_ssl_(false), | 199 using_ssl_(false), |
200 using_spdy_(false), | 200 using_spdy_(false), |
201 using_quic_(false), | 201 using_quic_(false), |
202 quic_request_(session_->quic_stream_factory()), | 202 quic_request_(session_->quic_stream_factory()), |
203 using_existing_quic_session_(false), | 203 using_existing_quic_session_(false), |
204 spdy_certificate_error_(OK), | |
205 establishing_tunnel_(false), | 204 establishing_tunnel_(false), |
206 was_alpn_negotiated_(false), | 205 was_alpn_negotiated_(false), |
207 negotiated_protocol_(kProtoUnknown), | 206 negotiated_protocol_(kProtoUnknown), |
208 num_streams_(0), | 207 num_streams_(0), |
209 spdy_session_direct_(false), | 208 spdy_session_direct_(false), |
210 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), | 209 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), |
211 ptr_factory_(this) { | 210 ptr_factory_(this) { |
212 DCHECK(session); | 211 DCHECK(session); |
213 // The job can't have alternative service and alternative proxy server set at | 212 // The job can't have alternative service and alternative proxy server set at |
214 // the same time since alternative services are used for requests that are | 213 // the same time since alternative services are used for requests that are |
215 // fetched directly, while the alternative proxy server is used for requests | 214 // fetched directly, while the alternative proxy server is used for requests |
216 // that should be fetched using proxy. | 215 // that should be fetched using proxy. |
217 DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL || | 216 DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL || |
218 !alternative_proxy_server_.is_valid()); | 217 !alternative_proxy_server_.is_valid()); |
219 DCHECK(!alternative_proxy_server_.is_valid() || | 218 DCHECK(!alternative_proxy_server_.is_valid() || |
220 !(IsSpdyAlternative() || IsQuicAlternative())); | 219 !(IsSpdyAlternative() || IsQuicAlternative())); |
221 // If either the alternative service protocol is specified or if the | 220 // If either the alternative service protocol is specified or if the |
222 // alternative proxy server is valid, then the job type must be set to | 221 // alternative proxy server is valid, then the job type must be set to |
223 // either ALTERNATIVE or PRECONNECT. | 222 // either ALTERNATIVE or PRECONNECT. |
224 DCHECK((alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL && | 223 DCHECK((alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL && |
225 !alternative_proxy_server_.is_valid()) || | 224 !alternative_proxy_server_.is_valid()) || |
226 (job_type_ == ALTERNATIVE || job_type_ == PRECONNECT)); | 225 (job_type_ == ALTERNATIVE || job_type_ == PRECONNECT)); |
227 // If the alternative proxy server is valid, then the job type must be | 226 // If the alternative proxy server is valid, then the job type must be |
228 // set to ALTERNATIVE. | 227 // set to ALTERNATIVE. |
229 DCHECK(!alternative_proxy_server_.is_valid() || job_type_ == ALTERNATIVE); | 228 DCHECK(!alternative_proxy_server_.is_valid() || job_type_ == ALTERNATIVE); |
230 | 229 |
231 if (IsSpdyAlternative()) { | 230 if (IsSpdyAlternative()) { |
232 DCHECK(origin_url_.SchemeIs("https")); | 231 DCHECK(origin_url_.SchemeIs(url::kHttpsScheme)); |
233 } | 232 } |
234 if (IsQuicAlternative()) { | 233 if (IsQuicAlternative()) { |
235 DCHECK(session_->params().enable_quic); | 234 DCHECK(session_->params().enable_quic); |
236 using_quic_ = true; | 235 using_quic_ = true; |
237 } | 236 } |
238 } | 237 } |
239 | 238 |
240 HttpStreamFactoryImpl::Job::~Job() { | 239 HttpStreamFactoryImpl::Job::~Job() { |
241 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB); | 240 net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB); |
242 | 241 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 } | 368 } |
370 | 369 |
371 bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const { | 370 bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const { |
372 // We need to make sure that if a spdy session was created for | 371 // We need to make sure that if a spdy session was created for |
373 // https://somehost/ that we don't use that session for http://somehost:443/. | 372 // https://somehost/ that we don't use that session for http://somehost:443/. |
374 // The only time we can use an existing session is if the request URL is | 373 // The only time we can use an existing session is if the request URL is |
375 // https (the normal case) or if we're connection to a SPDY proxy. | 374 // https (the normal case) or if we're connection to a SPDY proxy. |
376 // https://crbug.com/133176 | 375 // https://crbug.com/133176 |
377 // TODO(ricea): Add "wss" back to this list when SPDY WebSocket support is | 376 // TODO(ricea): Add "wss" back to this list when SPDY WebSocket support is |
378 // working. | 377 // working. |
379 return origin_url_.SchemeIs("https") || | 378 return origin_url_.SchemeIs(url::kHttpsScheme) || |
380 proxy_info_.proxy_server().is_https() || IsSpdyAlternative(); | 379 proxy_info_.proxy_server().is_https(); |
381 } | 380 } |
382 | 381 |
383 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { | 382 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { |
384 DCHECK(stream_.get()); | 383 DCHECK(stream_.get()); |
385 DCHECK_NE(job_type_, PRECONNECT); | 384 DCHECK_NE(job_type_, PRECONNECT); |
386 DCHECK(!delegate_->for_websockets()); | 385 DCHECK(!delegate_->for_websockets()); |
387 | 386 |
388 MaybeCopyConnectionAttemptsFromSocketOrHandle(); | 387 MaybeCopyConnectionAttemptsFromSocketOrHandle(); |
389 | 388 |
390 delegate_->OnStreamReady(this, server_ssl_config_, proxy_info_); | 389 delegate_->OnStreamReady(this, server_ssl_config_, proxy_info_); |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 | 766 |
768 return OK; | 767 return OK; |
769 } | 768 } |
770 | 769 |
771 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { | 770 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { |
772 return session_->params().enable_quic && | 771 return session_->params().enable_quic && |
773 (base::ContainsKey(session_->params().origins_to_force_quic_on, | 772 (base::ContainsKey(session_->params().origins_to_force_quic_on, |
774 HostPortPair()) || | 773 HostPortPair()) || |
775 base::ContainsKey(session_->params().origins_to_force_quic_on, | 774 base::ContainsKey(session_->params().origins_to_force_quic_on, |
776 destination_)) && | 775 destination_)) && |
777 proxy_info_.is_direct() && origin_url_.SchemeIs("https"); | 776 proxy_info_.is_direct() && origin_url_.SchemeIs(url::kHttpsScheme); |
778 } | 777 } |
779 | 778 |
780 int HttpStreamFactoryImpl::Job::DoWait() { | 779 int HttpStreamFactoryImpl::Job::DoWait() { |
781 next_state_ = STATE_WAIT_COMPLETE; | 780 next_state_ = STATE_WAIT_COMPLETE; |
782 if (delegate_->ShouldWait(this)) | 781 if (delegate_->ShouldWait(this)) |
783 return ERR_IO_PENDING; | 782 return ERR_IO_PENDING; |
784 | 783 |
785 return OK; | 784 return OK; |
786 } | 785 } |
787 | 786 |
(...skipping 13 matching lines...) Expand all Loading... |
801 | 800 |
802 int HttpStreamFactoryImpl::Job::DoInitConnectionImpl() { | 801 int HttpStreamFactoryImpl::Job::DoInitConnectionImpl() { |
803 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462812 is fixed. | 802 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462812 is fixed. |
804 tracked_objects::ScopedTracker tracking_profile( | 803 tracked_objects::ScopedTracker tracking_profile( |
805 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 804 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
806 "462812 HttpStreamFactoryImpl::Job::DoInitConnection")); | 805 "462812 HttpStreamFactoryImpl::Job::DoInitConnection")); |
807 DCHECK(!connection_->is_initialized()); | 806 DCHECK(!connection_->is_initialized()); |
808 DCHECK(proxy_info_.proxy_server().is_valid()); | 807 DCHECK(proxy_info_.proxy_server().is_valid()); |
809 next_state_ = STATE_INIT_CONNECTION_COMPLETE; | 808 next_state_ = STATE_INIT_CONNECTION_COMPLETE; |
810 | 809 |
811 using_ssl_ = origin_url_.SchemeIs("https") || origin_url_.SchemeIs("wss") || | 810 using_ssl_ = origin_url_.SchemeIs(url::kHttpsScheme) || |
812 IsSpdyAlternative(); | 811 origin_url_.SchemeIs(url::kWssScheme); |
813 using_spdy_ = false; | 812 using_spdy_ = false; |
814 | 813 |
815 if (ShouldForceQuic()) | 814 if (ShouldForceQuic()) |
816 using_quic_ = true; | 815 using_quic_ = true; |
817 | 816 |
818 DCHECK(!using_quic_ || session_->params().enable_quic); | 817 DCHECK(!using_quic_ || session_->params().enable_quic); |
819 | 818 |
820 if (proxy_info_.is_quic()) { | 819 if (proxy_info_.is_quic()) { |
821 using_quic_ = true; | 820 using_quic_ = true; |
822 DCHECK(session_->params().enable_quic); | 821 DCHECK(session_->params().enable_quic); |
823 } | 822 } |
824 | 823 |
825 if (proxy_info_.is_https() || proxy_info_.is_quic()) { | 824 if (proxy_info_.is_https() || proxy_info_.is_quic()) { |
826 InitSSLConfig(&proxy_ssl_config_, /*is_proxy=*/true); | 825 InitSSLConfig(&proxy_ssl_config_, /*is_proxy=*/true); |
827 // Disable revocation checking for HTTPS proxies since the revocation | 826 // Disable revocation checking for HTTPS proxies since the revocation |
828 // requests are probably going to need to go through the proxy too. | 827 // requests are probably going to need to go through the proxy too. |
829 proxy_ssl_config_.rev_checking_enabled = false; | 828 proxy_ssl_config_.rev_checking_enabled = false; |
830 } | 829 } |
831 if (using_ssl_) { | 830 if (using_ssl_) { |
832 InitSSLConfig(&server_ssl_config_, /*is_proxy=*/false); | 831 InitSSLConfig(&server_ssl_config_, /*is_proxy=*/false); |
833 } | 832 } |
834 | 833 |
835 if (using_quic_) { | 834 if (using_quic_) { |
836 if (proxy_info_.is_quic() && !request_info_.url.SchemeIs("http")) { | 835 if (proxy_info_.is_quic() && |
| 836 !request_info_.url.SchemeIs(url::kHttpScheme)) { |
837 NOTREACHED(); | 837 NOTREACHED(); |
838 // TODO(rch): support QUIC proxies for HTTPS urls. | 838 // TODO(rch): support QUIC proxies for HTTPS urls. |
839 return ERR_NOT_IMPLEMENTED; | 839 return ERR_NOT_IMPLEMENTED; |
840 } | 840 } |
841 HostPortPair destination; | 841 HostPortPair destination; |
842 SSLConfig* ssl_config; | 842 SSLConfig* ssl_config; |
843 GURL url(request_info_.url); | 843 GURL url(request_info_.url); |
844 if (proxy_info_.is_quic()) { | 844 if (proxy_info_.is_quic()) { |
845 // A proxy's certificate is expected to be valid for the proxy hostname. | 845 // A proxy's certificate is expected to be valid for the proxy hostname. |
846 destination = proxy_info_.proxy_server().host_port_pair(); | 846 destination = proxy_info_.proxy_server().host_port_pair(); |
847 ssl_config = &proxy_ssl_config_; | 847 ssl_config = &proxy_ssl_config_; |
848 GURL::Replacements replacements; | 848 GURL::Replacements replacements; |
849 replacements.SetSchemeStr("https"); | 849 replacements.SetSchemeStr(url::kHttpsScheme); |
850 replacements.SetHostStr(destination.host()); | 850 replacements.SetHostStr(destination.host()); |
851 const std::string new_port = base::UintToString(destination.port()); | 851 const std::string new_port = base::UintToString(destination.port()); |
852 replacements.SetPortStr(new_port); | 852 replacements.SetPortStr(new_port); |
853 replacements.ClearUsername(); | 853 replacements.ClearUsername(); |
854 replacements.ClearPassword(); | 854 replacements.ClearPassword(); |
855 replacements.ClearPath(); | 855 replacements.ClearPath(); |
856 replacements.ClearQuery(); | 856 replacements.ClearQuery(); |
857 replacements.ClearRef(); | 857 replacements.ClearRef(); |
858 url = url.ReplaceComponents(replacements); | 858 url = url.ReplaceComponents(replacements); |
859 | 859 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 if (existing_spdy_session_) { | 977 if (existing_spdy_session_) { |
978 using_spdy_ = true; | 978 using_spdy_ = true; |
979 next_state_ = STATE_CREATE_STREAM; | 979 next_state_ = STATE_CREATE_STREAM; |
980 } else { | 980 } else { |
981 // It is possible that the spdy session no longer exists. | 981 // It is possible that the spdy session no longer exists. |
982 ReturnToStateInitConnection(true /* close connection */); | 982 ReturnToStateInitConnection(true /* close connection */); |
983 } | 983 } |
984 return OK; | 984 return OK; |
985 } | 985 } |
986 | 986 |
987 if (proxy_info_.is_quic() && using_quic_) { | 987 if (proxy_info_.is_quic()) { |
| 988 DCHECK(using_quic_); |
988 // Mark QUIC proxy as bad if QUIC got disabled. | 989 // Mark QUIC proxy as bad if QUIC got disabled. |
989 // Underlying QUIC layer would have closed the connection. | 990 // Underlying QUIC layer would have closed the connection. |
990 HostPortPair destination = proxy_info_.proxy_server().host_port_pair(); | |
991 if (session_->quic_stream_factory()->IsQuicDisabled()) { | 991 if (session_->quic_stream_factory()->IsQuicDisabled()) { |
992 using_quic_ = false; | 992 using_quic_ = false; |
993 return ReconsiderProxyAfterError(ERR_QUIC_PROTOCOL_ERROR); | 993 return ReconsiderProxyAfterError(ERR_QUIC_PROTOCOL_ERROR); |
994 } | 994 } |
995 } | 995 } |
996 | 996 |
997 // |result| may be the result of any of the stacked pools. The following | 997 // |result| may be the result of any of the stacked pools. The following |
998 // logic is used when determining how to interpret an error. | 998 // logic is used when determining how to interpret an error. |
999 // If |result| < 0: | 999 // If |result| < 0: |
1000 // and connection_->socket() != NULL, then the SSL handshake ran and it | 1000 // and connection_->socket() != NULL, then the SSL handshake ran and it |
(...skipping 11 matching lines...) Expand all Loading... |
1012 } else { | 1012 } else { |
1013 SSLClientSocket* ssl_socket = | 1013 SSLClientSocket* ssl_socket = |
1014 static_cast<SSLClientSocket*>(connection_->socket()); | 1014 static_cast<SSLClientSocket*>(connection_->socket()); |
1015 if (ssl_socket->WasNpnNegotiated()) { | 1015 if (ssl_socket->WasNpnNegotiated()) { |
1016 was_alpn_negotiated_ = true; | 1016 was_alpn_negotiated_ = true; |
1017 negotiated_protocol_ = ssl_socket->GetNegotiatedProtocol(); | 1017 negotiated_protocol_ = ssl_socket->GetNegotiatedProtocol(); |
1018 net_log_.AddEvent( | 1018 net_log_.AddEvent( |
1019 NetLogEventType::HTTP_STREAM_REQUEST_PROTO, | 1019 NetLogEventType::HTTP_STREAM_REQUEST_PROTO, |
1020 base::Bind(&NetLogHttpStreamProtoCallback, negotiated_protocol_)); | 1020 base::Bind(&NetLogHttpStreamProtoCallback, negotiated_protocol_)); |
1021 if (negotiated_protocol_ == kProtoHTTP2) | 1021 if (negotiated_protocol_ == kProtoHTTP2) |
1022 SwitchToSpdyMode(); | 1022 using_spdy_ = true; |
1023 } | 1023 } |
1024 } | 1024 } |
1025 } else if (proxy_info_.is_https() && connection_->socket() && | 1025 } else if (proxy_info_.is_https() && connection_->socket() && |
1026 result == OK) { | 1026 result == OK) { |
1027 ProxyClientSocket* proxy_socket = | 1027 ProxyClientSocket* proxy_socket = |
1028 static_cast<ProxyClientSocket*>(connection_->socket()); | 1028 static_cast<ProxyClientSocket*>(connection_->socket()); |
1029 // http://crbug.com/642354 | 1029 // http://crbug.com/642354 |
1030 if (!proxy_socket->IsConnected()) | 1030 if (!proxy_socket->IsConnected()) |
1031 return ERR_CONNECTION_CLOSED; | 1031 return ERR_CONNECTION_CLOSED; |
1032 if (proxy_socket->IsUsingSpdy()) { | 1032 if (proxy_socket->IsUsingSpdy()) { |
1033 was_alpn_negotiated_ = true; | 1033 was_alpn_negotiated_ = true; |
1034 negotiated_protocol_ = proxy_socket->GetProxyNegotiatedProtocol(); | 1034 negotiated_protocol_ = proxy_socket->GetProxyNegotiatedProtocol(); |
1035 SwitchToSpdyMode(); | 1035 using_spdy_ = true; |
1036 } | 1036 } |
1037 } | 1037 } |
1038 | 1038 |
1039 if (result == ERR_PROXY_AUTH_REQUESTED || | 1039 if (result == ERR_PROXY_AUTH_REQUESTED || |
1040 result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { | 1040 result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { |
1041 DCHECK(!ssl_started); | 1041 DCHECK(!ssl_started); |
1042 // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an | 1042 // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an |
1043 // SSL socket, but there was an error before that could happen. This | 1043 // SSL socket, but there was an error before that could happen. This |
1044 // puts the in progress HttpProxy socket into |connection_| in order to | 1044 // puts the in progress HttpProxy socket into |connection_| in order to |
1045 // complete the auth (or read the response body). The tunnel restart code | 1045 // complete the auth (or read the response body). The tunnel restart code |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1084 } | 1084 } |
1085 | 1085 |
1086 if (result < 0 && !ssl_started) | 1086 if (result < 0 && !ssl_started) |
1087 return ReconsiderProxyAfterError(result); | 1087 return ReconsiderProxyAfterError(result); |
1088 establishing_tunnel_ = false; | 1088 establishing_tunnel_ = false; |
1089 | 1089 |
1090 // Handle SSL errors below. | 1090 // Handle SSL errors below. |
1091 if (using_ssl_) { | 1091 if (using_ssl_) { |
1092 DCHECK(ssl_started); | 1092 DCHECK(ssl_started); |
1093 if (IsCertificateError(result)) { | 1093 if (IsCertificateError(result)) { |
1094 if (IsSpdyAlternative() && origin_url_.SchemeIs("http")) { | 1094 result = HandleCertificateError(result); |
1095 // We ignore certificate errors for http over spdy. | 1095 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) { |
1096 spdy_certificate_error_ = result; | 1096 ReturnToStateInitConnection(true /* close connection */); |
1097 result = OK; | 1097 return result; |
1098 } else { | |
1099 result = HandleCertificateError(result); | |
1100 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) { | |
1101 ReturnToStateInitConnection(true /* close connection */); | |
1102 return result; | |
1103 } | |
1104 } | 1098 } |
1105 } | 1099 } |
1106 if (result < 0) | 1100 if (result < 0) |
1107 return result; | 1101 return result; |
1108 } | 1102 } |
1109 | 1103 |
1110 next_state_ = STATE_CREATE_STREAM; | 1104 next_state_ = STATE_CREATE_STREAM; |
1111 return OK; | 1105 return OK; |
1112 } | 1106 } |
1113 | 1107 |
(...skipping 15 matching lines...) Expand all Loading... |
1129 return ERR_NOT_IMPLEMENTED; | 1123 return ERR_NOT_IMPLEMENTED; |
1130 if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) { | 1124 if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) { |
1131 bidirectional_stream_impl_.reset(new BidirectionalStreamSpdyImpl(session)); | 1125 bidirectional_stream_impl_.reset(new BidirectionalStreamSpdyImpl(session)); |
1132 return OK; | 1126 return OK; |
1133 } | 1127 } |
1134 | 1128 |
1135 // TODO(willchan): Delete this code, because eventually, the | 1129 // TODO(willchan): Delete this code, because eventually, the |
1136 // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it | 1130 // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it |
1137 // will know when SpdySessions become available. | 1131 // will know when SpdySessions become available. |
1138 | 1132 |
1139 bool use_relative_url = direct || request_info_.url.SchemeIs("https"); | 1133 bool use_relative_url = |
| 1134 direct || request_info_.url.SchemeIs(url::kHttpsScheme); |
1140 stream_.reset(new SpdyHttpStream(session, use_relative_url)); | 1135 stream_.reset(new SpdyHttpStream(session, use_relative_url)); |
1141 return OK; | 1136 return OK; |
1142 } | 1137 } |
1143 | 1138 |
1144 int HttpStreamFactoryImpl::Job::DoCreateStream() { | 1139 int HttpStreamFactoryImpl::Job::DoCreateStream() { |
1145 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462811 is fixed. | 1140 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462811 is fixed. |
1146 tracked_objects::ScopedTracker tracking_profile( | 1141 tracked_objects::ScopedTracker tracking_profile( |
1147 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 1142 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
1148 "462811 HttpStreamFactoryImpl::Job::DoCreateStream")); | 1143 "462811 HttpStreamFactoryImpl::Job::DoCreateStream")); |
1149 DCHECK(connection_->socket() || existing_spdy_session_.get() || using_quic_); | 1144 DCHECK(connection_->socket() || existing_spdy_session_.get() || using_quic_); |
(...skipping 11 matching lines...) Expand all Loading... |
1161 // We only set the socket motivation if we're the first to use | 1156 // We only set the socket motivation if we're the first to use |
1162 // this socket. Is there a race for two SPDY requests? We really | 1157 // this socket. Is there a race for two SPDY requests? We really |
1163 // need to plumb this through to the connect level. | 1158 // need to plumb this through to the connect level. |
1164 if (connection_->socket() && !connection_->is_reused()) | 1159 if (connection_->socket() && !connection_->is_reused()) |
1165 SetSocketMotivation(); | 1160 SetSocketMotivation(); |
1166 | 1161 |
1167 if (!using_spdy_) { | 1162 if (!using_spdy_) { |
1168 DCHECK(!IsSpdyAlternative()); | 1163 DCHECK(!IsSpdyAlternative()); |
1169 // We may get ftp scheme when fetching ftp resources through proxy. | 1164 // We may get ftp scheme when fetching ftp resources through proxy. |
1170 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && | 1165 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && |
1171 (request_info_.url.SchemeIs("http") || | 1166 (request_info_.url.SchemeIs(url::kHttpScheme) || |
1172 request_info_.url.SchemeIs("ftp")); | 1167 request_info_.url.SchemeIs(url::kFtpScheme)); |
1173 if (delegate_->for_websockets()) { | 1168 if (delegate_->for_websockets()) { |
1174 DCHECK_NE(job_type_, PRECONNECT); | 1169 DCHECK_NE(job_type_, PRECONNECT); |
1175 DCHECK(delegate_->websocket_handshake_stream_create_helper()); | 1170 DCHECK(delegate_->websocket_handshake_stream_create_helper()); |
1176 websocket_stream_.reset( | 1171 websocket_stream_.reset( |
1177 delegate_->websocket_handshake_stream_create_helper() | 1172 delegate_->websocket_handshake_stream_create_helper() |
1178 ->CreateBasicStream(std::move(connection_), using_proxy)); | 1173 ->CreateBasicStream(std::move(connection_), using_proxy)); |
1179 } else { | 1174 } else { |
1180 stream_.reset(new HttpBasicStream( | 1175 stream_.reset(new HttpBasicStream( |
1181 std::move(connection_), using_proxy, | 1176 std::move(connection_), using_proxy, |
1182 session_->params().http_09_on_non_default_ports_enabled)); | 1177 session_->params().http_09_on_non_default_ports_enabled)); |
(...skipping 19 matching lines...) Expand all Loading... |
1202 SpdySessionKey spdy_session_key = GetSpdySessionKey(); | 1197 SpdySessionKey spdy_session_key = GetSpdySessionKey(); |
1203 base::WeakPtr<SpdySession> spdy_session = | 1198 base::WeakPtr<SpdySession> spdy_session = |
1204 session_->spdy_session_pool()->FindAvailableSession( | 1199 session_->spdy_session_pool()->FindAvailableSession( |
1205 spdy_session_key, origin_url_, net_log_); | 1200 spdy_session_key, origin_url_, net_log_); |
1206 if (spdy_session) { | 1201 if (spdy_session) { |
1207 return SetSpdyHttpStreamOrBidirectionalStreamImpl(spdy_session, direct); | 1202 return SetSpdyHttpStreamOrBidirectionalStreamImpl(spdy_session, direct); |
1208 } | 1203 } |
1209 | 1204 |
1210 spdy_session = | 1205 spdy_session = |
1211 session_->spdy_session_pool()->CreateAvailableSessionFromSocket( | 1206 session_->spdy_session_pool()->CreateAvailableSessionFromSocket( |
1212 spdy_session_key, std::move(connection_), net_log_, | 1207 spdy_session_key, std::move(connection_), net_log_, OK, using_ssl_); |
1213 spdy_certificate_error_, using_ssl_); | |
1214 | 1208 |
1215 if (!spdy_session->HasAcceptableTransportSecurity()) { | 1209 if (!spdy_session->HasAcceptableTransportSecurity()) { |
1216 spdy_session->CloseSessionOnError( | 1210 spdy_session->CloseSessionOnError( |
1217 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, ""); | 1211 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, ""); |
1218 return ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY; | 1212 return ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY; |
1219 } | 1213 } |
1220 | 1214 |
1221 SSLInfo ssl_info; | 1215 SSLInfo ssl_info; |
1222 if (spdy_session->GetSSLInfo(&ssl_info)) { | 1216 if (spdy_session->GetSSLInfo(&ssl_info)) { |
1223 UMA_HISTOGRAM_SPARSE_SLOWLY( | 1217 UMA_HISTOGRAM_SPARSE_SLOWLY( |
1224 "Net.Http2SSLCipherSuite", | 1218 "Net.Http2SSLCipherSuite", |
1225 SSLConnectionStatusToCipherSuite(ssl_info.connection_status)); | 1219 SSLConnectionStatusToCipherSuite(ssl_info.connection_status)); |
1226 } | 1220 } |
1227 | 1221 |
1228 new_spdy_session_ = spdy_session; | 1222 new_spdy_session_ = spdy_session; |
1229 spdy_session_direct_ = direct; | 1223 spdy_session_direct_ = direct; |
1230 const HostPortPair host_port_pair = spdy_session_key.host_port_pair(); | 1224 const HostPortPair host_port_pair = spdy_session_key.host_port_pair(); |
1231 bool is_https = ssl_info.is_valid(); | 1225 bool is_https = ssl_info.is_valid(); |
1232 url::SchemeHostPort scheme_host_port(is_https ? "https" : "http", | 1226 url::SchemeHostPort scheme_host_port( |
1233 host_port_pair.host(), | 1227 is_https ? url::kHttpsScheme : url::kHttpScheme, host_port_pair.host(), |
1234 host_port_pair.port()); | 1228 host_port_pair.port()); |
1235 | 1229 |
1236 HttpServerProperties* http_server_properties = | 1230 HttpServerProperties* http_server_properties = |
1237 session_->http_server_properties(); | 1231 session_->http_server_properties(); |
1238 if (http_server_properties) | 1232 if (http_server_properties) |
1239 http_server_properties->SetSupportsSpdy(scheme_host_port, true); | 1233 http_server_properties->SetSupportsSpdy(scheme_host_port, true); |
1240 | 1234 |
1241 // Create a SpdyHttpStream or a BidirectionalStreamImpl attached to the | 1235 // Create a SpdyHttpStream or a BidirectionalStreamImpl attached to the |
1242 // session; OnNewSpdySessionReadyCallback is not called until an event loop | 1236 // session; OnNewSpdySessionReadyCallback is not called until an event loop |
1243 // iteration later, so if the SpdySession is closed between then, allow | 1237 // iteration later, so if the SpdySession is closed between then, allow |
1244 // reuse state from the underlying socket, sampled by SpdyHttpStream, | 1238 // reuse state from the underlying socket, sampled by SpdyHttpStream, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) | 1292 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) |
1299 connection_->socket()->SetSubresourceSpeculation(); | 1293 connection_->socket()->SetSubresourceSpeculation(); |
1300 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) | 1294 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) |
1301 connection_->socket()->SetOmniboxSpeculation(); | 1295 connection_->socket()->SetOmniboxSpeculation(); |
1302 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). | 1296 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). |
1303 } | 1297 } |
1304 | 1298 |
1305 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() const { | 1299 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() const { |
1306 if (!proxy_info_.is_https()) | 1300 if (!proxy_info_.is_https()) |
1307 return false; | 1301 return false; |
1308 if (IsSpdyAlternative() || IsQuicAlternative()) { | 1302 DCHECK(!IsSpdyAlternative()); |
| 1303 if (IsQuicAlternative()) { |
1309 // We currently only support Alternate-Protocol where the original scheme | 1304 // We currently only support Alternate-Protocol where the original scheme |
1310 // is http. | 1305 // is http. |
1311 DCHECK(origin_url_.SchemeIs("http")); | 1306 // TODO(bnc): This comment is probably incorrect. |
1312 return origin_url_.SchemeIs("http"); | 1307 DCHECK(origin_url_.SchemeIs(url::kHttpScheme)); |
| 1308 return origin_url_.SchemeIs(url::kHttpScheme); |
1313 } | 1309 } |
1314 return request_info_.url.SchemeIs("http"); | 1310 return request_info_.url.SchemeIs(url::kHttpScheme); |
1315 } | 1311 } |
1316 | 1312 |
1317 bool HttpStreamFactoryImpl::Job::IsSpdyAlternative() const { | 1313 bool HttpStreamFactoryImpl::Job::IsSpdyAlternative() const { |
1318 return alternative_service_.protocol >= NPN_SPDY_MINIMUM_VERSION && | 1314 return alternative_service_.protocol >= NPN_SPDY_MINIMUM_VERSION && |
1319 alternative_service_.protocol <= NPN_SPDY_MAXIMUM_VERSION; | 1315 alternative_service_.protocol <= NPN_SPDY_MAXIMUM_VERSION; |
1320 } | 1316 } |
1321 | 1317 |
1322 bool HttpStreamFactoryImpl::Job::IsQuicAlternative() const { | 1318 bool HttpStreamFactoryImpl::Job::IsQuicAlternative() const { |
1323 return alternative_service_.protocol == QUIC; | 1319 return alternative_service_.protocol == QUIC; |
1324 } | 1320 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1378 case ERR_INTERNET_DISCONNECTED: | 1374 case ERR_INTERNET_DISCONNECTED: |
1379 case ERR_ADDRESS_UNREACHABLE: | 1375 case ERR_ADDRESS_UNREACHABLE: |
1380 case ERR_CONNECTION_CLOSED: | 1376 case ERR_CONNECTION_CLOSED: |
1381 case ERR_CONNECTION_TIMED_OUT: | 1377 case ERR_CONNECTION_TIMED_OUT: |
1382 case ERR_CONNECTION_RESET: | 1378 case ERR_CONNECTION_RESET: |
1383 case ERR_CONNECTION_REFUSED: | 1379 case ERR_CONNECTION_REFUSED: |
1384 case ERR_CONNECTION_ABORTED: | 1380 case ERR_CONNECTION_ABORTED: |
1385 case ERR_TIMED_OUT: | 1381 case ERR_TIMED_OUT: |
1386 case ERR_TUNNEL_CONNECTION_FAILED: | 1382 case ERR_TUNNEL_CONNECTION_FAILED: |
1387 case ERR_SOCKS_CONNECTION_FAILED: | 1383 case ERR_SOCKS_CONNECTION_FAILED: |
1388 // This can happen in the case of trying to talk to a proxy using SSL, and | 1384 // ERR_PROXY_CERTIFICATE_INVALID can happen in the case of trying to talk to |
1389 // ending up talking to a captive portal that supports SSL instead. | 1385 // a proxy using SSL, and ending up talking to a captive portal that |
| 1386 // supports SSL instead. |
1390 case ERR_PROXY_CERTIFICATE_INVALID: | 1387 case ERR_PROXY_CERTIFICATE_INVALID: |
1391 // This can happen when trying to talk SSL to a non-SSL server (Like a | |
1392 // captive portal). | |
1393 case ERR_QUIC_PROTOCOL_ERROR: | 1388 case ERR_QUIC_PROTOCOL_ERROR: |
1394 case ERR_QUIC_HANDSHAKE_FAILED: | 1389 case ERR_QUIC_HANDSHAKE_FAILED: |
1395 case ERR_MSG_TOO_BIG: | 1390 case ERR_MSG_TOO_BIG: |
| 1391 // ERR_SSL_PROTOCOL_ERROR can happen when trying to talk SSL to a non-SSL |
| 1392 // server (like a captive portal). |
1396 case ERR_SSL_PROTOCOL_ERROR: | 1393 case ERR_SSL_PROTOCOL_ERROR: |
1397 break; | 1394 break; |
1398 case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: | 1395 case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: |
1399 // Remap the SOCKS-specific "host unreachable" error to a more | 1396 // Remap the SOCKS-specific "host unreachable" error to a more |
1400 // generic error code (this way consumers like the link doctor | 1397 // generic error code (this way consumers like the link doctor |
1401 // know to substitute their error page). | 1398 // know to substitute their error page). |
1402 // | 1399 // |
1403 // Note that if the host resolving was done by the SOCKS5 proxy, we can't | 1400 // Note that if the host resolving was done by the SOCKS5 proxy, we can't |
1404 // differentiate between a proxy-side "host not found" versus a proxy-side | 1401 // differentiate between a proxy-side "host not found" versus a proxy-side |
1405 // "address unreachable" error, and will report both of these failures as | 1402 // "address unreachable" error, and will report both of these failures as |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 ssl_info_.cert_status); | 1470 ssl_info_.cert_status); |
1474 | 1471 |
1475 int load_flags = request_info_.load_flags; | 1472 int load_flags = request_info_.load_flags; |
1476 if (session_->params().ignore_certificate_errors) | 1473 if (session_->params().ignore_certificate_errors) |
1477 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; | 1474 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; |
1478 if (ssl_socket->IgnoreCertError(error, load_flags)) | 1475 if (ssl_socket->IgnoreCertError(error, load_flags)) |
1479 return OK; | 1476 return OK; |
1480 return error; | 1477 return error; |
1481 } | 1478 } |
1482 | 1479 |
1483 void HttpStreamFactoryImpl::Job::SwitchToSpdyMode() { | |
1484 using_spdy_ = true; | |
1485 } | |
1486 | |
1487 void HttpStreamFactoryImpl::Job::ReportJobSucceededForRequest() { | 1480 void HttpStreamFactoryImpl::Job::ReportJobSucceededForRequest() { |
1488 if (using_existing_quic_session_) { | 1481 if (using_existing_quic_session_) { |
1489 // If an existing session was used, then no TCP connection was | 1482 // If an existing session was used, then no TCP connection was |
1490 // started. | 1483 // started. |
1491 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE); | 1484 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE); |
1492 } else if (IsSpdyAlternative() || IsQuicAlternative()) { | 1485 } else if (IsSpdyAlternative() || IsQuicAlternative()) { |
1493 // This Job was the alternative Job, and hence won the race. | 1486 // This Job was the alternative Job, and hence won the race. |
1494 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); | 1487 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); |
1495 } else { | 1488 } else { |
1496 // This Job was the normal Job, and hence the alternative Job lost the race. | 1489 // This Job was the normal Job, and hence the alternative Job lost the race. |
1497 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); | 1490 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); |
1498 } | 1491 } |
1499 } | 1492 } |
1500 | 1493 |
1501 ClientSocketPoolManager::SocketGroupType | 1494 ClientSocketPoolManager::SocketGroupType |
1502 HttpStreamFactoryImpl::Job::GetSocketGroup() const { | 1495 HttpStreamFactoryImpl::Job::GetSocketGroup() const { |
1503 std::string scheme = origin_url_.scheme(); | 1496 std::string scheme = origin_url_.scheme(); |
1504 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative()) | 1497 if (scheme == url::kHttpsScheme || scheme == url::kWssScheme) |
1505 return ClientSocketPoolManager::SSL_GROUP; | 1498 return ClientSocketPoolManager::SSL_GROUP; |
1506 | 1499 |
1507 if (scheme == "ftp") | 1500 if (scheme == url::kFtpScheme) |
1508 return ClientSocketPoolManager::FTP_GROUP; | 1501 return ClientSocketPoolManager::FTP_GROUP; |
1509 | 1502 |
1510 return ClientSocketPoolManager::NORMAL_GROUP; | 1503 return ClientSocketPoolManager::NORMAL_GROUP; |
1511 } | 1504 } |
1512 | 1505 |
1513 // If the connection succeeds, failed connection attempts leading up to the | 1506 // If the connection succeeds, failed connection attempts leading up to the |
1514 // success will be returned via the successfully connected socket. If the | 1507 // success will be returned via the successfully connected socket. If the |
1515 // connection fails, failed connection attempts will be returned via the | 1508 // connection fails, failed connection attempts will be returned via the |
1516 // ClientSocketHandle. Check whether a socket was returned and copy the | 1509 // ClientSocketHandle. Check whether a socket was returned and copy the |
1517 // connection attempts from the proper place. | 1510 // connection attempts from the proper place. |
1518 void HttpStreamFactoryImpl::Job:: | 1511 void HttpStreamFactoryImpl::Job:: |
1519 MaybeCopyConnectionAttemptsFromSocketOrHandle() { | 1512 MaybeCopyConnectionAttemptsFromSocketOrHandle() { |
1520 if (!connection_) | 1513 if (!connection_) |
1521 return; | 1514 return; |
1522 | 1515 |
1523 ConnectionAttempts socket_attempts = connection_->connection_attempts(); | 1516 ConnectionAttempts socket_attempts = connection_->connection_attempts(); |
1524 if (connection_->socket()) { | 1517 if (connection_->socket()) { |
1525 connection_->socket()->GetConnectionAttempts(&socket_attempts); | 1518 connection_->socket()->GetConnectionAttempts(&socket_attempts); |
1526 } | 1519 } |
1527 | 1520 |
1528 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); | 1521 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); |
1529 } | 1522 } |
1530 | 1523 |
1531 } // namespace net | 1524 } // namespace net |
OLD | NEW |