summaryrefslogtreecommitdiff
path: root/chromium/net/http/http_proxy_connect_job.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-12 15:59:20 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-25 06:57:22 +0000
commitf7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch)
treecaed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/net/http/http_proxy_connect_job.cc
parent9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff)
downloadqtwebengine-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.cc219
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());