diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-12 15:59:20 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-25 06:57:22 +0000 |
commit | f7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch) | |
tree | caed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/net/http/http_proxy_connect_job.cc | |
parent | 9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff) | |
download | qtwebengine-chromium-f7eaed5286974984ba5f9e3189d8f49d03e99f81.tar.gz |
BASELINE: Update Chromium to 100.0.4896.167
Change-Id: I98cbeb5d7543d966ffe04d8cefded0c493a11333
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/http/http_proxy_connect_job.cc')
-rw-r--r-- | chromium/net/http/http_proxy_connect_job.cc | 219 |
1 files changed, 92 insertions, 127 deletions
diff --git a/chromium/net/http/http_proxy_connect_job.cc b/chromium/net/http/http_proxy_connect_job.cc index e1ecdd71bbf..5fadbafb011 100644 --- a/chromium/net/http/http_proxy_connect_job.cc +++ b/chromium/net/http/http_proxy_connect_job.cc @@ -12,12 +12,13 @@ #include "base/cxx17_backports.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" -#include "base/metrics/histogram_macros.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/build_config.h" +#include "http_proxy_client_socket.h" #include "net/base/host_port_pair.h" #include "net/base/http_user_agent_settings.h" #include "net/base/net_errors.h" @@ -27,8 +28,8 @@ #include "net/quic/quic_http_utils.h" #include "net/quic/quic_proxy_client_socket.h" #include "net/quic/quic_stream_factory.h" -#include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" +#include "net/socket/next_proto.h" #include "net/socket/ssl_client_socket.h" #include "net/socket/ssl_connect_job.h" #include "net/socket/transport_client_socket_pool.h" @@ -49,7 +50,7 @@ namespace { // HttpProxyConnectJobs will time out after this many seconds. Note this is in // addition to the timeout for the transport socket. -#if defined(OS_ANDROID) || defined(OS_IOS) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) constexpr base::TimeDelta kHttpProxyConnectJobTunnelTimeout = base::Seconds(10); #else constexpr base::TimeDelta kHttpProxyConnectJobTunnelTimeout = base::Seconds(30); @@ -189,8 +190,6 @@ HttpProxyConnectJob::HttpProxyConnectJob( params_(std::move(params)), next_state_(STATE_NONE), has_restarted_(false), - using_spdy_(false), - negotiated_protocol_(kProtoUnknown), has_established_connection_(false), http_auth_controller_( params_->tunnel() @@ -211,8 +210,7 @@ const RequestPriority HttpProxyConnectJob::kH2QuicTunnelPriority = LoadState HttpProxyConnectJob::GetLoadState() const { switch (next_state_) { - case STATE_TCP_CONNECT_COMPLETE: - case STATE_SSL_CONNECT_COMPLETE: + case STATE_TRANSPORT_CONNECT_COMPLETE: return nested_connect_job_->GetLoadState(); case STATE_HTTP_PROXY_CONNECT: case STATE_HTTP_PROXY_CONNECT_COMPLETE: @@ -224,10 +222,10 @@ LoadState HttpProxyConnectJob::GetLoadState() const { case STATE_RESTART_WITH_AUTH: case STATE_RESTART_WITH_AUTH_COMPLETE: return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; - // These states shouldn't be possible to be called in. - case STATE_TCP_CONNECT: - case STATE_SSL_CONNECT: - + // This state shouldn't be possible to be called in. + case STATE_TRANSPORT_CONNECT: + NOTREACHED(); + [[fallthrough]]; case STATE_BEGIN_CONNECT: case STATE_NONE: // May be possible for this method to be called after an error, shouldn't @@ -263,8 +261,7 @@ scoped_refptr<SSLCertRequestInfo> HttpProxyConnectJob::GetCertRequestInfo() { void HttpProxyConnectJob::OnConnectJobComplete(int result, ConnectJob* job) { DCHECK_EQ(nested_connect_job_.get(), job); - DCHECK(next_state_ == STATE_TCP_CONNECT_COMPLETE || - next_state_ == STATE_SSL_CONNECT_COMPLETE); + DCHECK_EQ(next_state_, STATE_TRANSPORT_CONNECT_COMPLETE); OnIOComplete(result); } @@ -287,9 +284,9 @@ base::TimeDelta HttpProxyConnectJob::AlternateNestedConnectionTimeout( // On Android and iOS, a default proxy connection timeout is used instead of // the actual TCP/SSL timeouts of nested jobs. -#if defined(OS_ANDROID) || defined(OS_IOS) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) default_alternate_timeout = kHttpProxyConnectJobTunnelTimeout; -#endif // !defined(OS_ANDROID) && !defined(OS_IOS) +#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) bool is_https = params.ssl_params() != nullptr; // HTTP proxy connections can't be on top of proxy connections. @@ -326,10 +323,7 @@ void HttpProxyConnectJob::UpdateFieldTrialParametersForTesting() { int HttpProxyConnectJob::ConnectInternal() { DCHECK_EQ(next_state_, STATE_NONE); next_state_ = STATE_BEGIN_CONNECT; - int result = DoLoop(OK); - if (result != ERR_IO_PENDING) - HandleConnectResult(result); - return result; + return DoLoop(OK); } ProxyServer::Scheme HttpProxyConnectJob::GetProxyServerScheme() const { @@ -345,8 +339,6 @@ ProxyServer::Scheme HttpProxyConnectJob::GetProxyServerScheme() const { void HttpProxyConnectJob::OnIOComplete(int result) { int rv = DoLoop(result); if (rv != ERR_IO_PENDING) { - HandleConnectResult(rv); - // May delete |this|. NotifyDelegateOfCompletion(rv); } @@ -375,20 +367,13 @@ int HttpProxyConnectJob::DoLoop(int result) { DCHECK_EQ(OK, rv); rv = DoBeginConnect(); break; - case STATE_TCP_CONNECT: + case STATE_TRANSPORT_CONNECT: DCHECK_EQ(OK, rv); rv = DoTransportConnect(); break; - case STATE_TCP_CONNECT_COMPLETE: + case STATE_TRANSPORT_CONNECT_COMPLETE: rv = DoTransportConnectComplete(rv); break; - case STATE_SSL_CONNECT: - DCHECK_EQ(OK, rv); - rv = DoSSLConnect(); - break; - case STATE_SSL_CONNECT_COMPLETE: - rv = DoSSLConnectComplete(rv); - break; case STATE_HTTP_PROXY_CONNECT: DCHECK_EQ(OK, rv); rv = DoHttpProxyConnect(); @@ -444,10 +429,8 @@ int HttpProxyConnectJob::DoBeginConnect() { has_established_connection_ = true; break; case ProxyServer::SCHEME_HTTP: - next_state_ = STATE_TCP_CONNECT; - break; case ProxyServer::SCHEME_HTTPS: - next_state_ = STATE_SSL_CONNECT; + next_state_ = STATE_TRANSPORT_CONNECT; break; default: NOTREACHED(); @@ -456,87 +439,82 @@ int HttpProxyConnectJob::DoBeginConnect() { } int HttpProxyConnectJob::DoTransportConnect() { - next_state_ = STATE_TCP_CONNECT_COMPLETE; - nested_connect_job_ = TransportConnectJob::CreateTransportConnectJob( - params_->transport_params(), priority(), socket_tag(), - common_connect_job_params(), this, &net_log()); - return nested_connect_job_->Connect(); -} - -int HttpProxyConnectJob::DoTransportConnectComplete(int result) { - resolve_error_info_ = nested_connect_job_->GetResolveErrorInfo(); - if (result != OK) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Insecure.Error", - base::TimeTicks::Now() - connect_start_time_); - return ERR_PROXY_CONNECTION_FAILED; - } - - has_established_connection_ = true; - - next_state_ = STATE_HTTP_PROXY_CONNECT; - return result; -} - -int HttpProxyConnectJob::DoSSLConnect() { - DCHECK(params_->ssl_params()); - if (params_->tunnel()) { - if (common_connect_job_params()->spdy_session_pool->FindAvailableSession( - CreateSpdySessionKey(), /* enable_ip_based_pooling = */ false, - /* is_websocket = */ false, net_log())) { - using_spdy_ = true; + ProxyServer::Scheme scheme = GetProxyServerScheme(); + if (scheme == ProxyServer::SCHEME_HTTP) { + nested_connect_job_ = TransportConnectJob::CreateTransportConnectJob( + params_->transport_params(), priority(), socket_tag(), + common_connect_job_params(), this, &net_log()); + } else { + DCHECK_EQ(scheme, ProxyServer::SCHEME_HTTPS); + DCHECK(params_->ssl_params()); + // Skip making a new connection if we have an existing HTTP/2 session. + if (params_->tunnel() && + common_connect_job_params()->spdy_session_pool->FindAvailableSession( + CreateSpdySessionKey(), /*enable_ip_based_pooling=*/false, + /*is_websocket=*/false, net_log())) { next_state_ = STATE_SPDY_PROXY_CREATE_STREAM; return OK; } + + nested_connect_job_ = std::make_unique<SSLConnectJob>( + priority(), socket_tag(), common_connect_job_params(), + params_->ssl_params(), this, &net_log()); } - next_state_ = STATE_SSL_CONNECT_COMPLETE; - nested_connect_job_ = std::make_unique<SSLConnectJob>( - priority(), socket_tag(), common_connect_job_params(), - params_->ssl_params(), this, &net_log()); + + next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; return nested_connect_job_->Connect(); } -int HttpProxyConnectJob::DoSSLConnectComplete(int result) { +int HttpProxyConnectJob::DoTransportConnectComplete(int result) { resolve_error_info_ = nested_connect_job_->GetResolveErrorInfo(); - if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Error", - base::TimeTicks::Now() - connect_start_time_); + ProxyServer::Scheme scheme = GetProxyServerScheme(); + if (result != OK) { + base::UmaHistogramMediumTimes( + scheme == ProxyServer::SCHEME_HTTP + ? "Net.HttpProxy.ConnectLatency.Insecure.Error" + : "Net.HttpProxy.ConnectLatency.Secure.Error", + base::TimeTicks::Now() - connect_start_time_); + + if (IsCertificateError(result)) { + DCHECK_EQ(ProxyServer::SCHEME_HTTPS, scheme); + // TODO(rch): allow the user to deal with proxy cert errors in the + // same way as server cert errors. + return ERR_PROXY_CERTIFICATE_INVALID; + } - ssl_cert_request_info_ = nested_connect_job_->GetCertRequestInfo(); - DCHECK(ssl_cert_request_info_); - ssl_cert_request_info_->is_proxy = true; - return result; - } + if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { + DCHECK_EQ(ProxyServer::SCHEME_HTTPS, scheme); + ssl_cert_request_info_ = nested_connect_job_->GetCertRequestInfo(); + DCHECK(ssl_cert_request_info_); + ssl_cert_request_info_->is_proxy = true; + return result; + } - if (IsCertificateError(result)) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Error", - base::TimeTicks::Now() - connect_start_time_); - // TODO(rch): allow the user to deal with proxy cert errors in the - // same way as server cert errors. - return ERR_PROXY_CERTIFICATE_INVALID; - } - if (result < 0) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Error", - base::TimeTicks::Now() - connect_start_time_); return ERR_PROXY_CONNECTION_FAILED; } - has_established_connection_ = true; + base::UmaHistogramMediumTimes( + scheme == ProxyServer::SCHEME_HTTP + ? "Net.HttpProxy.ConnectLatency.Insecure.Success" + : "Net.HttpProxy.ConnectLatency.Secure.Success", + base::TimeTicks::Now() - connect_start_time_); - negotiated_protocol_ = nested_connect_job_->socket()->GetNegotiatedProtocol(); - using_spdy_ = negotiated_protocol_ == kProtoHTTP2; + has_established_connection_ = true; - // Reset the timer to just the length of time allowed for HttpProxy handshake - // so that a fast SSL connection plus a slow HttpProxy failure doesn't take - // longer to timeout than it should. - ResetTimer(kHttpProxyConnectJobTunnelTimeout); + if (!params_->tunnel()) { + // If not tunneling, this is an HTTP URL being fetched directly over the + // proxy. Return the underlying socket directly. The caller will handle the + // ALPN protocol, etc., from here. Clear the DNS aliases to match the other + // proxy codepaths. + SetSocket(nested_connect_job_->PassSocket(), + /*dns_aliases=*/std::set<std::string>()); + return result; + } - // TODO(rch): If we ever decide to implement a "trusted" SPDY proxy - // (one that we speak SPDY over SSL to, but to which we send HTTPS - // request directly instead of through CONNECT tunnels, then we - // need to add a predicate to this if statement so we fall through - // to the else case. (HttpProxyClientSocket currently acts as - // a "trusted" SPDY proxy). - if (using_spdy_ && params_->tunnel()) { + // Establish a tunnel over the proxy by making a CONNECT request. HTTP/1.1 and + // HTTP/2 handle CONNECT differently. + if (nested_connect_job_->socket()->GetNegotiatedProtocol() == kProtoHTTP2) { + DCHECK_EQ(ProxyServer::SCHEME_HTTPS, scheme); next_state_ = STATE_SPDY_PROXY_CREATE_STREAM; } else { next_state_ = STATE_HTTP_PROXY_CONNECT; @@ -545,6 +523,7 @@ int HttpProxyConnectJob::DoSSLConnectComplete(int result) { } int HttpProxyConnectJob::DoHttpProxyConnect() { + DCHECK(params_->tunnel()); next_state_ = STATE_HTTP_PROXY_CONNECT_COMPLETE; // Reset the timer to just the length of time allowed for HttpProxy handshake @@ -552,20 +531,11 @@ int HttpProxyConnectJob::DoHttpProxyConnect() { // longer to timeout than it should. ResetTimer(kHttpProxyConnectJobTunnelTimeout); - if (params_->transport_params()) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Insecure.Success", - base::TimeTicks::Now() - connect_start_time_); - } else { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.Success", - base::TimeTicks::Now() - connect_start_time_); - } - // Add a HttpProxy connection on top of the tcp socket. - transport_socket_ = client_socket_factory()->CreateProxyClientSocket( + transport_socket_ = std::make_unique<HttpProxyClientSocket>( nested_connect_job_->PassSocket(), GetUserAgent(), params_->endpoint(), ProxyServer(GetProxyServerScheme(), GetDestination()), - http_auth_controller_.get(), params_->tunnel(), using_spdy_, - negotiated_protocol_, common_connect_job_params()->proxy_delegate, + http_auth_controller_.get(), common_connect_job_params()->proxy_delegate, params_->traffic_annotation()); nested_connect_job_.reset(); return transport_socket_->Connect(base::BindOnce( @@ -586,16 +556,19 @@ int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) { // In TLS 1.2 with False Start or TLS 1.3, alerts from the server rejecting // our client certificate are received at the first Read(), not Connect(), so - // the error mapping in DoSSLConnectComplete does not apply. Repeat the + // the error mapping in DoTransportConnectComplete does not apply. Repeat the // mapping here. if (result == ERR_BAD_SSL_CLIENT_AUTH_CERT) return ERR_PROXY_CONNECTION_FAILED; + if (result == OK) { + SetSocket(std::move(transport_socket_), /*dns_aliases=*/absl::nullopt); + } + return result; } int HttpProxyConnectJob::DoSpdyProxyCreateStream() { - DCHECK(using_spdy_); DCHECK(params_->tunnel()); DCHECK(params_->ssl_params()); @@ -667,8 +640,8 @@ int HttpProxyConnectJob::DoQuicProxyCreateSession() { DCHECK(!common_connect_job_params()->quic_supported_versions->empty()); // Reset the timer to just the length of time allowed for HttpProxy handshake - // so that a fast TCP connection plus a slow HttpProxy failure doesn't take - // longer to timeout than it should. + // so that a fast QUIC connection plus a slow tunnel setup doesn't take longer + // to timeout than it should. ResetTimer(kHttpProxyConnectJobTunnelTimeout); next_state_ = STATE_QUIC_PROXY_CREATE_STREAM; @@ -776,8 +749,6 @@ int HttpProxyConnectJob::DoRestartWithAuthComplete(int result) { if (reconnect) { // Attempt to create a new one. transport_socket_.reset(); - using_spdy_ = false; - negotiated_protocol_ = NextProto(); next_state_ = STATE_BEGIN_CONNECT; return OK; } @@ -801,21 +772,15 @@ void HttpProxyConnectJob::ChangePriorityInternal(RequestPriority priority) { } void HttpProxyConnectJob::OnTimedOutInternal() { - if (next_state_ == STATE_TCP_CONNECT_COMPLETE) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Insecure.TimedOut", - base::TimeTicks::Now() - connect_start_time_); - } else if (next_state_ == STATE_SSL_CONNECT_COMPLETE) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Secure.TimedOut", - base::TimeTicks::Now() - connect_start_time_); + if (next_state_ == STATE_TRANSPORT_CONNECT_COMPLETE) { + base::UmaHistogramMediumTimes( + GetProxyServerScheme() == ProxyServer::SCHEME_HTTP + ? "Net.HttpProxy.ConnectLatency.Insecure.TimedOut" + : "Net.HttpProxy.ConnectLatency.Secure.TimedOut", + base::TimeTicks::Now() - connect_start_time_); } } -int HttpProxyConnectJob::HandleConnectResult(int result) { - if (result == OK) - SetSocket(std::move(transport_socket_), absl::nullopt /* dns_aliases */); - return result; -} - void HttpProxyConnectJob::OnAuthChallenge() { // Stop timer while potentially waiting for user input. ResetTimer(base::TimeDelta()); |