| 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 |