// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/http_network_transaction.h"

#include <math.h>  // ceil
#include <stdarg.h>
#include <stdint.h>

#include <algorithm>
#include <array>
#include <limits>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "net/base/auth.h"
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/completion_once_callback.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/features.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/load_timing_internal_info.h"
#include "net/base/net_errors.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/network_isolation_key.h"
#include "net/base/privacy_mode.h"
#include "net/base/proxy_chain.h"
#include "net/base/proxy_delegate.h"
#include "net/base/proxy_server.h"
#include "net/base/proxy_string_util.h"
#include "net/base/request_priority.h"
#include "net/base/schemeful_site.h"
#include "net/base/session_usage.h"
#include "net/base/test_completion_callback.h"
#include "net/base/test_proxy_delegate.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_handler_digest.h"
#include "net/http/http_auth_handler_mock.h"
#include "net/http/http_auth_handler_ntlm.h"
#include "net/http/http_auth_ntlm_mechanism.h"
#include "net/http/http_auth_scheme.h"
#include "net/http/http_basic_stream.h"
#include "net/http/http_network_session.h"
#include "net/http/http_network_session_peer.h"
#include "net/http/http_proxy_connect_job.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_stream.h"
#include "net/http/http_stream_factory.h"
#include "net/http/http_stream_pool.h"
#include "net/http/http_stream_pool_group.h"
#include "net/http/http_stream_pool_test_util.h"
#include "net/http/http_transaction_test_util.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/net_buildflags.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/proxy_resolution/mock_proxy_resolver.h"
#include "net/proxy_resolution/proxy_config_service_fixed.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "net/proxy_resolution/proxy_resolver_factory.h"
#include "net/reporting/reporting_target_type.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_pool.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/connect_job.h"
#include "net/socket/connection_attempts.h"
#include "net/socket/mock_client_socket_pool_manager.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_pool_additional_capacity.h"
#include "net/socket/socket_tag.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/socks_connect_job.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
#include "net/spdy/spdy_test_util_common.h"
#include "net/ssl/client_cert_identity_test_util.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_info.h"
#include "net/ssl/ssl_private_key.h"
#include "net/ssl/test_ssl_config_service.h"
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
#include "net/test/test_with_task_environment.h"
#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h"
#include "net/third_party/quiche/src/quiche/http2/core/spdy_framer.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/websockets/websocket_handshake_stream_base.h"
#include "net/websockets/websocket_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "url/gurl.h"
#include "url/scheme_host_port.h"
#include "url/url_constants.h"

#if defined(NTLM_PORTABLE)
#include "base/base64.h"
#include "net/ntlm/ntlm_test_data.h"
#endif

#if BUILDFLAG(ENABLE_REPORTING)
#include "net/network_error_logging/network_error_logging_service.h"
#include "net/network_error_logging/network_error_logging_test_util.h"
#include "net/reporting/reporting_cache.h"
#include "net/reporting/reporting_endpoint.h"
#include "net/reporting/reporting_header_parser.h"
#include "net/reporting/reporting_service.h"
#include "net/reporting/reporting_test_util.h"
#endif  // BUILDFLAG(ENABLE_REPORTING)

using net::test::IsError;
using net::test::IsOk;

using base::ASCIIToUTF16;

using testing::AnyOf;
using testing::ElementsAre;
using testing::IsEmpty;

//-----------------------------------------------------------------------------

namespace net {

namespace {

const std::u16string kBar(u"bar");
const std::u16string kBar2(u"bar2");
const std::u16string kBar3(u"bar3");
const std::u16string kBaz(u"baz");
const std::u16string kFirst(u"first");
const std::u16string kFoo(u"foo");
const std::u16string kFoo2(u"foo2");
const std::u16string kFoo3(u"foo3");
const std::u16string kFou(u"fou");
const std::u16string kSecond(u"second");
const std::u16string kWrongPassword(u"wrongpassword");

const char kAlternativeServiceHttpHeader[] =
    "Alt-Svc: h2=\"mail.example.org:443\"\r\n";

constexpr char kStreamRequestSuccessHistogram[] =
    "Net.NetworkTransaction.StreamRequestCompleteTime2.Success";
constexpr char kStreamRequestFailureHistogram[] =
    "Net.NetworkTransaction.StreamRequestCompleteTime2.Failure";
constexpr char kStreamRequestH3SuccessHistogram[] =
    "Net.NetworkTransaction.StreamRequestCompleteTime2.GoogleHost.Success";

int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    return session->http_stream_pool()->TotalIdleStreamCount();
  }
  return session
      ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
                      ProxyChain::Direct())
      ->IdleSocketCount();
}

bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    // When the HappyEyeballsV3 feature is enabled, we need to run pending tasks
    // to ensure that HttpStreamFactory::JobController switches to
    // HttpStreamPool.
    base::RunLoop().RunUntilIdle();
    return session->http_stream_pool()->IsPoolStalled();
  }
  return session
      ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
                      ProxyChain::Direct())
      ->IsStalled();
}

// Takes in a Value created from a NetLogHttpResponseParameter, and returns
// a JSONified list of headers as a single string.  Uses single quotes instead
// of double quotes for easier comparison.
std::string GetHeaders(const base::Value::Dict& params) {
  const base::Value::List* header_list = params.FindList("headers");
  if (!header_list) {
    return "";
  }
  std::string headers;
  base::JSONWriter::Write(*header_list, &headers);
  base::ReplaceChars(headers, "\"", "'", &headers);
  return headers;
}

// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
// used.
void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
  EXPECT_TRUE(load_timing_info.socket_reused);
  EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);

  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());

  ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
  EXPECT_FALSE(load_timing_info.send_start.is_null());

  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);

  // Set at a higher level.
  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
  EXPECT_TRUE(load_timing_info.request_start.is_null());
  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}

// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
// used.
void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
                             int connect_timing_flags) {
  EXPECT_FALSE(load_timing_info.socket_reused);
  EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);

  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());

  ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
                              connect_timing_flags);
  EXPECT_LE(load_timing_info.connect_timing.connect_end,
            load_timing_info.send_start);

  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);

  // Set at a higher level.
  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
  EXPECT_TRUE(load_timing_info.request_start.is_null());
  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}

// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
// used.
void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
  EXPECT_TRUE(load_timing_info.socket_reused);
  EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);

  ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);

  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
  EXPECT_LE(load_timing_info.proxy_resolve_start,
            load_timing_info.proxy_resolve_end);
  EXPECT_LE(load_timing_info.proxy_resolve_end, load_timing_info.send_start);
  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);

  // Set at a higher level.
  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
  EXPECT_TRUE(load_timing_info.request_start.is_null());
  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}

// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
// used.
void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
                                    int connect_timing_flags) {
  EXPECT_FALSE(load_timing_info.socket_reused);
  EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);

  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
  EXPECT_LE(load_timing_info.proxy_resolve_start,
            load_timing_info.proxy_resolve_end);
  EXPECT_LE(load_timing_info.proxy_resolve_end,
            load_timing_info.connect_timing.connect_start);
  ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
                              connect_timing_flags);
  EXPECT_LE(load_timing_info.connect_timing.connect_end,
            load_timing_info.send_start);

  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);

  // Set at a higher level.
  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
  EXPECT_TRUE(load_timing_info.request_start.is_null());
  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}

// ProxyResolver that records URLs passed to it, and that can be told what
// result to return.
class CapturingProxyResolver : public ProxyResolver {
 public:
  struct LookupInfo {
    GURL url;
    NetworkAnonymizationKey network_anonymization_key;
  };

  CapturingProxyResolver()
      : proxy_chain_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}

  CapturingProxyResolver(const CapturingProxyResolver&) = delete;
  CapturingProxyResolver& operator=(const CapturingProxyResolver&) = delete;

  ~CapturingProxyResolver() override = default;

  int GetProxyForURL(const GURL& url,
                     const NetworkAnonymizationKey& network_anonymization_key,
                     ProxyInfo* results,
                     CompletionOnceCallback callback,
                     std::unique_ptr<Request>* request,
                     const NetLogWithSource& net_log) override {
    results->UseProxyChain(proxy_chain_);
    lookup_info_.push_back(LookupInfo{url, network_anonymization_key});
    return OK;
  }

  // Sets whether the resolver should use direct connections, instead of a
  // proxy.
  void set_proxy_chain(const ProxyChain& proxy_chain) {
    proxy_chain_ = proxy_chain;
  }

  const std::vector<LookupInfo>& lookup_info() const { return lookup_info_; }

 private:
  std::vector<LookupInfo> lookup_info_;

  ProxyChain proxy_chain_;
};

class CapturingProxyResolverFactory : public ProxyResolverFactory {
 public:
  explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
      : ProxyResolverFactory(false), resolver_(resolver) {}

  int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
                          std::unique_ptr<ProxyResolver>* resolver,
                          CompletionOnceCallback callback,
                          std::unique_ptr<Request>* request) override {
    *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
    return OK;
  }

 private:
  raw_ptr<ProxyResolver> resolver_ = nullptr;
};

std::unique_ptr<HttpNetworkSession> CreateSession(
    SpdySessionDependencies* session_deps) {
  return SpdySessionDependencies::SpdyCreateSession(session_deps);
}

class FailingProxyResolverFactory : public ProxyResolverFactory {
 public:
  FailingProxyResolverFactory() : ProxyResolverFactory(false) {}

  // ProxyResolverFactory override.
  int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
                          std::unique_ptr<ProxyResolver>* result,
                          CompletionOnceCallback callback,
                          std::unique_ptr<Request>* request) override {
    return ERR_PAC_SCRIPT_FAILED;
  }
};

// A default minimal HttpRequestInfo for use in tests, targeting HTTP.
HttpRequestInfo DefaultRequestInfo() {
  HttpRequestInfo info;
  info.method = "GET";
  info.url = GURL("http://foo.test");
  info.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  return info;
}

// The default info for transports to the embedded HTTP server.
TransportInfo EmbeddedHttpServerTransportInfo() {
  TransportInfo info;
  info.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 80);
  return info;
}

struct TestParams {
  explicit TestParams(bool happy_eyeballs_v3_enabled)
      : happy_eyeballs_v3_enabled(happy_eyeballs_v3_enabled) {}

  bool happy_eyeballs_v3_enabled;
};

std::vector<TestParams> GetTestParams() {
  return {TestParams(/*happy_eyeballs_v3_enabled=*/false),
          TestParams(/*happy_eyeballs_v3_enabled=*/true)};
}

}  // namespace

// TODO(crbug.com/365771838): Add tests for non-ip protection nested proxy
// chains if support is enabled for all builds.
class HttpNetworkTransactionTestBase : public PlatformTest,
                                       public WithTaskEnvironment {
 public:
  ~HttpNetworkTransactionTestBase() override {
    // Important to restore the per-pool limit first, since the pool limit must
    // always be greater than group limit, and the tests reduce both limits.
    ClientSocketPoolManager::set_socket_soft_cap_per_pool_for_test(
        HttpNetworkSession::NORMAL_SOCKET_POOL, old_socket_soft_cap_);
    ClientSocketPoolManager::set_max_sockets_per_group_for_test(
        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
  }

 protected:
  HttpNetworkTransactionTestBase()
      : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
        dummy_connect_job_params_(
            /*client_socket_factory=*/nullptr,
            /*host_resolver=*/nullptr,
            /*http_auth_cache=*/nullptr,
            /*http_auth_handler_factory=*/nullptr,
            /*spdy_session_pool=*/nullptr,
            /*quic_supported_versions=*/nullptr,
            /*quic_session_pool=*/nullptr,
            /*proxy_delegate=*/nullptr,
            /*http_user_agent_settings=*/nullptr,
            /*ssl_client_context=*/nullptr,
            /*socket_performance_watcher_factory=*/nullptr,
            /*network_quality_estimator=*/nullptr,
            /*net_log=*/NetLog::Get(),
            /*websocket_endpoint_lock_manager=*/nullptr,
            /*http_server_properties=*/nullptr,
            /*alpn_protos=*/nullptr,
            /*application_settings=*/nullptr,
            /*ignore_certificate_errors=*/nullptr,
            /*early_data_enabled=*/nullptr),
        spdy_util_(/*use_priority_header=*/true),
        ssl_(ASYNC, OK),
        old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
            HttpNetworkSession::NORMAL_SOCKET_POOL)),
        old_socket_soft_cap_(ClientSocketPoolManager::socket_soft_cap_per_pool(
            HttpNetworkSession::NORMAL_SOCKET_POOL)) {
    session_deps_.enable_http2_alternative_service = true;
  }

  struct SimpleGetHelperResult {
    int rv;
    std::string status_line;
    std::string response_data;
    int64_t total_received_bytes;
    int64_t total_sent_bytes;
    LoadTimingInfo load_timing_info;
    ConnectionAttempts connection_attempts;
    IPEndPoint remote_endpoint_after_start;
  };

  void SetUp() override {
    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
    base::RunLoop().RunUntilIdle();
    // Set an initial delay to ensure that the first call to TimeTicks::Now()
    // before incrementing the counter does not return a null value.
    FastForwardBy(base::Seconds(1));
  }

  void TearDown() override {
    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
    base::RunLoop().RunUntilIdle();
    // Empty the current queue.
    base::RunLoop().RunUntilIdle();
    PlatformTest::TearDown();
    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
    base::RunLoop().RunUntilIdle();
  }

  void Check100ResponseTiming(bool use_spdy);

  // Either |write_failure| specifies a write failure or |read_failure|
  // specifies a read failure when using a reused socket.  In either case, the
  // failure should cause the network transaction to resend the request, and the
  // other argument should be NULL.
  void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
                                            const MockRead* read_failure);

  // Either |write_failure| specifies a write failure or |read_failure|
  // specifies a read failure when using a reused socket.  In either case, the
  // failure should cause the network transaction to resend the request, and the
  // other argument should be NULL.
  void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
                                        const MockRead* read_failure,
                                        bool use_spdy,
                                        bool upload = false);

  SimpleGetHelperResult SimpleGetHelperForData(
      base::span<StaticSocketDataProvider*> providers) {
    SimpleGetHelperResult out;

    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    RecordingNetLogObserver net_log_observer;
    NetLogWithSource net_log_with_source =
        NetLogWithSource::Make(NetLogSourceType::NONE);
    session_deps_.net_log = NetLog::Get();
    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    for (auto* provider : providers) {
      session_deps_.socket_factory->AddSocketDataProvider(provider);
    }

    TestCompletionCallback callback;

    EXPECT_TRUE(net_log_with_source.IsCapturing());
    int rv = trans.Start(&request, callback.callback(), net_log_with_source);
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    out.rv = callback.WaitForResult();
    out.total_received_bytes = trans.GetTotalReceivedBytes();
    out.total_sent_bytes = trans.GetTotalSentBytes();

    // Even in the failure cases that use this function, connections are always
    // successfully established before the error.
    EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
    TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);

    if (out.rv != OK) {
      return out;
    }

    const HttpResponseInfo* response = trans.GetResponseInfo();
    // Can't use ASSERT_* inside helper functions like this, so
    // return an error.
    if (!response || !response->headers) {
      out.rv = ERR_UNEXPECTED;
      return out;
    }
    out.status_line = response->headers->GetStatusLine();

    EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
    EXPECT_EQ(80, response->remote_endpoint.port());

    bool got_endpoint =
        trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
    EXPECT_EQ(got_endpoint,
              out.remote_endpoint_after_start.address().size() > 0);

    rv = ReadTransaction(&trans, &out.response_data);
    EXPECT_THAT(rv, IsOk());

    auto entries = net_log_observer.GetEntries();
    size_t pos = ExpectLogContainsSomewhere(
        entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
        NetLogEventPhase::NONE);
    ExpectLogContainsSomewhere(
        entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
        NetLogEventPhase::NONE);

    EXPECT_EQ("GET / HTTP/1.1\r\n",
              GetStringValueFromParams(entries[pos], "line"));

    EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
              GetHeaders(entries[pos].params));

    out.total_received_bytes = trans.GetTotalReceivedBytes();
    // The total number of sent bytes should not have changed.
    EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());

    out.connection_attempts = trans.GetConnectionAttempts();
    return out;
  }

  SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
    MockWrite data_writes[] = {
        MockWrite("GET / HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    StaticSocketDataProvider reads(data_reads, data_writes);
    StaticSocketDataProvider* data[] = {&reads};
    SimpleGetHelperResult out = SimpleGetHelperForData(data);

    EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
    return out;
  }

  void AddSSLSocketData() {
    ssl_.next_proto = NextProto::kProtoHTTP2;
    ssl_.ssl_info.cert =
        ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
    ASSERT_TRUE(ssl_.ssl_info.cert);
    session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
  }

  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
                                             int expected_status);

  void ConnectStatusHelper(const MockRead& status);

  void CheckErrorIsPassedBack(int error, IoMode mode);

  base::RepeatingClosure FastForwardByCallback(base::TimeDelta delta) {
    return base::BindRepeating(&HttpNetworkTransactionTestBase::FastForwardBy,
                               base::Unretained(this), delta);
  }

  void HttpsNestedProxyNoSocketReuseHelper(const ProxyChain& chain1,
                                           const ProxyChain& chain2);

  const CommonConnectJobParams dummy_connect_job_params_;

  const NetworkAnonymizationKey kNetworkAnonymizationKey =
      NetworkAnonymizationKey::CreateCrossSite(
          SchemefulSite(GURL("https://foo.test/")));

  const NetworkIsolationKey kNetworkIsolationKey =
      NetworkIsolationKey(SchemefulSite(GURL("https://foo.test/")),
                          SchemefulSite(GURL("https://bar.test/")));

  // These clocks are defined here, even though they're only used in the
  // Reporting tests below, since they need to be destroyed after
  // |session_deps_|.
  base::SimpleTestClock clock_;
  base::SimpleTestTickClock tick_clock_;

  SpdyTestUtil spdy_util_;
  SpdySessionDependencies session_deps_;
  SSLSocketDataProvider ssl_;

  // Original socket limits.  Some tests set these.  Safest to always restore
  // them once each test has been run.
  int old_max_group_sockets_;
  int old_socket_soft_cap_;
};

class HttpNetworkTransactionTest
    : public HttpNetworkTransactionTestBase,
      public ::testing::WithParamInterface<TestParams> {
 protected:
  HttpNetworkTransactionTest() {
    std::vector<base::test::FeatureRef> enabled_features;
    std::vector<base::test::FeatureRef> disabled_features;

    if (HappyEyeballsV3Enabled()) {
      enabled_features.emplace_back(features::kHappyEyeballsV3);
    } else {
      disabled_features.emplace_back(features::kHappyEyeballsV3);
    }

    feature_list_.InitWithFeatures(enabled_features, disabled_features);
  }

  bool HappyEyeballsV3Enabled() const {
    return GetParam().happy_eyeballs_v3_enabled;
  }

  base::HistogramTester histogram_tester_;

  const ProxyServer proxy_server_1_{ProxyServer::SCHEME_HTTPS,
                                    HostPortPair("proxy1.test", 70)};
  const ProxyServer proxy_server_2_{ProxyServer::SCHEME_HTTPS,
                                    HostPortPair("proxy2.test", 71)};
  const ProxyChain nested_proxy_chain_{
      ProxyChain::ForIpProtection({{proxy_server_1_, proxy_server_2_}})};
  const ProxyChain example_proxy_server_chain_{ProxyServer{
      ProxyServer::SCHEME_HTTPS, HostPortPair("www.example.org", 443)}};

 private:
  base::test::ScopedFeatureList feature_list_;
};

INSTANTIATE_TEST_SUITE_P(All,
                         HttpNetworkTransactionTest,
                         testing::ValuesIn(GetTestParams()));

namespace {

// Fill |str| with a long header list that consumes >= |size| bytes.
void FillLargeHeadersString(std::string* str, int size) {
  const char kRow[] =
      "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
  const int sizeof_row = strlen(kRow);
  const int num_rows =
      static_cast<int>(ceil(static_cast<float>(size) / sizeof_row));
  const int sizeof_data = num_rows * sizeof_row;
  DCHECK(sizeof_data >= size);
  str->reserve(sizeof_data);

  for (int i = 0; i < num_rows; ++i) {
    str->append(kRow, sizeof_row);
  }
}

#if defined(NTLM_PORTABLE)
uint64_t MockGetMSTime() {
  // Tue, 23 May 2017 20:13:07 +0000
  return 131400439870000000;
}

// Alternative functions that eliminate randomness and dependency on the local
// host name so that the generated NTLM messages are reproducible.
void MockGenerateRandom(base::span<uint8_t> output) {
  // This is set to 0xaa because the client challenge for testing in
  // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
  std::ranges::fill(output, 0xaa);
}

std::string MockGetHostName() {
  return ntlm::test::kHostnameAscii;
}
#endif  // defined(NTLM_PORTABLE)

class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
 public:
  explicit CaptureGroupIdTransportSocketPool(
      const CommonConnectJobParams* common_connect_job_params)
      : TransportClientSocketPool(/*max_sockets=*/0,
                                  /*max_sockets_per_group=*/0,
                                  SocketPoolAdditionalCapacity::Create(),
                                  base::TimeDelta(),
                                  ProxyChain::Direct(),
                                  /*is_for_websockets=*/false,
                                  common_connect_job_params) {}

  const ClientSocketPool::GroupId& last_group_id_received() const {
    return last_group_id_;
  }

  bool socket_requested() const { return socket_requested_; }

  int RequestSocket(
      const ClientSocketPool::GroupId& group_id,
      scoped_refptr<ClientSocketPool::SocketParams> socket_params,
      const std::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
      RequestPriority priority,
      const SocketTag& socket_tag,
      ClientSocketPool::RespectLimits respect_limits,
      ClientSocketHandle* handle,
      CompletionOnceCallback callback,
      const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
      bool fail_if_alias_requires_proxy_override,
      const NetLogWithSource& net_log) override {
    last_group_id_ = group_id;
    socket_requested_ = true;
    return ERR_IO_PENDING;
  }
  void CancelRequest(const ClientSocketPool::GroupId& group_id,
                     ClientSocketHandle* handle,
                     bool cancel_connect_job) override {}
  void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
                     std::unique_ptr<StreamSocket> socket,
                     int64_t generation) override {}
  void CloseIdleSockets(const char* net_log_reason_utf8) override {}
  void CloseIdleSocketsInGroup(const ClientSocketPool::GroupId& group_id,
                               const char* net_log_reason_utf8) override {}
  size_t IdleSocketCount() const override { return 0; }
  size_t IdleSocketCountInGroup(
      const ClientSocketPool::GroupId& group_id) const override {
    return 0;
  }
  LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
                         const ClientSocketHandle* handle) const override {
    return LOAD_STATE_IDLE;
  }

 private:
  ClientSocketPool::GroupId last_group_id_;
  bool socket_requested_ = false;
};

class CaptureKeyHttpStreamPoolDelegate : public HttpStreamPool::TestDelegate {
 public:
  CaptureKeyHttpStreamPoolDelegate() = default;

  CaptureKeyHttpStreamPoolDelegate(const CaptureKeyHttpStreamPoolDelegate&) =
      delete;
  CaptureKeyHttpStreamPoolDelegate& operator=(
      const CaptureKeyHttpStreamPoolDelegate&) = delete;

  ~CaptureKeyHttpStreamPoolDelegate() override = default;

  void OnRequestStream(const HttpStreamKey& key) override { last_key_ = key; }

  std::optional<int> OnPreconnect(const HttpStreamKey& stream_key,
                                  size_t num_streams) override {
    return std::nullopt;
  }

  const HttpStreamKey& last_key() const { return last_key_; }

 private:
  HttpStreamKey last_key_;
};

//-----------------------------------------------------------------------------

// Helper functions for validating that AuthChallengeInfo's are correctly
// configured for common cases.
bool CheckBasicServerAuth(
    const std::optional<AuthChallengeInfo>& auth_challenge) {
  if (!auth_challenge) {
    return false;
  }
  EXPECT_FALSE(auth_challenge->is_proxy);
  EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
  return true;
}

bool CheckBasicSecureServerAuth(
    const std::optional<AuthChallengeInfo>& auth_challenge) {
  if (!auth_challenge) {
    return false;
  }
  EXPECT_FALSE(auth_challenge->is_proxy);
  EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
  return true;
}

bool CheckBasicProxyAuth(
    const std::optional<AuthChallengeInfo>& auth_challenge) {
  if (!auth_challenge) {
    return false;
  }
  EXPECT_TRUE(auth_challenge->is_proxy);
  EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
  return true;
}

bool CheckBasicSecureProxyAuth(
    const std::optional<AuthChallengeInfo>& auth_challenge) {
  if (!auth_challenge) {
    return false;
  }
  EXPECT_TRUE(auth_challenge->is_proxy);
  EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
  return true;
}

bool CheckDigestServerAuth(
    const std::optional<AuthChallengeInfo>& auth_challenge) {
  if (!auth_challenge) {
    return false;
  }
  EXPECT_FALSE(auth_challenge->is_proxy);
  EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
  EXPECT_EQ("digestive", auth_challenge->realm);
  EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
  return true;
}

#if defined(NTLM_PORTABLE)
bool CheckNTLMServerAuth(
    const std::optional<AuthChallengeInfo>& auth_challenge) {
  if (!auth_challenge) {
    return false;
  }
  EXPECT_FALSE(auth_challenge->is_proxy);
  EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
  EXPECT_EQ(std::string(), auth_challenge->realm);
  EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
  return true;
}

bool CheckNTLMProxyAuth(
    const std::optional<AuthChallengeInfo>& auth_challenge) {
  if (!auth_challenge) {
    return false;
  }
  EXPECT_TRUE(auth_challenge->is_proxy);
  EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
  EXPECT_EQ(std::string(), auth_challenge->realm);
  EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
  return true;
}
#endif  // defined(NTLM_PORTABLE)

}  // namespace

TEST_P(HttpNetworkTransactionTest, Basic) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
}

TEST_P(HttpNetworkTransactionTest, SimpleGET) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
  EXPECT_EQ("hello world", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, out.total_received_bytes);
  EXPECT_EQ(0u, out.connection_attempts.size());

  EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
  histogram_tester_.ExpectTotalCount(kStreamRequestSuccessHistogram, 1);
}

// Response with no status line.
TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
  MockRead data_reads[] = {
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
  EXPECT_EQ("hello world", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, out.total_received_bytes);
  histogram_tester_.ExpectTotalCount(kStreamRequestSuccessHistogram, 1);
}

// Response with no status line, and a weird port.  Should fail by default.
TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
  MockRead data_reads[] = {
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  request.method = "GET";
  request.url = GURL("http://www.example.com:2000/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
  histogram_tester_.ExpectTotalCount(kStreamRequestSuccessHistogram, 1);
}

// Tests that request info can be destroyed after the headers phase is complete.
TEST_P(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Connection: keep-alive\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, 0),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  {
    auto request = std::make_unique<HttpRequestInfo>();
    request->method = "GET";
    request->url = GURL("http://www.example.org/");
    request->traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    int rv =
        trans->Start(request.get(), callback.callback(), NetLogWithSource());

    EXPECT_THAT(callback.GetResult(rv), IsOk());
  }  // Let request info be destroyed.

  trans.reset();
}

// Test that a failure in resolving the hostname is retrievable.
TEST_P(HttpNetworkTransactionTest, SimpleGETHostResolutionFailure) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto resolver = std::make_unique<MockHostResolver>();
  resolver->rules()->AddSimulatedTimeoutFailure("www.example.org");
  session_deps_.net_log = NetLog::Get();
  session_deps_.host_resolver = std::move(resolver);
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
  histogram_tester_.ExpectTotalCount(kStreamRequestFailureHistogram, 1);
}

// This test verifies that if the transaction fails before even connecting to a
// remote endpoint, the ConnectedCallback is never called.
TEST_P(HttpNetworkTransactionTest, ConnectedCallbackNeverCalled) {
  auto resolver = std::make_unique<MockHostResolver>();
  resolver->rules()->AddSimulatedTimeoutFailure("bar.test");
  session_deps_.host_resolver = std::move(resolver);

  ConnectedHandler connected_handler;
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  auto request = DefaultRequestInfo();
  request.url = GURL("http://bar.test");

  HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
  transaction.SetConnectedCallback(connected_handler.Callback());

  TestCompletionCallback callback;
  transaction.Start(&request, callback.callback(), NetLogWithSource());
  callback.WaitForResult();

  EXPECT_THAT(connected_handler.transports(), IsEmpty());
  histogram_tester_.ExpectTotalCount(kStreamRequestFailureHistogram, 1);
}

// This test verifies that if the ConnectedCallback returns an error, the
// entire transaction fails with that error.
TEST_P(HttpNetworkTransactionTest, ConnectedCallbackFailure) {
  // The exact error code does not matter, as long as it is the same one
  // returned by the transaction overall.
  ConnectedHandler connected_handler;
  connected_handler.set_result(ERR_NOT_IMPLEMENTED);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  auto request = DefaultRequestInfo();
  HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
  transaction.SetConnectedCallback(connected_handler.Callback());

  // We never get to writing any data, but we still need a socket.
  StaticSocketDataProvider data;
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;
  EXPECT_THAT(
      transaction.Start(&request, callback.callback(), NetLogWithSource()),
      IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));

  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo()));
}

// This test verifies that if the ConnectedCallback returns an error, the
// underlying socket is not closed and can be reused by the next transaction.
TEST_P(HttpNetworkTransactionTest, ConnectedCallbackFailureAllowsSocketReuse) {
  ConnectedHandler connected_handler;
  connected_handler.set_result(ERR_NOT_IMPLEMENTED);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  auto request = DefaultRequestInfo();

  // A single socket should be opened and used for both transactions. Data
  // providers are matched to sockets at most once.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("X-Test-Header: foo\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  {
    HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
    transaction.SetConnectedCallback(connected_handler.Callback());

    TestCompletionCallback callback;
    EXPECT_THAT(
        transaction.Start(&request, callback.callback(), NetLogWithSource()),
        IsError(ERR_IO_PENDING));
    EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
  }

  // The data provider should still be linked to a socket.
  EXPECT_TRUE(data.socket());
  auto* socket = data.socket();

  {
    HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());

    TestCompletionCallback callback;
    EXPECT_THAT(
        transaction.Start(&request, callback.callback(), NetLogWithSource()),
        IsError(ERR_IO_PENDING));
    EXPECT_THAT(callback.WaitForResult(), IsOk());

    EXPECT_TRUE(transaction.GetResponseInfo()->headers->HasHeaderValue(
        "X-Test-Header", "foo"));

    // Still linked to the same socket.
    EXPECT_EQ(data.socket(), socket);
  }
}

// This test verifies that the ConnectedCallback is called once in the case of
// simple requests.
TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledOnce) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  ConnectedHandler connected_handler;
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  auto request = DefaultRequestInfo();
  HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
  transaction.SetConnectedCallback(connected_handler.Callback());

  TestCompletionCallback callback;
  EXPECT_THAT(
      transaction.Start(&request, callback.callback(), NetLogWithSource()),
      IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo()));
}

// This test verifies that the ConnectedCallback is called once more per
// authentication challenge.
TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachAuthChallenge) {
  ConnectedHandler connected_handler;
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  auto request = DefaultRequestInfo();
  HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
  transaction.SetConnectedCallback(connected_handler.Callback());

  // First request receives an auth challenge.
  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };
  StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // Second request is allowed through.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  // First request, connects once.
  TestCompletionCallback callback1;
  EXPECT_THAT(
      transaction.Start(&request, callback1.callback(), NetLogWithSource()),
      IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback1.WaitForResult(), IsOk());

  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo()));

  // Second request, connects again.
  TestCompletionCallback callback2;
  EXPECT_THAT(transaction.RestartWithAuth(AuthCredentials(kFoo, kBar),
                                          callback2.callback()),
              IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback2.WaitForResult(), IsOk());

  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo(),
                          EmbeddedHttpServerTransportInfo()));
}

// This test verifies that the ConnectedCallback is called once more per retry.
TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachRetry) {
  ConnectedHandler connected_handler;
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  auto request = DefaultRequestInfo();
  HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
  transaction.SetConnectedCallback(connected_handler.Callback());

  // First request receives a retryable error.
  MockRead data_reads1[] = {
      MockRead(SYNCHRONOUS, ERR_HTTP2_SERVER_REFUSED_STREAM),
  };
  StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // Second request is allowed through.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback1;
  EXPECT_THAT(
      transaction.Start(&request, callback1.callback(), NetLogWithSource()),
      IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback1.WaitForResult(), IsOk());

  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo(),
                          EmbeddedHttpServerTransportInfo()));
}

TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledAsync) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  ConnectedHandler connected_handler;
  connected_handler.set_run_callback(true);
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  auto request = DefaultRequestInfo();
  HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
  transaction.SetConnectedCallback(connected_handler.Callback());

  TestCompletionCallback callback;
  EXPECT_THAT(
      transaction.Start(&request, callback.callback(), NetLogWithSource()),
      IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo()));
}

TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledAsyncError) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  ConnectedHandler connected_handler;
  connected_handler.set_run_callback(true);
  connected_handler.set_result(ERR_FAILED);
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  auto request = DefaultRequestInfo();
  HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
  transaction.SetConnectedCallback(connected_handler.Callback());

  TestCompletionCallback callback;
  EXPECT_THAT(
      transaction.Start(&request, callback.callback(), NetLogWithSource()),
      IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));

  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo()));
}

// Test the case that the HttpNetworkTransaction is destroyed while requesting a
// stream, it will log to the failure histogram.
TEST_P(HttpNetworkTransactionTest, DeleteDuringStreamRequest) {
  session_deps_.host_resolver = std::make_unique<MockHostResolver>();
  session_deps_.host_resolver->set_ondemand_mode(true);
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  auto request = DefaultRequestInfo();
  auto transaction =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;
  EXPECT_THAT(
      transaction->Start(&request, callback.callback(), NetLogWithSource()),
      IsError(ERR_IO_PENDING));
  base::RunLoop().RunUntilIdle();
  histogram_tester_.ExpectTotalCount(kStreamRequestFailureHistogram, 0);

  transaction.reset();
  histogram_tester_.ExpectTotalCount(kStreamRequestFailureHistogram, 1);
}

// Allow up to 4 bytes of junk to precede status line.
TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
  MockRead data_reads[] = {
      MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
  EXPECT_EQ("DATA", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, out.total_received_bytes);
}

// Allow up to 4 bytes of junk to precede status line.
TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
  MockRead data_reads[] = {
      MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
  EXPECT_EQ("DATA", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, out.total_received_bytes);
}

// Beyond 4 bytes of slop and it should fail to find a status line.
TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
  MockRead data_reads[] = {
      MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
  EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, out.total_received_bytes);
}

// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
  MockRead data_reads[] = {
      MockRead("\n"),
      MockRead("\n"),
      MockRead("Q"),
      MockRead("J"),
      MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
  EXPECT_EQ("DATA", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, out.total_received_bytes);
}

// Close the connection before enough bytes to have a status line.
TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
  MockRead data_reads[] = {
      MockRead("HTT"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
  EXPECT_EQ("HTT", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, out.total_received_bytes);
}

// Simulate a 204 response, lacking a Content-Length header, sent over a
// persistent connection.  The response should still terminate since a 204
// cannot have a response body.
TEST_P(HttpNetworkTransactionTest, StopsReading204) {
  char junk[] = "junk";
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
      MockRead(junk),  // Should not be read!!
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
  EXPECT_EQ("", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  int64_t response_size = reads_size - strlen(junk);
  EXPECT_EQ(response_size, out.total_received_bytes);
}

// A simple request using chunked encoding with some extra data after.
TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
  std::string final_chunk = "0\r\n\r\n";
  std::string extra_data = "HTTP/1.1 200 OK\r\n";
  std::string last_read = final_chunk + extra_data;
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
      MockRead("5\r\nHello\r\n"),
      MockRead("1\r\n"),
      MockRead(" \r\n"),
      MockRead("5\r\nworld\r\n"),
      MockRead(last_read),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
  EXPECT_EQ("Hello world", out.response_data);
  int64_t reads_size = CountReadBytes(data_reads);
  int64_t response_size = reads_size - extra_data.size();
  EXPECT_EQ(response_size, out.total_received_bytes);
}

// Next tests deal with http://crbug.com/56344.

TEST_P(HttpNetworkTransactionTest,
       MultipleContentLengthHeadersNoTransferEncoding) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 10\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
}

TEST_P(HttpNetworkTransactionTest,
       DuplicateContentLengthHeadersNoTransferEncoding) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 5\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead("Hello"),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
  EXPECT_EQ("Hello", out.response_data);
}

TEST_P(HttpNetworkTransactionTest,
       ComplexContentLengthHeadersNoTransferEncoding) {
  // More than 2 dupes.
  {
    MockRead data_reads[] = {
        MockRead("HTTP/1.1 200 OK\r\n"),
        MockRead("Content-Length: 5\r\n"),
        MockRead("Content-Length: 5\r\n"),
        MockRead("Content-Length: 5\r\n\r\n"),
        MockRead("Hello"),
    };
    SimpleGetHelperResult out = SimpleGetHelper(data_reads);
    EXPECT_THAT(out.rv, IsOk());
    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
    EXPECT_EQ("Hello", out.response_data);
  }
  // HTTP/1.0
  {
    MockRead data_reads[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("Content-Length: 5\r\n"),
        MockRead("Content-Length: 5\r\n"),
        MockRead("Content-Length: 5\r\n\r\n"),
        MockRead("Hello"),
    };
    SimpleGetHelperResult out = SimpleGetHelper(data_reads);
    EXPECT_THAT(out.rv, IsOk());
    EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
    EXPECT_EQ("Hello", out.response_data);
  }
  // 2 dupes and one mismatched.
  {
    MockRead data_reads[] = {
        MockRead("HTTP/1.1 200 OK\r\n"),
        MockRead("Content-Length: 10\r\n"),
        MockRead("Content-Length: 10\r\n"),
        MockRead("Content-Length: 5\r\n\r\n"),
    };
    SimpleGetHelperResult out = SimpleGetHelper(data_reads);
    EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
  }
}

TEST_P(HttpNetworkTransactionTest,
       MultipleContentLengthHeadersTransferEncoding) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 666\r\n"),
      MockRead("Content-Length: 1337\r\n"),
      MockRead("Transfer-Encoding: chunked\r\n\r\n"),
      MockRead("5\r\nHello\r\n"),
      MockRead("1\r\n"),
      MockRead(" \r\n"),
      MockRead("5\r\nworld\r\n"),
      MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
  EXPECT_EQ("Hello world", out.response_data);
}

// Next tests deal with http://crbug.com/98895.

// Checks that a single Content-Disposition header results in no error.
TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(
          "Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead("Hello"),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
  EXPECT_EQ("Hello", out.response_data);
}

// Checks that two identical Content-Disposition headers result in no error.
TEST_P(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
      MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead("Hello"),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsOk());
  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
  EXPECT_EQ("Hello", out.response_data);
}

// Checks that two distinct Content-Disposition headers result in an error.
TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
      MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead("Hello"),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv,
              IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
}

// Checks that two identical Location headers result in no error.
// Also tests Location header behavior.
TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 302 Redirect\r\n"),
      MockRead("Location: http://good.com/\r\n"),
      MockRead("Location: http://good.com/\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://redirect.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
  std::string url;
  EXPECT_TRUE(response->headers->IsRedirect(&url));
  EXPECT_EQ("http://good.com/", url);
  EXPECT_TRUE(response->proxy_chain.is_direct());
}

// Checks that two distinct Location headers result in an error.
TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 302 Redirect\r\n"),
      MockRead("Location: http://good.com/\r\n"),
      MockRead("Location: http://evil.com/\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
}

// Do a request using the HEAD method. Verify that we don't try to read the
// message body (since HEAD has none).
TEST_P(HttpNetworkTransactionTest, Head) {
  HttpRequestInfo request;
  request.method = "HEAD";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  ConnectedHandler connected_handler;
  trans.SetConnectedCallback(connected_handler.Callback());

  MockWrite data_writes1[] = {
      MockWrite("HEAD / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 404 Not Found\r\n"),
      MockRead("Server: Blah\r\n"),
      MockRead("Content-Length: 1234\r\n\r\n"),

      // No response body because the test stops reading here.
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  // Check that the headers got parsed.
  EXPECT_TRUE(response->headers);
  EXPECT_EQ(1234, response->headers->GetContentLength()->InBytes());
  EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
  EXPECT_TRUE(response->proxy_chain.is_direct());
  EXPECT_THAT(connected_handler.transports(),
              ElementsAre(EmbeddedHttpServerTransportInfo()));

  std::string server_header;
  size_t iter = 0;
  bool has_server_header =
      response->headers->EnumerateHeader(&iter, "Server", &server_header);
  EXPECT_TRUE(has_server_header);
  EXPECT_EQ("Blah", server_header);

  // Reading should give EOF right away, since there is no message body
  // (despite non-zero content-length).
  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("", response_data);
}

TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("hello"),
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  const char* const kExpectedResponseData[] = {"hello", "world"};

  for (const auto* expected_response_data : kExpectedResponseData) {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    TestCompletionCallback callback;

    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);

    EXPECT_TRUE(response->headers);
    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
    EXPECT_TRUE(response->proxy_chain.is_direct());

    std::string response_data;
    rv = ReadTransaction(&trans, &response_data);
    EXPECT_THAT(rv, IsOk());
    EXPECT_EQ(expected_response_data, response_data);

    LoadTimingInternalInfo load_timing_internal;
    trans.PopulateLoadTimingInternalInfo(&load_timing_internal);
    EXPECT_EQ(load_timing_internal.session_source, std::nullopt);
  }
}

TEST_P(HttpNetworkTransactionTest, Ignores100) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Check the upload progress returned before initialization is correct.
  UploadProgress progress = request.upload_data_stream->GetUploadProgress();
  EXPECT_EQ(0u, progress.size());
  EXPECT_EQ(0u, progress.position());

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

// This test is almost the same as Ignores100 above, but the response contains
// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
// HTTP/1.1 and the two status headers are read in one read.
TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
               "HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

TEST_P(HttpNetworkTransactionTest, GetReceivedBodyBytes) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::vector<MockWrite> data_writes = {
      MockWrite(ASYNC, 0,
                "GET / HTTP/1.1\r\n"
                "Host: www.example.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  static constexpr char chunk1[] = "hello ";
  static constexpr char chunk2[] = "world";

  MockRead data_reads[] = {
      MockRead(ASYNC, 1, "HTTP/1.0 200 OK\r\n\r\n"),
      MockRead(ASYNC, 2, chunk1),
      MockRead(ASYNC, 3, chunk2),
      MockRead(ASYNC, OK, 4),
  };
  SequencedSocketData data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback start_cb;
  EXPECT_THAT(start_cb.GetResult(trans.Start(&request, start_cb.callback(),
                                             NetLogWithSource())),
              IsOk());

  const size_t kBufferSize = 256;

  auto buf = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
  EXPECT_THAT(trans.GetReceivedBodyBytes(), 0);

  TestCompletionCallback read_cb1;
  EXPECT_THAT(read_cb1.GetResult(
                  trans.Read(buf.get(), kBufferSize, read_cb1.callback())),
              strlen(chunk1));

  EXPECT_THAT(trans.GetReceivedBodyBytes(), strlen(chunk1));

  TestCompletionCallback read_cb2;
  EXPECT_THAT(read_cb2.GetResult(
                  trans.Read(buf.get(), kBufferSize, read_cb2.callback())),
              strlen(chunk2));

  EXPECT_THAT(trans.GetReceivedBodyBytes(), strlen(chunk1) + strlen(chunk2));

  TestCompletionCallback read_cb3;
  EXPECT_THAT(read_cb3.GetResult(
                  trans.Read(buf.get(), kBufferSize, read_cb3.callback())),
              IsOk());
  EXPECT_THAT(trans.GetReceivedBodyBytes(), strlen(chunk1) + strlen(chunk2));
}

TEST_P(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
  static const base::TimeDelta kDelayAfterFirstByte = base::Milliseconds(10);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::vector<MockWrite> data_writes = {
      MockWrite(ASYNC, 0,
                "GET / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  std::vector<MockRead> data_reads = {
      // Write one byte of the status line, followed by a pause.
      MockRead(ASYNC, 1, "H"),
      MockRead(ASYNC, ERR_IO_PENDING, 2),
      MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
      MockRead(ASYNC, 4, "hello world"),
      MockRead(SYNCHRONOUS, OK, 5),
  };

  SequencedSocketData data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  data.RunUntilPaused();
  ASSERT_TRUE(data.IsPaused());
  FastForwardBy(kDelayAfterFirstByte);
  data.Resume();

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
  EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
  // Ensure we didn't include the delay in the TTFB time.
  EXPECT_EQ(load_timing_info.receive_headers_start,
            load_timing_info.connect_timing.connect_end);
  // Ensure that the mock clock advanced at all.
  EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
            kDelayAfterFirstByte);

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

// Tests that the time-to-first-byte reported in a transaction's load timing
// info uses the first response, even if 1XX/informational.
void HttpNetworkTransactionTestBase::Check100ResponseTiming(bool use_spdy) {
  static const base::TimeDelta kDelayAfter100Response = base::Milliseconds(10);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::vector<MockWrite> data_writes;
  std::vector<MockRead> data_reads;

  spdy::SpdySerializedFrame spdy_req(
      spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));

  quiche::HttpHeaderBlock spdy_resp1_headers;
  spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
  spdy::SpdySerializedFrame spdy_resp1(
      spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
  spdy::SpdySerializedFrame spdy_resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame spdy_data(
      spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));

  if (use_spdy) {
    ssl.next_proto = NextProto::kProtoHTTP2;

    data_writes = {CreateMockWrite(spdy_req, 0)};

    data_reads = {
        CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
        CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
        MockRead(SYNCHRONOUS, OK, 5),
    };
  } else {
    data_writes = {
        MockWrite(ASYNC, 0,
                  "GET / HTTP/1.1\r\n"
                  "Host: www.foo.com\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    data_reads = {
        MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
        MockRead(ASYNC, ERR_IO_PENDING, 2),

        MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
        MockRead(ASYNC, 4, "hello world"),
        MockRead(SYNCHRONOUS, OK, 5),
    };
  }

  SequencedSocketData data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  data.RunUntilPaused();
  // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
  // the delay before parsing the 200 response.
  ASSERT_TRUE(data.IsPaused());
  FastForwardBy(kDelayAfter100Response);
  data.Resume();

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
  EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
  // Ensure we didn't include the delay in the TTFB time.
  EXPECT_EQ(load_timing_info.receive_headers_start,
            load_timing_info.connect_timing.connect_end);
  // Ensure that the mock clock advanced at all.
  EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
            kDelayAfter100Response);

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

TEST_P(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
  Check100ResponseTiming(false /* use_spdy */);
}

TEST_P(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
  Check100ResponseTiming(true /* use_spdy */);
}

TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
      MockRead(ASYNC, 0),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("", response_data);
}

TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead(ASYNC, 0),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
}

void HttpNetworkTransactionTestBase::KeepAliveConnectionResendRequestTest(
    const MockWrite* write_failure,
    const MockRead* read_failure) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Written data for successfully sending both requests.
  auto data1_writes =
      std::to_array<MockWrite>({MockWrite("GET / HTTP/1.1\r\n"
                                          "Host: www.foo.com\r\n"
                                          "Connection: keep-alive\r\n\r\n"),
                                MockWrite("GET / HTTP/1.1\r\n"
                                          "Host: www.foo.com\r\n"
                                          "Connection: keep-alive\r\n\r\n")});

  // Read results for the first request.
  auto data1_reads = std::to_array<MockRead>({
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("hello"),
      MockRead(ASYNC, OK),
  });

  if (write_failure) {
    ASSERT_FALSE(read_failure);
    data1_writes[1] = *write_failure;
  } else {
    ASSERT_TRUE(read_failure);
    data1_reads[2] = *read_failure;
  }

  StaticSocketDataProvider data1(data1_reads, data1_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  MockRead data2_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  const auto kExpectedResponseData =
      std::to_array<const char*>({"hello", "world"});

  uint32_t first_socket_log_id = NetLogSource::kInvalidId;
  for (int i = 0; i < 2; ++i) {
    TestCompletionCallback callback;

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    LoadTimingInfo load_timing_info;
    EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
    TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
    if (i == 0) {
      first_socket_log_id = load_timing_info.socket_log_id;
    } else {
      // The second request should be using a new socket.
      EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
    }

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);

    EXPECT_TRUE(response->headers);
    EXPECT_TRUE(response->proxy_chain.is_direct());
    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

    std::string response_data;
    rv = ReadTransaction(&trans, &response_data);
    EXPECT_THAT(rv, IsOk());
    EXPECT_EQ(kExpectedResponseData[i], response_data);
  }
}

void HttpNetworkTransactionTestBase::PreconnectErrorResendRequestTest(
    const MockWrite* write_failure,
    const MockRead* read_failure,
    bool use_spdy,
    bool chunked_upload) {
  SpdyTestUtil spdy_util(/*use_priority_header=*/true);
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ChunkedUploadDataStream upload_data_stream(0);
  if (chunked_upload) {
    request.method = "POST";
    upload_data_stream.AppendData(base::byte_span_from_cstring("foobar"), true);
    request.upload_data_stream = &upload_data_stream;
  }

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  SSLSocketDataProvider ssl1(ASYNC, OK);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  if (use_spdy) {
    ssl1.next_proto = NextProto::kProtoHTTP2;
    ssl2.next_proto = NextProto::kProtoHTTP2;
  }
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  // SPDY versions of the request and response.

  quiche::HttpHeaderBlock spdy_post_header_block;
  spdy_post_header_block[spdy::kHttp2MethodHeader] = "POST";
  spdy_util.AddUrlToHeaderBlock(request.url.spec(), &spdy_post_header_block);
  spdy::SpdySerializedFrame spdy_request(
      chunked_upload
          ? spdy_util.ConstructSpdyHeaders(1, std::move(spdy_post_header_block),
                                           DEFAULT_PRIORITY, false)
          : spdy_util.ConstructSpdyGet(request.url.spec().c_str(), 1,
                                       DEFAULT_PRIORITY));

  spdy::SpdySerializedFrame spdy_request_body(
      spdy_util.ConstructSpdyDataFrame(1, "foobar", true));
  spdy::SpdySerializedFrame spdy_response(
      spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame spdy_data(
      spdy_util.ConstructSpdyDataFrame(1, "hello", true));

  // HTTP/1.1 versions of the request and response.
  const std::string http_request =
      std::string(chunked_upload ? "POST" : "GET") +
      " / HTTP/1.1\r\n"
      "Host: www.foo.com\r\n"
      "Connection: keep-alive\r\n" +
      (chunked_upload ? "Transfer-Encoding: chunked\r\n\r\n" : "\r\n");
  const std::string_view kHttpRequest(http_request);
  const std::string_view kHttpResponse =
      "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
  const std::string_view kHttpData = "hello";

  std::vector<MockRead> data1_reads;
  std::vector<MockWrite> data1_writes;
  if (write_failure) {
    ASSERT_FALSE(read_failure);
    data1_writes.push_back(*write_failure);
    data1_reads.emplace_back(ASYNC, OK);
  } else {
    ASSERT_TRUE(read_failure);
    if (use_spdy) {
      data1_writes.push_back(CreateMockWrite(spdy_request));
      if (chunked_upload) {
        data1_writes.push_back(CreateMockWrite(spdy_request_body));
      }
    } else {
      data1_writes.emplace_back(kHttpRequest);
      if (chunked_upload) {
        data1_writes.emplace_back("6\r\nfoobar\r\n");
        data1_writes.emplace_back("0\r\n\r\n");
      }
    }
    data1_reads.push_back(*read_failure);
  }

  StaticSocketDataProvider data1(data1_reads, data1_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  std::vector<MockRead> data2_reads;
  std::vector<MockWrite> data2_writes;

  if (use_spdy) {
    int seq = 0;
    data2_writes.push_back(CreateMockWrite(spdy_request, seq++, ASYNC));
    if (chunked_upload) {
      data2_writes.push_back(CreateMockWrite(spdy_request_body, seq++, ASYNC));
    }
    data2_reads.push_back(CreateMockRead(spdy_response, seq++, ASYNC));
    data2_reads.push_back(CreateMockRead(spdy_data, seq++, ASYNC));
    data2_reads.emplace_back(ASYNC, OK, seq++);
  } else {
    int seq = 0;
    data2_writes.emplace_back(ASYNC, kHttpRequest, seq++);
    if (chunked_upload) {
      data2_writes.emplace_back(ASYNC, seq++, "6\r\nfoobar\r\n");
      data2_writes.emplace_back(ASYNC, seq++, "0\r\n\r\n");
    }
    data2_reads.emplace_back(ASYNC, seq++, kHttpResponse);
    data2_reads.emplace_back(ASYNC, seq++, kHttpData);
    data2_reads.emplace_back(ASYNC, OK, seq++);
  }
  SequencedSocketData data2(data2_reads, data2_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  // Preconnect a socket.
  session->http_stream_factory()->PreconnectStreams(1, request,
                                                    base::OnceClosure());
  // Wait for the preconnect to complete.
  // TODO(davidben): Some way to wait for an idle socket count might be handy.
  base::RunLoop().RunUntilIdle();
  if (use_spdy && base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    // When the HappyEyeballsV3 feature is enabled, we immediately create a SPDY
    // session, but it becomes unavailable after getting an error.
    EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
    SpdySessionKey spdy_sesion_key(
        HostPortPair::FromURL(request.url), PRIVACY_MODE_DISABLED,
        ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(),
        NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
        /*disable_cert_verification_network_fetches=*/false);
    EXPECT_FALSE(HasSpdySession(session->spdy_session_pool(), spdy_sesion_key));
  } else {
    EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
  }

  // Make the request.
  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES |
                                                CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  if (response->was_fetched_via_spdy) {
    EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  } else {
    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  }

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ(kHttpData, response_data);
}

// Test that we do not retry indefinitely when a server sends an error like
// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
TEST_P(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Check whether we give up after the third try.

  // Construct an HTTP2 request and a "Go away" response.
  spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
      request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
  spdy::SpdySerializedFrame spdy_response_go_away(
      spdy_util_.ConstructSpdyGoAway(0));
  MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
  MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};

  // Three go away responses.
  StaticSocketDataProvider data1(data_read1, data_write);
  StaticSocketDataProvider data2(data_read1, data_write);
  StaticSocketDataProvider data3(data_read1, data_write);

  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  AddSSLSocketData();
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  AddSSLSocketData();
  session_deps_.socket_factory->AddSocketDataProvider(&data3);
  AddSSLSocketData();

  TestCompletionCallback callback;
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
}

TEST_P(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Check whether we try atleast thrice before giving up.

  // Construct an HTTP2 request and a "Go away" response.
  spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
      request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
  spdy::SpdySerializedFrame spdy_response_go_away(
      spdy_util_.ConstructSpdyGoAway(0));
  MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
  MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};

  // Construct a non error HTTP2 response.
  spdy::SpdySerializedFrame spdy_response_no_error(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));
  spdy::SpdySerializedFrame spdy_data(
      spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
                           CreateMockRead(spdy_data, 2)};

  // Two error responses.
  StaticSocketDataProvider data1(data_read1, data_write);
  StaticSocketDataProvider data2(data_read1, data_write);
  // Followed by a success response.
  SequencedSocketData data3(data_read2, data_write);

  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  AddSSLSocketData();
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  AddSSLSocketData();
  session_deps_.socket_factory->AddSocketDataProvider(&data3);
  AddSSLSocketData();

  TestCompletionCallback callback;
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
  KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
}

TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
  KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
}

TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
  KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
}

// Make sure that on a 408 response (Request Timeout), the request is retried,
// if the socket was a reused keep alive socket.
TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
  MockRead read_failure(SYNCHRONOUS,
                        "HTTP/1.1 408 Request Timeout\r\n"
                        "Connection: Keep-Alive\r\n"
                        "Content-Length: 6\r\n\r\n"
                        "Pickle");
  KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
}

TEST_P(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
  PreconnectErrorResendRequestTest(&write_failure, nullptr,
                                   false /* use_spdy */);
  PreconnectErrorResendRequestTest(
      &write_failure, nullptr, false /* use_spdy */, true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
  PreconnectErrorResendRequestTest(nullptr, &read_failure,
                                   false /* use_spdy */);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
                                   true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
  PreconnectErrorResendRequestTest(nullptr, &read_failure,
                                   false /* use_spdy */);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
                                   true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
  MockRead read_failure(ASYNC, OK);  // EOF
  PreconnectErrorResendRequestTest(nullptr, &read_failure,
                                   false /* use_spdy */);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
                                   true /* chunked_upload */);
}

// Make sure that on a 408 response (Request Timeout), the request is retried,
// if the socket was a preconnected (UNUSED_IDLE) socket.
TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
  MockRead read_failure(SYNCHRONOUS,
                        "HTTP/1.1 408 Request Timeout\r\n"
                        "Connection: Keep-Alive\r\n"
                        "Content-Length: 6\r\n\r\n"
                        "Pickle");
  KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
  PreconnectErrorResendRequestTest(nullptr, &read_failure,
                                   false /* use_spdy */);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
                                   true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
  PreconnectErrorResendRequestTest(&write_failure, nullptr,
                                   true /* use_spdy */);
  PreconnectErrorResendRequestTest(&write_failure, nullptr, true /* use_spdy */,
                                   true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
                                   true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
  PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
                                   true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
  MockRead read_failure(ASYNC, OK);  // EOF
  PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
  PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
                                   true /* chunked_upload */);
}

TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead(ASYNC, ERR_CONNECTION_RESET),
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));

  IPEndPoint endpoint;
  EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
  EXPECT_LT(0u, endpoint.address().size());
}

// What do various browsers do when the server closes a non-keepalive
// connection without sending any response header or body?
//
// IE7: error page
// Safari 3.1.2 (Windows): error page
// Firefox 3.0.1: blank page
// Opera 9.52: after five attempts, blank page
// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
// Us: error page (EMPTY_RESPONSE)
TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
  MockRead data_reads[] = {
      MockRead(SYNCHRONOUS, OK),            // EOF
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  SimpleGetHelperResult out = SimpleGetHelper(data_reads);
  EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
}

// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
// tests. There was a bug causing HttpNetworkTransaction to hang in the
// destructor in such situations.
// See http://crbug.com/154712 and http://crbug.com/156609.
TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Connection: keep-alive\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead("hello"),
      MockRead(SYNCHRONOUS, 0),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  scoped_refptr<IOBufferWithSize> io_buf =
      base::MakeRefCounted<IOBufferWithSize>(100);
  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_EQ(5, rv);
  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
  EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));

  trans.reset();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}

TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Connection: keep-alive\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, 0),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  scoped_refptr<IOBufferWithSize> io_buf(
      base::MakeRefCounted<IOBufferWithSize>(100));
  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));

  trans.reset();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Test that we correctly reuse a keep-alive connection after not explicitly
// reading the body.
TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  const std::string_view kRequestData =
      "GET / HTTP/1.1\r\n"
      "Host: www.foo.com\r\n"
      "Connection: keep-alive\r\n\r\n";
  MockWrite data_writes[] = {
      MockWrite(ASYNC, 0, kRequestData),  MockWrite(ASYNC, 2, kRequestData),
      MockWrite(ASYNC, 4, kRequestData),  MockWrite(ASYNC, 6, kRequestData),
      MockWrite(ASYNC, 8, kRequestData),  MockWrite(ASYNC, 10, kRequestData),
      MockWrite(ASYNC, 12, kRequestData), MockWrite(ASYNC, 14, kRequestData),
      MockWrite(ASYNC, 17, kRequestData), MockWrite(ASYNC, 20, kRequestData),
  };

  // Note that because all these reads happen in the same
  // StaticSocketDataProvider, it shows that the same socket is being reused for
  // all transactions.
  MockRead data_reads[] = {
      MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
      MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
      MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
      MockRead(ASYNC, 7,
               "HTTP/1.1 302 Found\r\n"
               "Content-Length: 0\r\n\r\n"),
      MockRead(ASYNC, 9,
               "HTTP/1.1 302 Found\r\n"
               "Content-Length: 5\r\n\r\n"
               "hello"),
      MockRead(ASYNC, 11,
               "HTTP/1.1 301 Moved Permanently\r\n"
               "Content-Length: 0\r\n\r\n"),
      MockRead(ASYNC, 13,
               "HTTP/1.1 301 Moved Permanently\r\n"
               "Content-Length: 5\r\n\r\n"
               "hello"),

      // In the next two rounds, IsConnectedAndIdle returns false, due to
      // the set_busy_before_sync_reads(true) call, while the
      // HttpNetworkTransaction is being shut down, but the socket is still
      // reuseable.  See http://crbug.com/544255.
      MockRead(ASYNC, 15,
               "HTTP/1.1 200 Hunky-Dory\r\n"
               "Content-Length: 5\r\n\r\n"),
      MockRead(SYNCHRONOUS, 16, "hello"),

      MockRead(ASYNC, 18,
               "HTTP/1.1 200 Hunky-Dory\r\n"
               "Content-Length: 5\r\n\r\n"
               "he"),
      MockRead(SYNCHRONOUS, 19, "llo"),

      // The body of the final request is actually read.
      MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead(ASYNC, 22, "hello"),
  };
  SequencedSocketData data(data_reads, data_writes);
  data.set_busy_before_sync_reads(true);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  const int kNumUnreadBodies = std::size(data_writes) - 1;
  std::array<std::string, kNumUnreadBodies> response_lines;

  uint32_t first_socket_log_id = NetLogSource::kInvalidId;
  for (size_t i = 0; i < kNumUnreadBodies; ++i) {
    TestCompletionCallback callback;

    auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
                                                          session.get());

    int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(callback.GetResult(rv), IsOk());

    LoadTimingInfo load_timing_info;
    EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
    if (i == 0) {
      TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
      first_socket_log_id = load_timing_info.socket_log_id;
    } else {
      TestLoadTimingReused(load_timing_info);
      EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
    }

    const HttpResponseInfo* response = trans->GetResponseInfo();
    ASSERT_TRUE(response);

    ASSERT_TRUE(response->headers);
    response_lines[i] = response->headers->GetStatusLine();

    // Delete the transaction without reading the response bodies.  Then spin
    // the message loop, so the response bodies are drained.
    trans.reset();
    base::RunLoop().RunUntilIdle();
  }

  const auto kStatusLines = std::to_array<const char*>({
      "HTTP/1.1 204 No Content",
      "HTTP/1.1 205 Reset Content",
      "HTTP/1.1 304 Not Modified",
      "HTTP/1.1 302 Found",
      "HTTP/1.1 302 Found",
      "HTTP/1.1 301 Moved Permanently",
      "HTTP/1.1 301 Moved Permanently",
      "HTTP/1.1 200 Hunky-Dory",
      "HTTP/1.1 200 Hunky-Dory",
  });

  static_assert(kNumUnreadBodies == std::size(kStatusLines),
                "forgot to update kStatusLines");

  for (int i = 0; i < kNumUnreadBodies; ++i) {
    EXPECT_EQ(kStatusLines[i], response_lines[i]);
  }

  TestCompletionCallback callback;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello", response_data);
}

// Sockets that receive extra data after a response is complete should not be
// reused.
TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  MockWrite data_writes1[] = {
      MockWrite("HEAD / HTTP/1.1\r\n"
                "Host: www.borked.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 22\r\n\r\n"
               "This server is borked."),
  };

  MockWrite data_writes2[] = {
      MockWrite("GET /foo HTTP/1.1\r\n"
                "Host: www.borked.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Length: 3\r\n\r\n"
               "foo"),
  };
  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "HEAD";
  request1.url = GURL("http://www.borked.com/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ(200, response1->headers->response_code());
  EXPECT_TRUE(response1->headers->IsKeepAlive());

  std::string response_data1;
  EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
  EXPECT_EQ("", response_data1);
  // Deleting the transaction attempts to release the socket back into the
  // socket pool.
  trans1.reset();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("http://www.borked.com/foo");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
  ASSERT_TRUE(response2);
  ASSERT_TRUE(response2->headers);
  EXPECT_EQ(200, response2->headers->response_code());

  std::string response_data2;
  EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
  EXPECT_EQ("foo", response_data2);
}

TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.borked.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 22\r\n\r\n"
               "This server is borked."
               "Bonus data!"),
  };

  MockWrite data_writes2[] = {
      MockWrite("GET /foo HTTP/1.1\r\n"
                "Host: www.borked.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Length: 3\r\n\r\n"
               "foo"),
  };
  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("http://www.borked.com/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ(200, response1->headers->response_code());
  EXPECT_TRUE(response1->headers->IsKeepAlive());

  std::string response_data1;
  EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
  EXPECT_EQ("This server is borked.", response_data1);
  // Deleting the transaction attempts to release the socket back into the
  // socket pool.
  trans1.reset();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("http://www.borked.com/foo");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
  ASSERT_TRUE(response2);
  ASSERT_TRUE(response2->headers);
  EXPECT_EQ(200, response2->headers->response_code());

  std::string response_data2;
  EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
  EXPECT_EQ("foo", response_data2);
}

TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.borked.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Transfer-Encoding: chunked\r\n\r\n"),
      MockRead("16\r\nThis server is borked.\r\n"),
      MockRead("0\r\n\r\nBonus data!"),
  };

  MockWrite data_writes2[] = {
      MockWrite("GET /foo HTTP/1.1\r\n"
                "Host: www.borked.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Length: 3\r\n\r\n"
               "foo"),
  };
  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("http://www.borked.com/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ(200, response1->headers->response_code());
  EXPECT_TRUE(response1->headers->IsKeepAlive());

  std::string response_data1;
  EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
  EXPECT_EQ("This server is borked.", response_data1);
  // Deleting the transaction attempts to release the socket back into the
  // socket pool.
  trans1.reset();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("http://www.borked.com/foo");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
  ASSERT_TRUE(response2);
  ASSERT_TRUE(response2->headers);
  EXPECT_EQ(200, response2->headers->response_code());

  std::string response_data2;
  EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
  EXPECT_EQ("foo", response_data2);
}

// This is a little different from the others - it tests the case that the
// HttpStreamParser doesn't know if there's extra data on a socket or not when
// the HttpNetworkTransaction is torn down, because the response body hasn't
// been read from yet, but the request goes through the HttpResponseBodyDrainer.
TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.borked.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Transfer-Encoding: chunked\r\n\r\n"),
      MockRead("16\r\nThis server is borked.\r\n"),
      MockRead("0\r\n\r\nBonus data!"),
  };
  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("http://www.borked.com/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response1 = trans->GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ(200, response1->headers->response_code());
  EXPECT_TRUE(response1->headers->IsKeepAlive());

  // Deleting the transaction creates an HttpResponseBodyDrainer to read the
  // response body.
  trans.reset();

  // Let the HttpResponseBodyDrainer drain the socket.  It should determine the
  // socket can't be reused, rather than returning it to the socket pool.
  base::RunLoop().RunUntilIdle();

  // There should be no idle sockets in the pool.
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Test the request-challenge-retry sequence for basic auth.
// (basic auth is the easiest to mock, because it has no randomness).
TEST_P(HttpNetworkTransactionTest, BasicAuth) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      // Give a couple authenticate options (only the middle one is actually
      // supported).
      MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After calling trans->RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info1;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);

  int64_t writes_size1 = CountWriteBytes(data_writes1);
  EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
  int64_t reads_size1 = CountReadBytes(data_reads1);
  EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
  // The load timing after restart should have a new socket ID, and times after
  // those of the first load timing.
  EXPECT_LE(load_timing_info1.receive_headers_end,
            load_timing_info2.connect_timing.connect_start);
  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);

  int64_t writes_size2 = CountWriteBytes(data_writes2);
  EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
  int64_t reads_size2 = CountReadBytes(data_reads2);
  EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->did_use_server_http_auth);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
}

// Test the request-challenge-retry sequence for basic auth.
// (basic auth is the easiest to mock, because it has no randomness).
TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto resolver = std::make_unique<MockHostResolver>();
  auto* resolver_ptr = resolver.get();
  session_deps_.net_log = NetLog::Get();
  session_deps_.host_resolver = std::move(resolver);
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  resolver_ptr->rules()->ClearRules();
  resolver_ptr->rules()->AddRule("www.example.org", "127.0.0.1");

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      // Give a couple authenticate options (only the middle one is actually
      // supported).
      MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After calling trans->RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback1;

  EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
                                                NetLogWithSource())));

  LoadTimingInfo load_timing_info1;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);

  int64_t writes_size1 = CountWriteBytes(data_writes1);
  EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
  int64_t reads_size1 = CountReadBytes(data_reads1);
  EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  IPEndPoint endpoint;
  EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
  ASSERT_FALSE(endpoint.address().empty());
  EXPECT_EQ("127.0.0.1:80", endpoint.ToString());

  resolver_ptr->rules()->ClearRules();
  resolver_ptr->rules()->AddRule("www.example.org", "127.0.0.2");

  TestCompletionCallback callback2;

  EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
                    AuthCredentials(kFoo, kBar), callback2.callback())));

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
  // The load timing after restart should have a new socket ID, and times after
  // those of the first load timing.
  EXPECT_LE(load_timing_info1.receive_headers_end,
            load_timing_info2.connect_timing.connect_start);
  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);

  int64_t writes_size2 = CountWriteBytes(data_writes2);
  EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
  int64_t reads_size2 = CountReadBytes(data_reads2);
  EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->did_use_server_http_auth);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());

  EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
  ASSERT_FALSE(endpoint.address().empty());
  EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
}

// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
// will eventually give up.
TEST_P(HttpNetworkTransactionTest, BasicAuthForever) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      // Give a couple authenticate options (only the middle one is actually
      // supported).
      MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After calling trans->RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  MockWrite data_writes_restart[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;
  int rv = callback.GetResult(
      trans.Start(&request, callback.callback(), NetLogWithSource()));

  std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
  for (int i = 0; i < 32; i++) {
    // Check the previous response was a 401.
    EXPECT_THAT(rv, IsOk());
    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

    data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
        data_reads, data_writes_restart));
    session_deps_.socket_factory->AddSocketDataProvider(
        data_restarts.back().get());
    rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
                                                  callback.callback()));
  }

  // After too many tries, the transaction should have given up.
  EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
}

TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_EQ(0, rv);

  int64_t writes_size = CountWriteBytes(data_writes);
  EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
  int64_t reads_size = CountReadBytes(data_reads);
  EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
}

// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection.
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
  // On the second pass, the body read of the auth challenge is synchronous, so
  // IsConnectedAndIdle returns false.  The socket should still be drained and
  // reused.  See http://crbug.com/544255.
  for (int i = 0; i < 2; ++i) {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    session_deps_.net_log = NetLog::Get();
    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

    MockWrite data_writes[] = {
        MockWrite(ASYNC, 0,
                  "GET / HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n\r\n"),

        // After calling trans.RestartWithAuth(), this is the request we should
        // be issuing -- the final header line contains the credentials.
        MockWrite(ASYNC, 6,
                  "GET / HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    };

    MockRead data_reads[] = {
        MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
        MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
        MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
        MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
        MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),

        // Lastly, the server responds with the actual content.
        MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
        MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
        MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
        MockRead(ASYNC, 10, "Hello"),
    };

    SequencedSocketData data(data_reads, data_writes);
    data.set_busy_before_sync_reads(true);
    session_deps_.socket_factory->AddSocketDataProvider(&data);

    TestCompletionCallback callback1;

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    ASSERT_THAT(callback1.GetResult(rv), IsOk());

    LoadTimingInfo load_timing_info1;
    EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
    TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
    EXPECT_FALSE(response->did_use_server_http_auth);

    TestCompletionCallback callback2;

    rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
                               callback2.callback());
    ASSERT_THAT(callback2.GetResult(rv), IsOk());

    LoadTimingInfo load_timing_info2;
    EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
    TestLoadTimingReused(load_timing_info2);
    // The load timing after restart should have the same socket ID, and times
    // those of the first load timing.
    EXPECT_LE(load_timing_info1.receive_headers_end,
              load_timing_info2.send_start);
    EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);

    response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(response->did_use_server_http_auth);
    EXPECT_FALSE(response->auth_challenge.has_value());
    EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());

    std::string response_data;
    EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());

    int64_t writes_size = CountWriteBytes(data_writes);
    EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
    int64_t reads_size = CountReadBytes(data_reads);
    EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
  }
}

// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection and with no response body to drain.
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),

      // After calling trans.RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),  // No response body.

      // Lastly, the server responds with the actual content.
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead("hello"),
  };

  // An incorrect reconnect would cause this to be read.
  MockRead data_reads2[] = {
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->did_use_server_http_auth);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
}

// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection and with a large response body to drain.
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),

      // After calling trans.RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  // Respond with 5 kb of response body.
  std::string large_body_string("Unauthorized");
  large_body_string.append(5 * 1024, ' ');
  large_body_string.append("\r\n");

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // 5134 = 12 + 5 * 1024 + 2
      MockRead("Content-Length: 5134\r\n\r\n"),
      MockRead(ASYNC, large_body_string),

      // Lastly, the server responds with the actual content.
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead("hello"),
  };

  // An incorrect reconnect would cause this to be read.
  MockRead data_reads2[] = {
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->did_use_server_http_auth);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
}

// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// connection, but the server gets impatient and closes the connection.
TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
      // This simulates the seemingly successful write to a closed connection
      // if the bug is not fixed.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 14\r\n\r\n"),
      // Tell MockTCPClientSocket to simulate the server closing the connection.
      MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
      MockRead("Unauthorized\r\n"),
      MockRead(SYNCHRONOUS, OK),  // The server closes the connection.
  };

  // After calling trans.RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead("hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->did_use_server_http_auth);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
}

// Test the request-challenge-retry sequence for basic auth, over a connection
// that requires a restart when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  NetLogWithSource net_log_with_source =
      NetLogWithSource::Make(NetLogSourceType::NONE);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
  };

  // Since the first connection couldn't be reused, need to establish another
  // once given credentials.
  MockWrite data_writes2[] = {
      // After calling trans->RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead(SYNCHRONOUS, "hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;
  ConnectedHandler connected_handler;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  trans->SetConnectedCallback(connected_handler.Callback());

  int rv = trans->Start(&request, callback1.callback(), net_log_with_source);
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);

  // TODO(crbug.com/40637204): Fix handling of OnConnected() when proxy
  // authentication is required. We should notify the callback that a connection
  // was established, even though the stream might not be ready for us to send
  // data through it.
  EXPECT_THAT(connected_handler.transports(), IsEmpty());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->headers->IsKeepAlive());
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  LoadTimingInfo load_timing_info;
  // CONNECT requests and responses are handled at the connect job level, so
  // the transaction does not yet have a connection.
  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));

  TestCompletionCallback callback2;

  rv =
      trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  // Check that credentials were successfully cached, with the right target.
  HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
      HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
      NetworkAnonymizationKey());
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo, entry->credentials().username());
  ASSERT_EQ(kBar, entry->credentials().password());

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test the request-challenge-retry sequence for basic auth, over a connection
// that requires a restart when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Proxy-Connection: close\r\n\r\n"),
  };

  MockWrite data_writes2[] = {
      // After calling trans->RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead(SYNCHRONOUS, "hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  ConnectedHandler connected_handler;
  TestCompletionCallback callback1;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  trans->SetConnectedCallback(connected_handler.Callback());

  int rv = trans->Start(&request, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->headers->IsKeepAlive());
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
  EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
            response->proxy_chain);

  // TODO(crbug.com/40637204): Fix handling of OnConnected() when proxy
  // authentication is required. We should notify the callback that a connection
  // was established, even though the stream might not be ready for us to send
  // data through it.
  EXPECT_THAT(connected_handler.transports(), IsEmpty());

  LoadTimingInfo load_timing_info;
  // CONNECT requests and responses are handled at the connect job level, so
  // the transaction does not yet have a connection.
  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));

  TestCompletionCallback callback2;

  rv =
      trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
            response->proxy_chain);

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
  // On the second pass, the body read of the auth challenge is synchronous, so
  // IsConnectedAndIdle returns false.  The socket should still be drained and
  // reused.  See http://crbug.com/544255.
  for (int i = 0; i < 2; ++i) {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("https://www.example.org/");
    // Ensure that proxy authentication is attempted even
    // when the no authentication data flag is set.
    request.privacy_mode = PRIVACY_MODE_ENABLED;
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    // Configure against proxy server "myproxy:70".
    session_deps_.proxy_resolution_service =
        ConfiguredProxyResolutionService::CreateFixedForTest(
            "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
    RecordingNetLogObserver net_log_observer;
    session_deps_.net_log = NetLog::Get();
    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    // Since we have proxy, should try to establish tunnel.
    MockWrite data_writes1[] = {
        MockWrite(ASYNC, 0,
                  "CONNECT www.example.org:443 HTTP/1.1\r\n"
                  "Host: www.example.org:443\r\n"
                  "Proxy-Connection: keep-alive\r\n"
                  "User-Agent: test-ua\r\n\r\n"),

        // After calling trans.RestartWithAuth(), this is the request we should
        // be issuing -- the final header line contains the credentials.
        MockWrite(ASYNC, 3,
                  "CONNECT www.example.org:443 HTTP/1.1\r\n"
                  "Host: www.example.org:443\r\n"
                  "Proxy-Connection: keep-alive\r\n"
                  "User-Agent: test-ua\r\n"
                  "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
    };

    // The proxy responds to the connect with a 407, using a persistent
    // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
    MockRead data_reads1[] = {
        // No credentials.
        MockRead(ASYNC, 1,
                 "HTTP/1.0 407 Proxy Authentication Required\r\n"
                 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
                 "Proxy-Connection: keep-alive\r\n"
                 "User-Agent: test-ua\r\n"
                 "Content-Length: 10\r\n\r\n"),
        MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),

        // Wrong credentials (wrong password).
        MockRead(ASYNC, 4,
                 "HTTP/1.0 407 Proxy Authentication Required\r\n"
                 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
                 "Proxy-Connection: keep-alive\r\n"
                 "User-Agent: test-ua\r\n"
                 "Content-Length: 10\r\n\r\n"),
        // No response body because the test stops reading here.
        MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
    };

    SequencedSocketData data1(data_reads1, data_writes1);
    data1.set_busy_before_sync_reads(true);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(),
                         NetLogWithSource::Make(NetLogSourceType::NONE));
    EXPECT_THAT(callback1.GetResult(rv), IsOk());

    auto entries = net_log_observer.GetEntries();
    size_t pos = ExpectLogContainsSomewhere(
        entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
        NetLogEventPhase::NONE);
    ExpectLogContainsSomewhere(
        entries, pos,
        NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
        NetLogEventPhase::NONE);

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->headers);
    EXPECT_TRUE(response->headers->IsKeepAlive());
    EXPECT_EQ(407, response->headers->response_code());
    EXPECT_EQ(10, response->headers->GetContentLength()->InBytes());
    EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
    EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

    TestCompletionCallback callback2;

    // Wrong password (should be "bar").
    rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
                               callback2.callback());
    EXPECT_THAT(callback2.GetResult(rv), IsOk());

    response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->headers);
    EXPECT_TRUE(response->headers->IsKeepAlive());
    EXPECT_EQ(407, response->headers->response_code());
    EXPECT_EQ(10, response->headers->GetContentLength()->InBytes());
    EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
    EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

    // Flush the idle socket before the NetLog and HttpNetworkTransaction go
    // out of scope.
    session->CloseAllConnections(ERR_FAILED, "Very good reason");
  }
}

// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
  // On the second pass, the body read of the auth challenge is synchronous, so
  // IsConnectedAndIdle returns false.  The socket should still be drained and
  // reused.  See http://crbug.com/544255.
  for (int i = 0; i < 2; ++i) {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("https://www.example.org/");
    // Ensure that proxy authentication is attempted even
    // when the no authentication data flag is set.
    request.privacy_mode = PRIVACY_MODE_ENABLED;
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    // Configure against proxy server "myproxy:70".
    session_deps_.proxy_resolution_service =
        ConfiguredProxyResolutionService::CreateFixedForTest(
            "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
    RecordingNetLogObserver net_log_observer;
    session_deps_.net_log = NetLog::Get();
    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    // Since we have proxy, should try to establish tunnel.
    MockWrite data_writes1[] = {
        MockWrite(ASYNC, 0,
                  "CONNECT www.example.org:443 HTTP/1.1\r\n"
                  "Host: www.example.org:443\r\n"
                  "Proxy-Connection: keep-alive\r\n"
                  "User-Agent: test-ua\r\n\r\n"),

        // After calling trans.RestartWithAuth(), this is the request we should
        // be issuing -- the final header line contains the credentials.
        MockWrite(ASYNC, 3,
                  "CONNECT www.example.org:443 HTTP/1.1\r\n"
                  "Host: www.example.org:443\r\n"
                  "Proxy-Connection: keep-alive\r\n"
                  "User-Agent: test-ua\r\n"
                  "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
    };

    // The proxy responds to the connect with a 407, using a persistent
    // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
    MockRead data_reads1[] = {
        // No credentials.
        MockRead(ASYNC, 1,
                 "HTTP/1.1 407 Proxy Authentication Required\r\n"
                 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
                 "Content-Length: 10\r\n\r\n"),
        MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),

        // Wrong credentials (wrong password).
        MockRead(ASYNC, 4,
                 "HTTP/1.1 407 Proxy Authentication Required\r\n"
                 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
                 "Content-Length: 10\r\n\r\n"),
        // No response body because the test stops reading here.
        MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
    };

    SequencedSocketData data1(data_reads1, data_writes1);
    data1.set_busy_before_sync_reads(true);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(),
                         NetLogWithSource::Make(NetLogSourceType::NONE));
    EXPECT_THAT(callback1.GetResult(rv), IsOk());

    auto entries = net_log_observer.GetEntries();
    size_t pos = ExpectLogContainsSomewhere(
        entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
        NetLogEventPhase::NONE);
    ExpectLogContainsSomewhere(
        entries, pos,
        NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
        NetLogEventPhase::NONE);

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->headers);
    EXPECT_TRUE(response->headers->IsKeepAlive());
    EXPECT_EQ(407, response->headers->response_code());
    EXPECT_EQ(10, response->headers->GetContentLength()->InBytes());
    EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
    EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
    EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
              response->proxy_chain);

    TestCompletionCallback callback2;

    // Wrong password (should be "bar").
    rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
                               callback2.callback());
    EXPECT_THAT(callback2.GetResult(rv), IsOk());

    response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->headers);
    EXPECT_TRUE(response->headers->IsKeepAlive());
    EXPECT_EQ(407, response->headers->response_code());
    EXPECT_EQ(10, response->headers->GetContentLength()->InBytes());
    EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
    EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
    EXPECT_FALSE(response->did_use_server_http_auth);
    EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
              response->proxy_chain);

    // Flush the idle socket before the NetLog and HttpNetworkTransaction go
    // out of scope.
    session->CloseAllConnections(ERR_FAILED, "Very good reason");
  }
}

// Test the request-challenge-retry sequence for basic auth, over a keep-alive
// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
// the case the server sends extra data on the original socket, so it can't be
// reused.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a persistent, but sends
  // extra data, so the socket cannot be reused.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead(ASYNC, 1,
               "HTTP/1.1 407 Proxy Authentication Required\r\n"
               "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 10\r\n\r\n"),
      MockRead(SYNCHRONOUS, 2, "0123456789"),
      MockRead(SYNCHRONOUS, 3, "I'm broken!"),
  };

  MockWrite data_writes2[] = {
      // After calling trans->RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),

      MockWrite(ASYNC, 2,
                "GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead(ASYNC, 3,
               "HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html; charset=iso-8859-1\r\n"
               "Content-Length: 5\r\n\r\n"),
      // No response body because the test stops reading here.
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
  };

  SequencedSocketData data1(data_reads1, data_writes1);
  data1.set_busy_before_sync_reads(true);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SequencedSocketData data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(callback1.GetResult(rv), IsOk());

  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  LoadTimingInfo load_timing_info;
  // CONNECT requests and responses are handled at the connect job level, so
  // the transaction does not yet have a connection.
  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));

  TestCompletionCallback callback2;

  rv =
      trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(callback2.GetResult(rv), IsOk());

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test the case a proxy closes a socket while the challenge body is being
// drained.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  // Ensure that proxy authentication is attempted even
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead("spam!"),
      // Server hands up in the middle of the body.
      MockRead(ASYNC, ERR_CONNECTION_CLOSED),
  };

  MockWrite data_writes2[] = {
      // After calling trans.RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead(SYNCHRONOUS, "hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  std::string body;
  EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
  EXPECT_EQ("hello", body);
}

// Test that we don't read the response body when we fail to establish a tunnel,
// even if the user cancels the proxy's auth attempt.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407.
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead("0123456789"),
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));

  // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test the no-tunnel HTTP auth case where proxy and server origins and realms
// are the same, but the user/passwords are different. Serves to verify
// credentials are correctly separated based on HttpAuth::Target.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://myproxy:70/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Proxy matches request URL.
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  NetLogWithSource net_log_with_source =
      NetLogWithSource::Make(NetLogSourceType::NONE);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes[] = {
      // Initial request gets a proxy auth challenge. The user-agent from
      // `session_deps_` does not appear because this is a GET request to the
      // proxy but containing headers for the destination.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
      // Retry with proxy auth credentials, which will result in a server auth
      // challenge.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
      // Retry with proxy and server auth credentials, which gets a response.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
      // A second request should preemptively send the correct proxy and server
      // auth headers.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
  };

  MockRead data_reads[] = {
      // Proxy auth challenge.
      MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Server auth challenge.
      MockRead("HTTP/1.0 401 Authentication Required\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Response.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Content-Length: 5\r\n\r\n"
               "hello"),
      // Response to second request.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Content-Length: 2\r\n\r\n"
               "hi"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(401, response->headers->response_code());
  EXPECT_FALSE(response->auth_challenge->is_proxy);
  EXPECT_EQ("http://myproxy:70",
            response->auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);

  rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
                              callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  std::string response_data;
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello", response_data);

  // Check that the credentials were cached correctly.
  HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
      HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
      NetworkAnonymizationKey());
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo, entry->credentials().username());
  ASSERT_EQ(kBar, entry->credentials().password());
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
      HttpAuth::AUTH_SERVER, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
      NetworkAnonymizationKey());
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo2, entry->credentials().username());
  ASSERT_EQ(kBar2, entry->credentials().password());

  // Make another request, which should automatically send the correct proxy and
  // server auth credentials and get another response.
  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hi", response_data);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test the no-tunnel HTTP auth case where proxy and server origins and realms
// are the same, but the user/passwords are different, and with different
// NetworkAnonymizationKeys. Sends one request with a NAK, response to both
// proxy and auth challenges, sends another request with another NAK, expecting
// only the proxy credentials to be cached, and thus sees only a server auth
// challenge. Then sends a request with the original NAK, expecting cached proxy
// and auth credentials that match the ones used in the first request.
//
// Serves to verify credentials are correctly separated based on
// HttpAuth::Target and NetworkAnonymizationKeys, but NetworkAnonymizationKey
// only affects server credentials, not proxy credentials.
TEST_P(HttpNetworkTransactionTest,
       BasicAuthProxyMatchesServerAuthWithNetworkAnonymizationKeyNoTunnel) {
  const SchemefulSite kSite1(GURL("https://foo.test/"));
  const auto kNetworkAnonymizationKey1 =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
  const SchemefulSite kSite2(GURL("https://bar.test/"));
  const auto kNetworkAnonymizationKey2 =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);

  // This test would need to use a single socket without this option enabled.
  // Best to use this option when it would affect a test, as it will eventually
  // become the default behavior.
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionConnectionsByNetworkIsolationKey);

  // Proxy matches request URL.
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  NetLogWithSource net_log_with_source =
      NetLogWithSource::Make(NetLogSourceType::NONE);

  session_deps_.net_log = NetLog::Get();
  session_deps_.key_auth_cache_server_entries_by_network_anonymization_key =
      true;
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes[] = {
      // Initial request gets a proxy auth challenge.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
      // Retry with proxy auth credentials, which will result in a server auth
      // challenge.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
      // Retry with proxy and server auth credentials, which gets a response.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
      // Another request to the same server and using the same NAK should
      // preemptively send the correct cached proxy and server
      // auth headers.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
  };

  MockRead data_reads[] = {
      // Proxy auth challenge.
      MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Server auth challenge.
      MockRead("HTTP/1.0 401 Authentication Required\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Response.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Content-Length: 5\r\n\r\n"
               "hello"),
      // Response to second request.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Content-Length: 2\r\n\r\n"
               "hi"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  MockWrite data_writes2[] = {
      // Initial request using a different NetworkAnonymizationKey includes the
      // cached proxy credentials, but not server credentials.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
      // Retry with proxy and new server auth credentials, which gets a
      // response.
      MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
                "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      // Server auth challenge.
      MockRead("HTTP/1.0 401 Authentication Required\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Response.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Content-Length: 9\r\n\r\n"
               "greetings"),
  };

  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback;

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://myproxy:70/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request.network_isolation_key = kNetworkIsolationKey1;
  request.network_anonymization_key = kNetworkAnonymizationKey1;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(401, response->headers->response_code());
  EXPECT_FALSE(response->auth_challenge->is_proxy);
  EXPECT_EQ("http://myproxy:70",
            response->auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);

  rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
                              callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
  std::string response_data;
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello", response_data);

  // Check that the proxy credentials were cached correctly. The should be
  // accessible with any NetworkAnonymizationKey.
  HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
      HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
      kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo, entry->credentials().username());
  ASSERT_EQ(kBar, entry->credentials().password());
  EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
                       url::SchemeHostPort(GURL("http://myproxy:70")),
                       HttpAuth::AUTH_PROXY, "MyRealm1",
                       HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));

  // Check that the server credentials were cached correctly. The should be
  // accessible with only kNetworkAnonymizationKey1.
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo2, entry->credentials().username());
  ASSERT_EQ(kBar2, entry->credentials().password());
  // Looking up the server entry with another NetworkAnonymizationKey should
  // fail.
  EXPECT_FALSE(session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));

  // Make another request with a different NetworkAnonymizationKey. It should
  // use another socket, reuse the cached proxy credentials, but result in a
  // server auth challenge.
  request.network_isolation_key = kNetworkIsolationKey2;
  request.network_anonymization_key = kNetworkAnonymizationKey2;

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(401, response->headers->response_code());
  EXPECT_FALSE(response->auth_challenge->is_proxy);
  EXPECT_EQ("http://myproxy:70",
            response->auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);

  rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
                              callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("greetings", response_data);

  // Check that the proxy credentials are still cached.
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_PROXY,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo, entry->credentials().username());
  ASSERT_EQ(kBar, entry->credentials().password());
  EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
                       url::SchemeHostPort(GURL("http://myproxy:70")),
                       HttpAuth::AUTH_PROXY, "MyRealm1",
                       HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));

  // Check that the correct server credentials are cached for each
  // NetworkAnonymizationKey.
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo2, entry->credentials().username());
  ASSERT_EQ(kBar2, entry->credentials().password());
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo3, entry->credentials().username());
  ASSERT_EQ(kBar3, entry->credentials().password());

  // Make a request with the original NetworkAnonymizationKey. It should reuse
  // the first socket, and the proxy credentials sent on the first socket.
  request.network_isolation_key = kNetworkIsolationKey1;
  request.network_anonymization_key = kNetworkAnonymizationKey1;
  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hi", response_data);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Much like the test above, but uses tunnelled connections.
TEST_P(HttpNetworkTransactionTest,
       BasicAuthProxyMatchesServerAuthWithNetworkAnonymizationKeyWithTunnel) {
  const SchemefulSite kSite1(GURL("https://foo.test/"));
  const auto kNetworkAnonymizationKey1 =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
  const SchemefulSite kSite2(GURL("https://bar.test/"));
  const auto kNetworkAnonymizationKey2 =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);

  // This test would need to use a single socket without this option enabled.
  // Best to use this option when it would affect a test, as it will eventually
  // become the default behavior.
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionConnectionsByNetworkIsolationKey);

  // Proxy matches request URL.
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  NetLogWithSource net_log_with_source =
      NetLogWithSource::Make(NetLogSourceType::NONE);
  session_deps_.net_log = NetLog::Get();
  session_deps_.key_auth_cache_server_entries_by_network_anonymization_key =
      true;
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes[] = {
      // Initial tunnel request gets a proxy auth challenge.
      MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      // Retry with proxy auth credentials, which will result in establishing a
      // tunnel.
      MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
      // Request over the tunnel, which gets a server auth challenge.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Connection: keep-alive\r\n\r\n"),
      // Retry with server auth credentials, which gets a response.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
      // Another request to the same server and using the same NAK should
      // preemptively send the correct cached server
      // auth header. Since a tunnel was already established, the proxy headers
      // won't be sent again except when establishing another tunnel.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
  };

  MockRead data_reads[] = {
      // Proxy auth challenge.
      MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "User-Agent: test-ua\r\n"
               "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Tunnel success
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      // Server auth challenge.
      MockRead("HTTP/1.0 401 Authentication Required\r\n"
               "Connection: keep-alive\r\n"
               "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Response.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 5\r\n\r\n"
               "hello"),
      // Response to second request.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 2\r\n\r\n"
               "hi"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  // One for the proxy connection, one of the server connection.
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  MockWrite data_writes2[] = {
      // Initial request using a different NetworkAnonymizationKey includes the
      // cached proxy credentials when establishing a tunnel.
      MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
      // Request over the tunnel, which gets a server auth challenge. Cached
      // credentials cannot be used, since the NAK is different.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Connection: keep-alive\r\n\r\n"),
      // Retry with server auth credentials, which gets a response.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: myproxy:70\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      // Tunnel success
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      // Server auth challenge.
      MockRead("HTTP/1.0 401 Authentication Required\r\n"
               "Connection: keep-alive\r\n"
               "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n\r\n"),
      // Response.
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 9\r\n\r\n"
               "greetings"),
  };

  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  // One for the proxy connection, one of the server connection.
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
  SSLSocketDataProvider ssl4(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);

  TestCompletionCallback callback;

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://myproxy:70/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request.network_isolation_key = kNetworkIsolationKey1;
  request.network_anonymization_key = kNetworkAnonymizationKey1;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));

  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(401, response->headers->response_code());
  EXPECT_FALSE(response->auth_challenge->is_proxy);
  EXPECT_EQ("https://myproxy:70",
            response->auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);

  rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
                              callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
  std::string response_data;
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello", response_data);

  // Check that the proxy credentials were cached correctly. The should be
  // accessible with any NetworkAnonymizationKey.
  HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(url::SchemeHostPort(GURL("https://myproxy:70"))),
      HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
      kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo, entry->credentials().username());
  ASSERT_EQ(kBar, entry->credentials().password());
  EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
                       url::SchemeHostPort(GURL("https://myproxy:70")),
                       HttpAuth::AUTH_PROXY, "MyRealm1",
                       HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));

  // Check that the server credentials were cached correctly. The should be
  // accessible with only kNetworkAnonymizationKey1.
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo2, entry->credentials().username());
  ASSERT_EQ(kBar2, entry->credentials().password());
  // Looking up the server entry with another NetworkAnonymiationKey should
  // fail.
  EXPECT_FALSE(session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));

  // Make another request with a different NetworkAnonymiationKey. It should use
  // another socket, reuse the cached proxy credentials, but result in a server
  // auth challenge.
  request.network_isolation_key = kNetworkIsolationKey2;
  request.network_anonymization_key = kNetworkAnonymizationKey2;

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(401, response->headers->response_code());
  EXPECT_FALSE(response->auth_challenge->is_proxy);
  EXPECT_EQ("https://myproxy:70",
            response->auth_challenge->challenger.Serialize());
  EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);

  rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
                              callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("greetings", response_data);

  // Check that the proxy credentials are still cached.
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_PROXY,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo, entry->credentials().username());
  ASSERT_EQ(kBar, entry->credentials().password());
  EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
                       url::SchemeHostPort(GURL("https://myproxy:70")),
                       HttpAuth::AUTH_PROXY, "MyRealm1",
                       HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));

  // Check that the correct server credentials are cached for each
  // NetworkAnonymiationKey.
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo2, entry->credentials().username());
  ASSERT_EQ(kBar2, entry->credentials().password());
  entry = session->http_auth_cache()->Lookup(
      url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2);
  ASSERT_TRUE(entry);
  ASSERT_EQ(kFoo3, entry->credentials().username());
  ASSERT_EQ(kBar3, entry->credentials().password());

  // Make a request with the original NetworkAnonymiationKey. It should reuse
  // the first socket, and the proxy credentials sent on the first socket.
  request.network_isolation_key = kNetworkIsolationKey1;
  request.network_anonymization_key = kNetworkAnonymizationKey1;

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans->Start(&request, callback.callback(), net_log_with_source);
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hi", response_data);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test that we don't pass extraneous headers from the proxy's response to the
// caller when the proxy responds to CONNECT with 407.
TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407.
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("X-Foo: bar\r\n"),
      MockRead("Set-Cookie: foo=bar\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
  EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));

  // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // We are using a DIRECT connection (i.e. no proxy) for this session.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
}

// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
// through a non-authenticating proxy. The request should fail with
// ERR_UNEXPECTED_PROXY_AUTH.
// Note that it is impossible to detect if an HTTP server returns a 407 through
// a non-authenticating proxy - there is nothing to indicate whether the
// response came from the proxy or the server, so it is treated as if the proxy
// issued the challenge.
TEST_P(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 407 Unauthorized\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);
}

// Test a proxy auth scheme that allows default credentials and a proxy server
// that uses non-persistent connections.
TEST_P(HttpNetworkTransactionTest,
       AuthAllowsDefaultCredentialsTunnelConnectionClose) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
  auth_handler_factory->set_do_init_from_challenge(true);
  auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_PROXY);
  session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);

  // Add NetLog just so can verify load timing information gets a NetLog ID.
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Mock\r\n"),
      MockRead("Proxy-Connection: close\r\n\r\n"),
  };

  // Since the first connection couldn't be reused, need to establish another
  // once given credentials.
  MockWrite data_writes2[] = {
      // After calling trans->RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: auth_token\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead(SYNCHRONOUS, "hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_FALSE(response->headers->IsKeepAlive());
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
  EXPECT_FALSE(response->auth_challenge.has_value());

  LoadTimingInfo load_timing_info;
  // CONNECT requests and responses are handled at the connect job level, so
  // the transaction does not yet have a connection.
  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));

  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test a proxy auth scheme that allows default credentials and a proxy server
// that hangs up when credentials are initially sent.
TEST_P(HttpNetworkTransactionTest,
       AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
  auth_handler_factory->set_do_init_from_challenge(true);
  auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_PROXY);
  session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);

  // Add NetLog just so can verify load timing information gets a NetLog ID.
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: auth_token\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
  };

  // Since the first connection was closed, need to establish another once given
  // credentials.
  MockWrite data_writes2[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: auth_token\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead(SYNCHRONOUS, "hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
  EXPECT_FALSE(response->auth_challenge.has_value());

  LoadTimingInfo load_timing_info;
  // CONNECT requests and responses are handled at the connect job level, so
  // the transaction does not yet have a connection.
  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));

  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test a proxy auth scheme that allows default credentials and a proxy server
// that hangs up when credentials are initially sent, and hangs up again when
// they are retried.
TEST_P(HttpNetworkTransactionTest,
       AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
  auth_handler_factory->set_do_init_from_challenge(true);
  auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_PROXY);
  session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);

  // Add NetLog just so can verify load timing information gets a NetLog ID.
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: auth_token\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, and then hangs up after the
  // second request is sent.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Content-Length: 0\r\n"),
      MockRead("Proxy-Connection: keep-alive\r\n"
               "User-Agent: test-ua\r\n"),
      MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
  };

  // HttpNetworkTransaction sees a reused connection that was closed with
  // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
  // request.
  MockWrite data_writes2[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy, having had more than enough of us, just hangs up.
  MockRead data_reads2[] = {
      // No credentials.
      MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
  EXPECT_FALSE(response->auth_challenge.has_value());

  LoadTimingInfo load_timing_info;
  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));

  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// This test exercises an odd edge case where the proxy closes the connection
// after the authentication handshake is complete. Presumably this technique is
// used in lieu of returning a 403 or 5xx status code when the authentication
// succeeds, but the user is not authorized to connect to the destination
// server. There's no standard for what a proxy should do to indicate a blocked
// site.
TEST_P(HttpNetworkTransactionTest,
       AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
  auth_handler_factory->set_do_init_from_challenge(true);

  // Create two mock AuthHandlers. This is because the transaction gets retried
  // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
  // was a real network error.
  //
  // The handlers support both default and explicit credentials. The retry
  // mentioned above should be able to reuse the default identity. Thus there
  // should never be a need to prompt for explicit credentials.
  auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  mock_handler->set_allows_explicit_credentials(true);
  mock_handler->set_connection_based(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_PROXY);
  mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  mock_handler->set_allows_explicit_credentials(true);
  mock_handler->set_connection_based(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_PROXY);
  session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Data for both sockets.
  //
  // Writes are for the tunnel establishment attempts and the
  // authentication handshake.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: auth_token\r\n\r\n"),

      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: auth_token\r\n\r\n"),
  };

  // The server side of the authentication handshake. Note that the response to
  // the final CONNECT request is ERR_CONNECTION_CLOSED.
  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Content-Length: 0\r\n"),
      MockRead("Proxy-Connection: keep-alive\r\n"
               "User-Agent: test-ua\r\n"),
      MockRead("Proxy-Authenticate: Mock\r\n\r\n"),

      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Content-Length: 0\r\n"),
      MockRead("Proxy-Connection: keep-alive\r\n"
               "User-Agent: test-ua\r\n"),
      MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),

      MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // The second socket is for the reconnection attempt. Data is identical to the
  // first attempt.
  StaticSocketDataProvider data2(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());

  // Two rounds per handshake. After one retry, the error is propagated up the
  // stack.
  for (int i = 0; i < 4; ++i) {
    EXPECT_THAT(callback.GetResult(rv), IsOk());

    const HttpResponseInfo* response = trans->GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->headers);
    EXPECT_EQ(407, response->headers->response_code());
    ASSERT_TRUE(trans->IsReadyToRestartForAuth());

    rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
  }

  // One shall be the number thou shalt retry, and the number of the retrying
  // shall be one.  Two shalt thou not retry, neither retry thou zero, excepting
  // that thou then proceed to one.  Three is right out.  Once the number one,
  // being the first number, be reached, then lobbest thou thy
  // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test a proxy auth scheme that allows default credentials and a proxy server
// that hangs up when credentials are initially sent, and sends a challenge
// again they are retried.
TEST_P(HttpNetworkTransactionTest,
       AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
  auth_handler_factory->set_do_init_from_challenge(true);
  auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_PROXY);
  // Add another handler for the second challenge. It supports default
  // credentials, but they shouldn't be used, since they were already tried.
  mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_PROXY);
  session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);

  // Add NetLog just so can verify load timing information gets a NetLog ID.
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Mock\r\n"),
      MockRead("Proxy-Connection: close\r\n\r\n"),
  };

  // Since the first connection was closed, need to establish another once given
  // credentials.
  MockWrite data_writes2[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: auth_token\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Mock\r\n"),
      MockRead("Proxy-Connection: close\r\n\r\n"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
  EXPECT_FALSE(response->auth_challenge.has_value());

  LoadTimingInfo load_timing_info;
  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));

  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
  EXPECT_TRUE(response->auth_challenge.has_value());

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// A more nuanced test than GenerateAuthToken test which asserts that
// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
// unnecessarily invalidated, and that if the server co-operates, the
// authentication handshake can continue with the same scheme but with a
// different identity.
TEST_P(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
  auth_handler_factory->set_do_init_from_challenge(true);

  // First handler. Uses default credentials, but barfs at generate auth token.
  auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  mock_handler->set_allows_explicit_credentials(true);
  mock_handler->set_connection_based(true);
  mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_SERVER);

  // Add another handler for the second challenge. It supports default
  // credentials, but they shouldn't be used, since they were already tried.
  mock_handler = std::make_unique<HttpAuthHandlerMock>();
  mock_handler->set_allows_default_credentials(true);
  mock_handler->set_allows_explicit_credentials(true);
  mock_handler->set_connection_based(true);
  auth_handler_factory->AddMockHandler(std::move(mock_handler),
                                       HttpAuth::AUTH_SERVER);
  session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Authentication Required\r\n"
               "WWW-Authenticate: Mock\r\n"
               "Connection: keep-alive\r\n\r\n"),
  };

  // Identical to data_writes1[]. The AuthHandler encounters a
  // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
  // transaction procceds without an authorization header.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 401 Authentication Required\r\n"
               "WWW-Authenticate: Mock\r\n"
               "Connection: keep-alive\r\n\r\n"),
  };

  MockWrite data_writes3[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: auth_token\r\n\r\n"),
  };

  MockRead data_reads3[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Length: 5\r\n"
               "Content-Type: text/plain\r\n"
               "Connection: keep-alive\r\n\r\n"
               "Hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  StaticSocketDataProvider data3(data_reads3, data_writes3);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  // The following three tests assert that an authentication challenge was
  // received and that the stack is ready to respond to the challenge using
  // ambient credentials.
  EXPECT_EQ(401, response->headers->response_code());
  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
  EXPECT_FALSE(response->auth_challenge.has_value());

  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);

  // The following three tests assert that an authentication challenge was
  // received and that the stack needs explicit credentials before it is ready
  // to respond to the challenge.
  EXPECT_EQ(401, response->headers->response_code());
  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
  EXPECT_TRUE(response->auth_challenge.has_value());

  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(200, response->headers->response_code());

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Proxy resolver that returns a proxy with the same host and port for different
// schemes, based on the path of the URL being requests.
class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
 public:
  SameProxyWithDifferentSchemesProxyResolver() = default;

  SameProxyWithDifferentSchemesProxyResolver(
      const SameProxyWithDifferentSchemesProxyResolver&) = delete;
  SameProxyWithDifferentSchemesProxyResolver& operator=(
      const SameProxyWithDifferentSchemesProxyResolver&) = delete;

  ~SameProxyWithDifferentSchemesProxyResolver() override = default;

  static constexpr uint16_t kProxyPort = 10000;

  static HostPortPair ProxyHostPortPair() {
    return HostPortPair("proxy.test", kProxyPort);
  }

  static std::string ProxyHostPortPairAsString() {
    return ProxyHostPortPair().ToString();
  }

  // ProxyResolver implementation.
  int GetProxyForURL(const GURL& url,
                     const NetworkAnonymizationKey& network_anonymization_key,
                     ProxyInfo* results,
                     CompletionOnceCallback callback,
                     std::unique_ptr<Request>* request,
                     const NetLogWithSource& /*net_log*/) override {
    *results = ProxyInfo();
    results->set_traffic_annotation(
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
    if (url.GetPath() == "/socks4") {
      results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
      return OK;
    }
    if (url.GetPath() == "/socks5") {
      results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
      return OK;
    }
    if (url.GetPath() == "/http") {
      results->UsePacString("PROXY " + ProxyHostPortPairAsString());
      return OK;
    }
    if (url.GetPath() == "/https") {
      results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
      return OK;
    }
    NOTREACHED();
  }
};

class SameProxyWithDifferentSchemesProxyResolverFactory
    : public ProxyResolverFactory {
 public:
  SameProxyWithDifferentSchemesProxyResolverFactory()
      : ProxyResolverFactory(false) {}

  SameProxyWithDifferentSchemesProxyResolverFactory(
      const SameProxyWithDifferentSchemesProxyResolverFactory&) = delete;
  SameProxyWithDifferentSchemesProxyResolverFactory& operator=(
      const SameProxyWithDifferentSchemesProxyResolverFactory&) = delete;

  int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
                          std::unique_ptr<ProxyResolver>* resolver,
                          CompletionOnceCallback callback,
                          std::unique_ptr<Request>* request) override {
    *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
    return OK;
  }
};

// Check that when different proxy schemes are all applied to a proxy at the
// same address, the connections are not grouped together.  i.e., a request to
// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
// request to foo.com using proxy.com as an HTTP proxy.
TEST_P(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  MockWrite socks_writes[] = {
      MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80),
      MockWrite(SYNCHRONOUS,
                "GET /socks4 HTTP/1.1\r\n"
                "Host: test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead socks_reads[] = {
      MockRead(SYNCHRONOUS, kSOCKS4OkReply),
      MockRead("HTTP/1.0 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 15\r\n\r\n"
               "SOCKS4 Response"),
  };
  StaticSocketDataProvider socks_data(socks_reads, socks_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&socks_data);

  const char kSOCKS5Request[] = {
      0x05,                  // Version
      0x01,                  // Command (CONNECT)
      0x00,                  // Reserved
      0x03,                  // Address type (DOMAINNAME)
      0x04,                  // Length of domain (4)
      't',  'e',  's', 't',  // Domain string
      0x00, 0x50,            // 16-bit port (80)
  };
  MockWrite socks5_writes[] = {
      MockWrite(ASYNC, kSOCKS5GreetRequest),
      MockWrite(ASYNC, base::as_byte_span(kSOCKS5Request)),
      MockWrite(SYNCHRONOUS,
                "GET /socks5 HTTP/1.1\r\n"
                "Host: test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead socks5_reads[] = {
      MockRead(ASYNC, kSOCKS5GreetResponse),
      MockRead(ASYNC, kSOCKS5OkResponse),
      MockRead("HTTP/1.0 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 15\r\n\r\n"
               "SOCKS5 Response"),
  };
  StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);

  MockWrite http_writes[] = {
      MockWrite(SYNCHRONOUS,
                "GET http://test/http HTTP/1.1\r\n"
                "Host: test\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };
  MockRead http_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Content-Length: 13\r\n\r\n"
               "HTTP Response"),
  };
  StaticSocketDataProvider http_data(http_reads, http_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  MockWrite https_writes[] = {
      MockWrite(SYNCHRONOUS,
                "GET http://test/https HTTP/1.1\r\n"
                "Host: test\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };
  MockRead https_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "Content-Length: 14\r\n\r\n"
               "HTTPS Response"),
  };
  StaticSocketDataProvider https_data(https_reads, https_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&https_data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  struct TestCase {
    GURL url;
    std::string expected_response;
    // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
    // after the test.
    int expected_idle_socks4_sockets;
    int expected_idle_socks5_sockets;
    // How many idle sockets there should be in the HTTP/HTTPS proxy socket
    // pools after the test.
    int expected_idle_http_sockets;
    int expected_idle_https_sockets;
  } const kTestCases[] = {
      {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0},
      {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0},
      {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0},
      {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1},
  };

  for (const auto& test_case : kTestCases) {
    SCOPED_TRACE(test_case.url);

    HttpRequestInfo request;
    request.method = "GET";
    request.url = test_case.url;
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
    ConnectedHandler connected_handler;

    auto transaction = std::make_unique<HttpNetworkTransaction>(
        DEFAULT_PRIORITY, session.get());

    transaction->SetConnectedCallback(connected_handler.Callback());

    TestCompletionCallback callback;
    int rv =
        transaction->Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(callback.GetResult(rv), IsOk());

    const HttpResponseInfo* response = transaction->GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->headers);
    EXPECT_EQ(200, response->headers->response_code());
    std::string response_data;
    EXPECT_THAT(ReadTransaction(transaction.get(), &response_data), IsOk());
    EXPECT_EQ(test_case.expected_response, response_data);

    TransportInfo expected_transport;
    expected_transport.type = TransportType::kProxied;
    expected_transport.endpoint =
        IPEndPoint(IPAddress::IPv4Localhost(),
                   SameProxyWithDifferentSchemesProxyResolver::kProxyPort);
    expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
    EXPECT_THAT(connected_handler.transports(),
                ElementsAre(expected_transport));

    // Return the socket to the socket pool, so can make sure it's not used for
    // the next requests.
    transaction.reset();
    base::RunLoop().RunUntilIdle();

    // Check the number of idle sockets in the pool, to make sure that used
    // sockets are indeed being returned to the socket pool.  If each request
    // doesn't return an idle socket to the pool, the test would incorrectly
    // pass.
    EXPECT_EQ(test_case.expected_idle_socks4_sockets,
              session
                  ->GetSocketPool(
                      HttpNetworkSession::NORMAL_SOCKET_POOL,
                      ProxyChain(ProxyServer::SCHEME_SOCKS4,
                                 SameProxyWithDifferentSchemesProxyResolver::
                                     ProxyHostPortPair()))
                  ->IdleSocketCount());
    EXPECT_EQ(test_case.expected_idle_socks5_sockets,
              session
                  ->GetSocketPool(
                      HttpNetworkSession::NORMAL_SOCKET_POOL,
                      ProxyChain(ProxyServer::SCHEME_SOCKS5,
                                 SameProxyWithDifferentSchemesProxyResolver::
                                     ProxyHostPortPair()))
                  ->IdleSocketCount());
    EXPECT_EQ(test_case.expected_idle_http_sockets,
              session
                  ->GetSocketPool(
                      HttpNetworkSession::NORMAL_SOCKET_POOL,
                      ProxyChain(ProxyServer::SCHEME_HTTP,
                                 SameProxyWithDifferentSchemesProxyResolver::
                                     ProxyHostPortPair()))
                  ->IdleSocketCount());
    EXPECT_EQ(test_case.expected_idle_https_sockets,
              session
                  ->GetSocketPool(
                      HttpNetworkSession::NORMAL_SOCKET_POOL,
                      ProxyChain(ProxyServer::SCHEME_HTTPS,
                                 SameProxyWithDifferentSchemesProxyResolver::
                                     ProxyHostPortPair()))
                  ->IdleSocketCount());
  }
}

// Test the load timing for HTTPS requests with an HTTP proxy.
TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/1");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.example.org/2");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  NetLogWithSource net_log_with_source =
      NetLogWithSource::Make(NetLogSourceType::NONE);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),

      MockWrite("GET /2 HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a persistent
  // connection.
  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 2\r\n\r\n"),
      MockRead(SYNCHRONOUS, "22"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans1->Start(&request1, callback1.callback(), net_log_with_source);
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_EQ(1u, response1->proxy_chain.length());
  EXPECT_TRUE(response1->proxy_chain.GetProxyServer(0).is_http());
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ(1, response1->headers->GetContentLength()->InBytes());

  LoadTimingInfo load_timing_info1;
  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);

  trans1.reset();

  TestCompletionCallback callback2;
  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans2->Start(&request2, callback2.callback(), net_log_with_source);
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
  ASSERT_TRUE(response2);
  ASSERT_EQ(1u, response2->proxy_chain.length());
  EXPECT_TRUE(response2->proxy_chain.GetProxyServer(0).is_http());
  ASSERT_TRUE(response2->headers);
  EXPECT_EQ(2, response2->headers->GetContentLength()->InBytes());

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
  TestLoadTimingReused(load_timing_info2);

  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);

  trans2.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/1");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.example.org/2");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  NetLogWithSource net_log_with_source =
      NetLogWithSource::Make(NetLogSourceType::NONE);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),

      MockWrite("GET /2 HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a persistent
  // connection.
  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 2\r\n\r\n"),
      MockRead(SYNCHRONOUS, "22"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans1->Start(&request1, callback1.callback(), net_log_with_source);
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ(1, response1->headers->GetContentLength()->InBytes());

  LoadTimingInfo load_timing_info1;
  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
  TestLoadTimingNotReusedWithPac(load_timing_info1,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  trans1.reset();

  TestCompletionCallback callback2;
  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans2->Start(&request2, callback2.callback(), net_log_with_source);
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
  ASSERT_TRUE(response2);
  ASSERT_TRUE(response2->headers);
  EXPECT_EQ(2, response2->headers->GetContentLength()->InBytes());

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
  TestLoadTimingReusedWithPac(load_timing_info2);

  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);

  trans2.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Make sure that NetworkAnonymizationKeys are passed down to the proxy layer.
TEST_P(HttpNetworkTransactionTest, ProxyResolvedWithNetworkAnonymizationKey) {
  ProxyConfig proxy_config;
  proxy_config.set_auto_detect(true);
  proxy_config.set_pac_url(GURL("http://fooproxyurl"));

  CapturingProxyResolver capturing_proxy_resolver;
  capturing_proxy_resolver.set_proxy_chain(ProxyChain::Direct());
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::make_unique<CapturingProxyResolverFactory>(
              &capturing_proxy_resolver),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // No need to continue with the network request - proxy resolution occurs
  // before establishing a data.
  StaticSocketDataProvider data{base::span<MockRead>(),
                                base::span<MockWrite>()};
  data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  // Run first request until an auth challenge is observed.
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://foo.test/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request.network_isolation_key = kNetworkIsolationKey;
  request.network_anonymization_key = kNetworkAnonymizationKey;
  HttpNetworkTransaction trans(LOWEST, session.get());
  TestCompletionCallback callback;
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));

  ASSERT_EQ(1u, capturing_proxy_resolver.lookup_info().size());
  ASSERT_EQ(
      kNetworkAnonymizationKey,
      capturing_proxy_resolver.lookup_info()[0].network_anonymization_key);
  ASSERT_EQ(request.url, capturing_proxy_resolver.lookup_info()[0].url);
}

// Test that a failure in resolving the proxy hostname is retrievable.
TEST_P(HttpNetworkTransactionTest, ProxyHostResolutionFailure) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  auto resolver = std::make_unique<MockHostResolver>();
  resolver->rules()->AddSimulatedTimeoutFailure("proxy");
  session_deps_.net_log = NetLog::Get();
  session_deps_.host_resolver = std::move(resolver);
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED));

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
}

// Test a simple GET (for an HTTP endpoint) through an HTTPS Proxy
// (HTTPS -> HTTP).
TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  // GET should use UA header from the request, not from the
  // `HttpUserAgentSettings` in session_deps_.
  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, "request-ua");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should use full url
  MockWrite data_writes1[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: request-ua\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  ConnectedHandler connected_handler;
  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  trans.SetConnectedCallback(connected_handler.Callback());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  ASSERT_EQ(1u, response->proxy_chain.length());
  EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  // DNS aliases should be empty when using a proxy.
  EXPECT_TRUE(response->dns_aliases.empty());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
  // not be reported as a property of the origin.
  EXPECT_FALSE(response->ssl_info.cert);
}

// Test a simple GET (for an HTTP endpoint) through two HTTPS proxies
// (HTTPS -> HTTPS -> HTTP). This should tunnel through both proxies.
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyGet) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes1[] = {
      MockWrite("CONNECT proxy2.test:71 HTTP/1.1\r\n"
                "Host: proxy2.test:71\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
                "Host: www.example.org:80\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  ConnectedHandler connected_handler;
  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  trans.SetConnectedCallback(connected_handler.Callback());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_EQ(2u, response->proxy_chain.length());
  EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
  EXPECT_TRUE(response->proxy_chain.GetProxyServer(1).is_https());
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  // DNS aliases should be empty when using a proxy.
  EXPECT_TRUE(response->dns_aliases.empty());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
  // not be reported as a property of the origin.
  EXPECT_FALSE(response->ssl_info.cert);
}

// Test a SPDY GET (for an HTTP endpoint) through an HTTPS (SPDY) proxy
// (SPDY -> HTTP).
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Fetch http://www.example.org/ via SPDY.
  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  ConnectedHandler connected_handler;
  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  trans.SetConnectedCallback(connected_handler.Callback());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(1u, response->proxy_chain.length());
  EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  // DNS aliases should be empty when using a proxy.
  EXPECT_TRUE(response->dns_aliases.empty());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoHTTP2;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);

  // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
  // not be reported as a property of the origin.
  EXPECT_FALSE(response->ssl_info.cert);
}

// Test a SPDY GET (for an HTTP endpoint) through two HTTPS (SPDY) proxies
// (SPDY -> SPDY -> HTTP).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySpdyGet) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:80 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // request is calculated correctly.
  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 80)));
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      spdy_util2.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  // Fetch http://www.example.org/ via HTTP/1.x.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util2.ConstructSpdyDataFrame(1, kGet, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util2.ConstructSpdyDataFrame(1, kResp, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));

  const char kRespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util2.ConstructSpdyDataFrame(1, kRespData, false));
  spdy::SpdySerializedFrame wrapped_wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_wrapped_get, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
      CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
      MockRead(ASYNC, 0, 8),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  ConnectedHandler connected_handler;
  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  trans.SetConnectedCallback(connected_handler.Callback());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/0),
            proxy_server_1_);
  EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/1),
            proxy_server_2_);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  // DNS aliases should be empty when using a proxy.
  EXPECT_TRUE(response->dns_aliases.empty());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kRespData, response_data);

  // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
  // not be reported as a property of the origin.
  EXPECT_FALSE(response->ssl_info.cert);
}

// Test a SPDY GET (for an HTTP endpoint) through the same HTTPS (SPDY) proxy
// twice (SPDY -> SPDY -> HTTP).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySameProxyTwiceSpdyGet) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure a nested proxy.
  const ProxyChain kSameServerNestedProxyChain =
      ProxyChain::ForIpProtection({{proxy_server_1_, proxy_server_1_}});

  ProxyList proxy_list;
  proxy_list.AddProxyChain(kSameServerNestedProxyChain);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy.test:70 via SPDY.
  spdy::SpdySerializedFrame proxy_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_1_.host_port_pair()));

  spdy::SpdySerializedFrame proxy_connect_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));

  // CONNECT to www.example.org:80 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // request is calculated correctly.
  SpdyTestUtil new_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 80)));
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  // Fetch http://www.example.org/ via HTTP/1.x.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));

  const char kRespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      new_spdy_util.ConstructSpdyDataFrame(1, kRespData, false));
  spdy::SpdySerializedFrame wrapped_wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_wrapped_get, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy_connect_resp, 1),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
      CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
      MockRead(ASYNC, 0, 8),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  ConnectedHandler connected_handler;
  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  trans.SetConnectedCallback(connected_handler.Callback());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/0),
            proxy_server_1_);
  EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/1),
            proxy_server_1_);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  // DNS aliases should be empty when using a proxy.
  EXPECT_TRUE(response->dns_aliases.empty());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kRespData, response_data);

  // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
  // not be reported as a property of the origin.
  EXPECT_FALSE(response->ssl_info.cert);
}

// Test that a SPDY protocol error encountered when attempting to perform an
// HTTP request over a multi-proxy chain is handled correctly.
TEST_P(HttpNetworkTransactionTest, NestedProxyHttpOverSpdyProtocolError) {
  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:80 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // request is calculated correctly.
  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 80)));
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_data(
      spdy_util_.ConstructWrappedSpdyFrame(data, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      // Instead of returning a valid response, just return wrapped data. This
      // should trigger an HTTP2 protocol error and not CHECK when nested
      // proxies are in use.
      CreateMockRead(wrapped_data, 4),
      MockRead(ASYNC, 0, 5),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
}

// Test that a proxy server requesting a client auth cert doesn't cause a crash.
// TODO(crbug.com/40284947): This test can be deleted once we no longer
// need the multi-proxy chain version below, since this functionality should
// be sufficiently tested elsewhere. For now this test just shows that
// single-proxy and multi-proxy behavior is consistent (when a read returns
// ERR_SSL_CLIENT_AUTH_CERT_NEEDED).
TEST_P(HttpNetworkTransactionTest, HttpsClientAuthCertNeededNoCrash) {
  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame endpoint_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  spdy::SpdySerializedFrame spdy_response_go_away(
      spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_PROTOCOL_ERROR,
                                     "Error 110 reading from socket."));

  MockWrite spdy_writes[] = {
      CreateMockWrite(endpoint_connect, 0),
      CreateMockWrite(spdy_response_go_away, 2),
  };

  MockRead spdy_reads[] = {
      MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans.GetResponseInfo()->cert_request_info.get();
  // In the case of a read returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED directly,
  // no `SSLCertRequestInfo` is available.
  EXPECT_FALSE(cert_request_info);
}

// Test that the first proxy server in a multi-proxy chain requesting a client
// auth cert doesn't cause a crash.
// TODO(crbug.com/40284947): Support client auth certificates for
// multi-proxy chains and then replace this test with a more robust one (for
// instance, a version of the AuthEverywhere test that uses a multi-proxy
// chain).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyClientAuthCertNeededFirstProxyNoCrash) {
  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame spdy_response_go_away(
      spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_PROTOCOL_ERROR,
                                     "Error 110 reading from socket."));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(spdy_response_go_away, 2),
  };

  MockRead spdy_reads[] = {
      MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans.GetResponseInfo()->cert_request_info.get();
  // In the case of a read returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED directly,
  // no `SSLCertRequestInfo` is available.
  EXPECT_FALSE(cert_request_info);
}

// Same as above but using a different method to request the client auth
// certificate.
// TODO(crbug.com/40284947): Support client auth certificates for
// multi-proxy chains and then replace this test with a more robust one (for
// instance, a version of the AuthEverywhere test that uses a multi-proxy
// chain).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyClientAuthCertNeededFirstProxyNoCrash2) {
  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  StaticSocketDataProvider spdy_data{base::span<MockRead>(),
                                     base::span<MockWrite>()};
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_proxy->host_and_port = proxy_server_1_.host_port_pair();

  SSLSocketDataProvider ssl(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl.cert_request_info = cert_request_info_proxy;
  ssl.expected_send_client_cert = false;
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans.GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_TRUE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port, proxy_server_1_.host_port_pair());
}

// Test that a read returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED after the first
// CONNECT doesn't result in a crash when a multi-proxy chain is in use.
// TODO(crbug.com/40284947): Support client auth certificates for
// multi-proxy chains and then replace this test with a more robust one (for
// instance, a version of the AuthEverywhere test that uses a multi-proxy
// chain).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyClientAuthCertNeededAfterFirstConnectNoCrash2) {
  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:80 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // request is calculated correctly.
  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 80)));
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame spdy_response_go_away(
      spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_PROTOCOL_ERROR,
                                     "Error 110 reading from socket."));
  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(spdy_response_go_away, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 4),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
  SSLCertRequestInfo* cert_request_info =
      trans.GetResponseInfo()->cert_request_info.get();
  EXPECT_FALSE(cert_request_info);
}

// Test that the second proxy server in a multi-proxy chain requesting a client
// auth cert doesn't cause a crash.
// TODO(crbug.com/40284947): Support client auth certificates for
// multi-proxy chains and then replace this test with a more robust one (for
// instance, a version of the AuthEverywhere test that uses a multi-proxy
// chain).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyClientAuthCertNeededSecondProxyNoCrash) {
  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(rst, 2),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_proxy->host_and_port = proxy_server_2_.host_port_pair();

  SSLSocketDataProvider ssl2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl2.cert_request_info = cert_request_info_proxy;
  ssl2.expected_send_client_cert = false;
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans.GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_TRUE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port, proxy_server_2_.host_port_pair());
}

// Test that the endpoint requesting a client auth cert over a multi-proxy chain
// tunnel doesn't cause a crash.
// TODO(crbug.com/40284947): Support client auth certificates for
// multi-proxy chains and then replace this test with a more robust one (for
// instance, a version of the AuthEverywhere test that uses a multi-proxy
// chain).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyClientAuthCertNeededEndpointNoCrash) {
  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:443 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // CONNECT is calculated correctly.
  SpdyTestUtil new_spdy_util;
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  spdy::SpdySerializedFrame rst(
      new_spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
  spdy::SpdySerializedFrame wrapped_rst(
      spdy_util_.ConstructWrappedSpdyFrame(rst, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_rst, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      MockRead(ASYNC, ERR_IO_PENDING, 6),
      MockRead(ASYNC, 0, 7),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_origin->host_and_port =
      HostPortPair("www.example.org", 443);

  SSLSocketDataProvider ssl3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl3.cert_request_info = cert_request_info_origin;
  ssl3.expected_send_client_cert = false;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans.GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_FALSE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port,
            HostPortPair("www.example.org", 443));
}

// Verifies that a session which races and wins against the owning transaction
// (completing prior to host resolution), doesn't fail the transaction.
// Regression test for crbug.com/334413.
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure SPDY proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  NetLogWithSource net_log_with_source =
      NetLogWithSource::Make(NetLogSourceType::NONE);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Fetch http://www.example.org/ via SPDY through the SPDY proxy.
  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Stall the hostname resolution begun by the transaction.
  session_deps_.host_resolver->set_ondemand_mode(true);

  int rv = trans.Start(&request, callback1.callback(), net_log_with_source);
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Race a session to the proxy, which completes first.
  session_deps_.host_resolver->set_ondemand_mode(false);
  SpdySessionKey key(HostPortPair("proxy", 70), PRIVACY_MODE_DISABLED,
                     ProxyChain::Direct(), SessionUsage::kProxy, SocketTag(),
                     NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
                     /*disable_cert_verification_network_fetches=*/true);
  base::WeakPtr<SpdySession> spdy_session =
      CreateSpdySession(session.get(), key, net_log_with_source);

  // Unstall the resolution begun by the transaction.
  session_deps_.host_resolver->set_ondemand_mode(true);
  session_deps_.host_resolver->ResolveAllPending();

  EXPECT_FALSE(callback1.have_result());
  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);
}

// Test a SPDY GET through an HTTPS proxy that uses proxy auth.
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // The first request will be a bare GET, the second request will be a
  // GET with a Proxy-Authorization header.
  spdy_util_.set_default_url(request.url);
  spdy::SpdySerializedFrame req_get(spdy_util_.ConstructSpdyGet(
      base::span<const std::string_view>(), 1, LOWEST));
  spdy_util_.UpdateWithStreamDestruction(1);
  const std::string_view kExtraAuthorizationHeaders[] = {"proxy-authorization",
                                                         "Basic Zm9vOmJhcg=="};
  spdy::SpdySerializedFrame req_get_authorization(
      spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders, 3, LOWEST));
  MockWrite spdy_writes[] = {
      CreateMockWrite(req_get, 0),
      CreateMockWrite(req_get_authorization, 3),
  };

  // The first response is a 407 proxy authentication challenge, and the second
  // response will be a 200 response since the second request includes a valid
  // Authorization header.
  const std::string_view kExtraAuthenticationHeaders[] = {
      "proxy-authenticate", "Basic realm=\"MyRealm1\""};
  spdy::SpdySerializedFrame resp_authentication(
      spdy_util_.ConstructSpdyReplyError("407", kExtraAuthenticationHeaders,
                                         1));
  spdy::SpdySerializedFrame body_authentication(
      spdy_util_.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame resp_data(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame body_data(
      spdy_util_.ConstructSpdyDataFrame(3, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp_authentication, 1),
      CreateMockRead(body_authentication, 2, SYNCHRONOUS),
      CreateMockRead(resp_data, 4),
      CreateMockRead(body_data, 5),
      MockRead(ASYNC, 0, 6),
  };

  SequencedSocketData data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* const response = trans.GetResponseInfo();

  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* const response_restart = trans.GetResponseInfo();

  ASSERT_TRUE(response_restart);
  ASSERT_TRUE(response_restart->headers);
  EXPECT_EQ(200, response_restart->headers->response_code());
  // The password prompt info should not be set.
  EXPECT_FALSE(response_restart->auth_challenge.has_value());
}

// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server
// (SPDY -> HTTPS).
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  // Fetch https://www.example.org/ via HTTP/1.x.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util_.ConstructSpdyDataFrame(1, kGet, false));
  spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util_.ConstructSpdyDataFrame(1, kResp, false));
  const char kRespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util_.ConstructSpdyDataFrame(1, kRespData, false));

  MockWrite spdy_writes[] = {
      CreateMockWrite(connect, 0),
      CreateMockWrite(wrapped_get, 2),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(conn_resp, 1, ASYNC),
      CreateMockRead(wrapped_get_resp, 3, ASYNC),
      CreateMockRead(wrapped_body, 4, ASYNC),
      MockRead(ASYNC, 0, 5),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kRespData, response_data);
}

// Test a SPDY CONNECT through two HTTPS (SPDY) proxies to an HTTPS (non-SPDY)
// server (SPDY -> SPDY -> HTTPS).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySpdyConnectHttps) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:443 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // CONNECT is calculated correctly.
  SpdyTestUtil new_spdy_util;
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  // Fetch https://www.example.org/ via HTTP/1.x.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));

  const char kRespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      new_spdy_util.ConstructSpdyDataFrame(1, kRespData, false));
  spdy::SpdySerializedFrame wrapped_wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_wrapped_get, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
      CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
      MockRead(ASYNC, 0, 8),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kRespData, response_data);
}

// Test that a backup job is not created for an HTTPS (non-SPDY) request through
// two HTTPS (SPDY) proxies (SPDY -> SPDY -> HTTPS) when the second CONNECT
// request takes longer than `net::ClientSocketPool::kMaxConnectRetryIntervalMs`
// to complete.
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxySpdyConnectHttpsNoBackupJob) {
  bool connect_backup_jobs_enabled =
      TransportClientSocketPool::connect_backup_jobs_enabled();
  TransportClientSocketPool::set_connect_backup_jobs_enabled(true);
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.test/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.test:443 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // CONNECT is calculated correctly.
  SpdyTestUtil new_spdy_util;
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.test", 443)));

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  // Fetch https://www.example.test/ via HTTP/1.x.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.test\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n"
      "1234567890";
  spdy::SpdySerializedFrame wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_wrapped_get, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // Delay this read to simulate a slow connection and trigger the backup
      // job.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
      // Note: We leave the socket open here instead of closing it to avoid
      // request failures possibly related to crbug.com/41180906.
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();

  // Advance the clock to attempt to trigger the backup job. No backup job
  // should be created since the `ConnectJob::HasEstablishedConnection()` call
  // in `TransportClientSocketPool::Group::OnBackupJobTimerFired()` will return
  // true.
  FastForwardBy(
      base::Milliseconds(net::ClientSocketPool::kMaxConnectRetryIntervalMs));

  spdy_data.Resume();

  ASSERT_THAT(callback1.GetResult(rv), IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("1234567890", response_data);

  spdy_data.ExpectAllReadDataConsumed();
  spdy_data.ExpectAllWriteDataConsumed();

  TransportClientSocketPool::set_connect_backup_jobs_enabled(
      connect_backup_jobs_enabled);
}

// Test that a backup job is not created for an HTTPS (non-SPDY) request through
// two HTTPS (SPDY) proxies (SPDY -> SPDY -> HTTPS) when the second CONNECT
// request takes longer than `net::ClientSocketPool::kMaxConnectRetryIntervalMs`
// to complete when using an existing socket to the second proxy. This tests the
// fix for crbug.com/448445046.
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxySpdyConnectHttpsNoBackupJobUsingExistingSocket) {
  bool connect_backup_jobs_enabled =
      TransportClientSocketPool::connect_backup_jobs_enabled();
  TransportClientSocketPool::set_connect_backup_jobs_enabled(true);
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.test/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.test:443 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // CONNECT is calculated correctly.
  SpdyTestUtil new_spdy_util;
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.test", 443)));

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));

  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  // Fetch https://www.example.test/ via HTTP/1.x.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.test\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n"
      "1234567890";
  spdy::SpdySerializedFrame wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));

  // CONNECT to www.example2.test:443 via SPDY for the second request.
  spdy::SpdySerializedFrame second_endpoint_connect(
      new_spdy_util.ConstructSpdyConnect(
          base::span<const std::string_view>(), 3,
          HttpProxyConnectJob::kH2QuicTunnelPriority,
          HostPortPair("www.example2.test", 443)));

  spdy::SpdySerializedFrame second_wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(second_endpoint_connect, 1));

  spdy::SpdySerializedFrame second_endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          3));
  spdy::SpdySerializedFrame second_wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(second_endpoint_connect_resp, 1));

  // fetch https://www.example2.test/ via HTTP.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet2[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example2.test\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame second_wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(3, kGet2, false));
  spdy::SpdySerializedFrame second_wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(second_wrapped_get, 1));

  const char kResp2[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n"
      "0987654321";
  spdy::SpdySerializedFrame second_wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(3, kResp2, false));
  spdy::SpdySerializedFrame second_wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(second_wrapped_get_resp, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_wrapped_get, 5),
      CreateMockWrite(second_wrapped_endpoint_connect, 7),
      CreateMockWrite(second_wrapped_wrapped_get, 10),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // causing the stream to be reset with HTTP2_PROTOCOL_ERROR.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
      // Delay this read to simulate a slow connection and trigger the backup
      // job.
      MockRead(ASYNC, ERR_IO_PENDING, 8),
      CreateMockRead(second_wrapped_endpoint_connect_resp, 9, ASYNC),
      CreateMockRead(second_wrapped_wrapped_get_resp, 11, ASYNC),
      // Note: We leave the socket open here instead of closing it to avoid
      // request failures possibly related to crbug.com/41180906.
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 12),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
  // For the connection to the second endpoint:
  SSLSocketDataProvider ssl4(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  ASSERT_THAT(callback1.GetResult(rv), IsOk());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("1234567890", response_data);

  // Make a second request to a different origin.
  request.url = GURL("https://www.example2.test/");
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback2;
  rv = trans2.Start(&request, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();

  // Advance the clock to attempt to trigger the backup job. No backup job
  // should be created since the `ConnectJob::HasEstablishedConnection()` call
  // in `TransportClientSocketPool::Group::OnBackupJobTimerFired()` will return
  // true.
  FastForwardBy(
      base::Milliseconds(net::ClientSocketPool::kMaxConnectRetryIntervalMs));
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  ASSERT_THAT(callback2.GetResult(rv), IsOk());

  std::string response_data2;
  ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
  EXPECT_EQ("0987654321", response_data2);

  spdy_data.ExpectAllReadDataConsumed();
  spdy_data.ExpectAllWriteDataConsumed();

  TransportClientSocketPool::set_connect_backup_jobs_enabled(
      connect_backup_jobs_enabled);
}

// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server (SPDY -> SPDY).
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
  SpdyTestUtil spdy_util_wrapped(/*use_priority_header=*/true);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  // Fetch https://www.example.org/ via SPDY.
  const char kMyUrl[] = "https://www.example.org/";
  spdy::SpdySerializedFrame get(
      spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(get, 1));
  spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame get_resp(spdy_util_wrapped.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
  spdy::SpdySerializedFrame body(
      spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(body, 1));
  spdy::SpdySerializedFrame window_update_get_resp(
      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
  spdy::SpdySerializedFrame window_update_body(
      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));

  MockWrite spdy_writes[] = {
      CreateMockWrite(connect, 0),
      CreateMockWrite(wrapped_get, 2),
      CreateMockWrite(window_update_get_resp, 6),
      CreateMockWrite(window_update_body, 7),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(conn_resp, 1, ASYNC),
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_get_resp, 4, ASYNC),
      CreateMockRead(wrapped_body, 5, ASYNC),
      MockRead(ASYNC, 0, 8),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Allow the SpdyProxyClientSocket's write callback to complete.
  base::RunLoop().RunUntilIdle();
  // Now allow the read of the response to complete.
  spdy_data.Resume();
  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);
}

// Test a SPDY CONNECT for an HTTPS (non-SPDY) endpoint through an HTTPS
// (non-SPDY) proxy and HTTPS (SPDY) proxy chain (HTTPS -> SPDY -> HTTPS).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyMixedConnectSpdy) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to proxy2.test:71 via HTTP.
  std::string_view kProxy2Connect =
      "CONNECT proxy2.test:71 HTTP/1.1\r\n"
      "Host: proxy2.test:71\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n\r\n";

  std::string_view kProxy2ConnectResp =
      "HTTP/1.1 200 Connection Established\r\n\r\n";

  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame endpoint_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // Fetch https://www.example.org/ via HTTP/1.x.
  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util_.ConstructSpdyDataFrame(1, kGet, false));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util_.ConstructSpdyDataFrame(1, kResp, false));

  const char kRespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util_.ConstructSpdyDataFrame(1, kRespData, false));

  MockWrite socket_writes[] = {
      MockWrite(ASYNC, 0, kProxy2Connect),
      CreateMockWrite(endpoint_connect, 2),
      CreateMockWrite(wrapped_get, 4),
  };

  MockRead socket_reads[] = {
      MockRead(ASYNC, 1, kProxy2ConnectResp),
      CreateMockRead(endpoint_connect_resp, 3, ASYNC),
      CreateMockRead(wrapped_get_resp, 5, ASYNC),
      CreateMockRead(wrapped_body, 6, ASYNC),
      MockRead(ASYNC, 0, 7),
  };

  SequencedSocketData socket_data(socket_reads, socket_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&socket_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kRespData, response_data);
}

// Test an HTTP CONNECT for an HTTPS (non-SPDY) endpoint through an HTTPS (SPDY)
// proxy and HTTPS (non-SPDY) proxy chain (SPDY -> HTTPS -> HTTPS).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyMixedConnectHttps) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:443 via HTTPS.
  const char kEndpointConnect[] =
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n\r\n";

  const char kEndpointConnectResp[] =
      "HTTP/1.1 200 Connection Established\r\n\r\n";

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructSpdyDataFrame(1, kEndpointConnect, false));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructSpdyDataFrame(1, kEndpointConnectResp, false));

  // Fetch https://www.example.org/ via HTTP/1.x.
  // Since this request will go over the SPDY tunnel, it needs to be wrapped as
  // well.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util_.ConstructSpdyDataFrame(1, kGet, false));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util_.ConstructSpdyDataFrame(1, kResp, false));

  const char kRespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util_.ConstructSpdyDataFrame(1, kRespData, false));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_get, 4),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      CreateMockRead(wrapped_endpoint_connect_resp, 3, ASYNC),
      CreateMockRead(wrapped_get_resp, 5, ASYNC),
      CreateMockRead(wrapped_body, 6, ASYNC),
      MockRead(ASYNC, 0, 7),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ(kRespData, response_data);
}

// Test a SPDY CONNECT failure through an HTTPS (SPDY) proxy
// (SPDY -> HTTPS/SPDY).
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));

  MockWrite spdy_writes[] = {
      CreateMockWrite(connect, 0),
      CreateMockWrite(rst, 2),
  };

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
  MockRead spdy_reads[] = {
      CreateMockRead(resp, 1, ASYNC),
      // Pause instead of triggering a connection close so that it's more clear
      // which action is causing the tunnel error (the endpoint connect error
      // above).
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      MockRead(ASYNC, 0, 4),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));

  // TODO(juliatuttle): Anything else to check here?
}

// Test a SPDY CONNECT failure through two HTTPS (SPDY) proxies where the
// connection to the first proxy fails (SPDY -> HTTPS/SPDY -> HTTPS/SPDY).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxySpdyConnectFirstProxyFailure) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));
  spdy::SpdySerializedFrame proxy2_connect_error_resp(
      spdy_util_.ConstructSpdyReplyError(1));

  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(rst, 2),
  };
  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_error_resp, 1, ASYNC),
      // Pause instead of triggering a connection close so that it's more clear
      // which action is causing the tunnel error (the endpoint connect error
      // above).
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      MockRead(ASYNC, 0, 4),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
}

// Test a SPDY CONNECT failure through two HTTPS (SPDY) proxies where the
// connection to the second proxy fails (SPDY -> SPDY -> HTTPS/SPDY).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxySpdyConnectSecondProxyFailure) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          /*resolver_factory=*/nullptr,
          /*host_resolver_for_override_rules=*/nullptr,
          /*net_log=*/nullptr, /*quick_check_enabled=*/true);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // request is calculated correctly.
  SpdyTestUtil new_spdy_util;
  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame rst(
      new_spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructSpdyDataFrame(1, endpoint_connect, false));
  spdy::SpdySerializedFrame wrapped_rst(
      spdy_util_.ConstructSpdyDataFrame(1, rst, false));

  spdy::SpdySerializedFrame endpoint_connect_error_resp(
      new_spdy_util.ConstructSpdyReplyError(1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_error_resp(
      spdy_util_.ConstructSpdyDataFrame(1, endpoint_connect_error_resp, false));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_rst, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_error_resp, 4, ASYNC),
      // Pause instead of triggering a connection close so that it's more clear
      // which action is causing the tunnel error (the endpoint connect error
      // above).
      MockRead(ASYNC, ERR_IO_PENDING, 6),
      MockRead(ASYNC, 0, 7),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
}

// This method creates a tunnel using `chain1`, proxies an HTTP GET request
// through it to ensure that it has been created successfully, and then creates
// another tunnel using `chain2` to check whether a new socket is used for it.
// This is used to test that no unexpected socket reuse occurs between different
// proxy chains.
void HttpNetworkTransactionTestBase::HttpsNestedProxyNoSocketReuseHelper(
    const ProxyChain& chain1,
    const ProxyChain& chain2) {
  ASSERT_NE(chain1, chain2);

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(chain1);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  std::vector<SSLSocketDataProvider> ssl_socket_data_providers;
  std::vector<std::string> connects;
  // Allocate enough space in each of these so that the address of each entry
  // will not change after insertion.
  ssl_socket_data_providers.reserve(chain1.length() + chain2.length());
  connects.reserve(chain1.length() - 1 + chain2.length() - 1);

  std::vector<MockWrite> data_writes1;
  std::vector<MockRead> data_reads1;

  for (size_t proxy_index = 1; proxy_index < chain1.length(); ++proxy_index) {
    const auto& proxy_host_port_pair_string =
        chain1.GetProxyServer(proxy_index).host_port_pair().ToString();
    connects.push_back(
        base::StringPrintf("CONNECT %s HTTP/1.1\r\n"
                           "Host: %s\r\n"
                           "Proxy-Connection: keep-alive\r\n"
                           "User-Agent: test-ua\r\n\r\n",
                           proxy_host_port_pair_string.c_str(),
                           proxy_host_port_pair_string.c_str()));
    data_writes1.emplace_back(connects.back());
    data_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  }

  if (chain1.is_multi_proxy()) {
    // Since this is a multi-proxy chain, CONNECT to the endpoint.
    data_writes1.emplace_back(
        "CONNECT www.example.org:80 HTTP/1.1\r\n"
        "Host: www.example.org:80\r\n"
        "Proxy-Connection: keep-alive\r\n"
        "User-Agent: test-ua\r\n\r\n");
    data_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");

    // Make the request to the endpoint.
    data_writes1.emplace_back(
        "GET / HTTP/1.1\r\n"
        "Host: www.example.org\r\n"
        "Connection: keep-alive\r\n\r\n");
  } else {
    // For a single-proxy chain, use GET.
    data_writes1.emplace_back(
        "GET http://www.example.org/ HTTP/1.1\r\n"
        "Host: www.example.org\r\n"
        "Proxy-Connection: keep-alive\r\n"
        "User-Agent: test-ua\r\n\r\n");
  }

  data_reads1.emplace_back("HTTP/1.1 200 OK\r\n");
  data_reads1.emplace_back(SYNCHRONOUS, OK);

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  for (size_t proxy_index = 0; proxy_index < chain1.length(); ++proxy_index) {
    ssl_socket_data_providers.emplace_back(ASYNC, OK);
    session_deps_.socket_factory->AddSSLSocketDataProvider(
        &ssl_socket_data_providers.back());
  }

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(chain1, response->proxy_chain);

  // Now use the second proxy chain. We expect that it will use a new
  // socket, so to test this we will create a new socket data provider and
  // expect that this gets used instead of the one created above for the
  // first transaction.
  proxy_delegate->set_proxy_chain(chain2);

  std::vector<MockWrite> data_writes2;
  std::vector<MockRead> data_reads2;

  for (size_t proxy_index = 1; proxy_index < chain2.length(); ++proxy_index) {
    const auto& proxy_host_port_pair_string =
        chain2.GetProxyServer(proxy_index).host_port_pair().ToString();
    connects.push_back(
        base::StringPrintf("CONNECT %s HTTP/1.1\r\n"
                           "Host: %s\r\n"
                           "Proxy-Connection: keep-alive\r\n"
                           "User-Agent: test-ua\r\n\r\n",
                           proxy_host_port_pair_string.c_str(),
                           proxy_host_port_pair_string.c_str()));
    data_writes2.emplace_back(connects.back());
    data_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  }

  if (chain2.is_multi_proxy()) {
    // Since this is a multi-proxy chain, CONNECT to the endpoint.
    data_writes2.emplace_back(
        "CONNECT www.example.org:80 HTTP/1.1\r\n"
        "Host: www.example.org:80\r\n"
        "Proxy-Connection: keep-alive\r\n"
        "User-Agent: test-ua\r\n\r\n");
    data_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");

    // Make the request to the endpoint.
    data_writes2.emplace_back(
        "GET / HTTP/1.1\r\n"
        "Host: www.example.org\r\n"
        "Connection: keep-alive\r\n\r\n");
  } else {
    // For a single-proxy chain, use GET.
    data_writes2.emplace_back(
        "GET http://www.example.org/ HTTP/1.1\r\n"
        "Host: www.example.org\r\n"
        "Proxy-Connection: keep-alive\r\n\r\n");
  }
  data_reads2.emplace_back("HTTP/1.1 200 OK\r\n");
  data_reads2.emplace_back(SYNCHRONOUS, OK);

  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  for (size_t proxy_index = 0; proxy_index < chain2.length(); ++proxy_index) {
    ssl_socket_data_providers.emplace_back(ASYNC, OK);
    session_deps_.socket_factory->AddSSLSocketDataProvider(
        &ssl_socket_data_providers.back());
  }

  TestCompletionCallback callback2;
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(chain2, response->proxy_chain);

  EXPECT_TRUE(data1.AllReadDataConsumed());
  EXPECT_TRUE(data1.AllWriteDataConsumed());
  EXPECT_TRUE(data2.AllReadDataConsumed());
  EXPECT_TRUE(data2.AllWriteDataConsumed());
}

// If we have established a proxy tunnel through a two hop proxy and then
// establish a tunnel through only the first hop, ensure that socket re-use does
// not occur (HTTPS A -> HTTPS B != HTTPS A).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyNoSocketReuseFirstHop) {
  const ProxyChain kFirstHopOnlyChain{{proxy_server_1_}};
  HttpsNestedProxyNoSocketReuseHelper(nested_proxy_chain_, kFirstHopOnlyChain);
}

// If we have established a proxy tunnel through a two hop proxy and then
// establish a tunnel through only the second hop, ensure that socket re-use
// does not occur (HTTPS A -> HTTPS B != HTTPS B).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyNoSocketReuseSecondHop) {
  const ProxyChain kSecondHopOnlyChain{{proxy_server_2_}};

  HttpsNestedProxyNoSocketReuseHelper(nested_proxy_chain_, kSecondHopOnlyChain);
}

// If we have established a proxy tunnel through a two hop proxy and then
// establish a tunnel through the same proxies with the order reversed, ensure
// that socket re-use does not occur (HTTPS A -> HTTPS B != HTTPS B -> HTTPS A).
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyNoSocketReuseReversedChain) {
  const ProxyChain kReversedChain =
      ProxyChain::ForIpProtection({{proxy_server_2_, proxy_server_1_}});

  HttpsNestedProxyNoSocketReuseHelper(nested_proxy_chain_, kReversedChain);
}

// If we have established a proxy tunnel through a two hop proxy using SPDY,
// ensure that socket reuse occurs as expected. Specifically, for:
// (SPDY A -> SPDY B -> HTTPS Endpoint),
// (SPDY A -> HTTPS Endpoint) should send the endpoint CONNECT to
// the existing SPDY A socket but for:
// (SPDY B -> HTTPS Endpoint), the SPDY A -> SPDY B socket should not be used.
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxySpdySocketReuseDifferentChains) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  const ProxyChain kFirstHopOnlyChain =
      ProxyChain::ForIpProtection({proxy_server_1_});
  const ProxyChain kSecondHopOnlyChain =
      ProxyChain::ForIpProtection({proxy_server_2_});

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(nested_proxy_chain_);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:443 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // CONNECT is calculated correctly.
  SpdyTestUtil new_spdy_util;
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  // Fetch https://www.example.org/ via HTTP/1.x.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));

  const char kTrans1RespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      new_spdy_util.ConstructSpdyDataFrame(1, kTrans1RespData, false));
  spdy::SpdySerializedFrame wrapped_wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));

  const char kTrans2RespData[] = "abcdefghij";
  spdy::SpdySerializedFrame second_trans_endpoint_connect(
      spdy_util_.ConstructSpdyConnect(
          base::span<const std::string_view>(), 3,
          HttpProxyConnectJob::kH2QuicTunnelPriority,
          HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame second_trans_endpoint_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       3));
  spdy::SpdySerializedFrame second_trans_wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(3, kGet, false));
  spdy::SpdySerializedFrame second_trans_wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(3, kResp, false));
  spdy::SpdySerializedFrame second_trans_wrapped_body(
      new_spdy_util.ConstructSpdyDataFrame(3, kTrans2RespData, false));

  MockWrite spdy_writes1[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_wrapped_get, 5),
      // For the second transaction, we expect the endpoint connect on this
      // socket.
      CreateMockWrite(second_trans_endpoint_connect, 8),
      CreateMockWrite(second_trans_wrapped_get, 10),

  };

  MockRead spdy_reads1[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
      CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
      CreateMockRead(second_trans_endpoint_connect_resp, 9),
      CreateMockRead(second_trans_wrapped_get_resp, 11, ASYNC),
      CreateMockRead(second_trans_wrapped_body, 12, ASYNC),
      // Pause reads so that the socket will remain open (so we can see whether
      // it gets reused below).
      MockRead(ASYNC, ERR_IO_PENDING, 13),
      MockRead(ASYNC, 0, 14),
  };

  SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback1;
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data1.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data1.Resume();

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_EQ(nested_proxy_chain_, response->proxy_chain);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kTrans1RespData, response_data);

  // Now use a proxy chain consisting of only the first proxy. We expect that it
  // will re-use the existing socket to the proxy, so we will look for the reads
  // and writes associated with this in the same SocketDataProvider used by the
  // first transaction.
  proxy_delegate->set_proxy_chain(kFirstHopOnlyChain);

  SSLSocketDataProvider ssl4(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);

  TestCompletionCallback callback2;
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_EQ(kFirstHopOnlyChain, response->proxy_chain);

  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ(kTrans2RespData, response_data);

  // Now use a proxy chain consisting of only the second proxy. We expect that
  // it will not re-use the existing socket to the first proxy, so we will look
  // for the reads and writes associated with this in a new SocketDataProvider.
  proxy_delegate->set_proxy_chain(kSecondHopOnlyChain);

  // CONNECT to www.example.org:443 via SPDY.
  SpdyTestUtil third_spdy_util;
  spdy::SpdySerializedFrame third_trans_endpoint_connect(
      third_spdy_util.ConstructSpdyConnect(
          base::span<const std::string_view>(), 1,
          HttpProxyConnectJob::kH2QuicTunnelPriority,
          HostPortPair("www.example.org", 443)));

  spdy::SpdySerializedFrame third_trans_endpoint_connect_resp(
      third_spdy_util.ConstructSpdyGetReply(
          base::span<const std::string_view>(), 1));

  // Fetch https://www.example.org/ via HTTP/1.x.
  spdy::SpdySerializedFrame third_trans_wrapped_get(
      third_spdy_util.ConstructSpdyDataFrame(1, kGet, false));

  spdy::SpdySerializedFrame third_trans_wrapped_get_resp(
      third_spdy_util.ConstructSpdyDataFrame(1, kResp, false));

  const char kTrans3RespData[] = "!@#$%^&*()";
  spdy::SpdySerializedFrame third_trans_wrapped_body(
      third_spdy_util.ConstructSpdyDataFrame(1, kTrans3RespData, false));

  MockWrite spdy_writes2[] = {
      CreateMockWrite(third_trans_endpoint_connect, 0),
      CreateMockWrite(third_trans_wrapped_get, 2),
  };

  MockRead spdy_reads2[] = {
      CreateMockRead(third_trans_endpoint_connect_resp, 1, ASYNC),
      CreateMockRead(third_trans_wrapped_get_resp, 3, ASYNC),
      CreateMockRead(third_trans_wrapped_body, 4, ASYNC),
      MockRead(ASYNC, 0, 5),
  };

  SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);

  SSLSocketDataProvider ssl5(ASYNC, OK);
  ssl5.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl5);

  SSLSocketDataProvider ssl6(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl6);

  TestCompletionCallback callback3;
  HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());

  rv = trans3.Start(&request, callback3.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback3.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  response = trans3.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_EQ(kSecondHopOnlyChain, response->proxy_chain);

  ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
  EXPECT_EQ(kTrans3RespData, response_data);

  EXPECT_EQ(proxy_delegate->on_before_tunnel_request_call_count(), 4u);

  // Wait for the socket we left open to close so all data is consumed.
  spdy_data1.RunUntilPaused();
  spdy_data1.Resume();
  EXPECT_TRUE(spdy_data1.AllReadDataConsumed());
  EXPECT_TRUE(spdy_data1.AllWriteDataConsumed());
  EXPECT_TRUE(spdy_data2.AllReadDataConsumed());
  EXPECT_TRUE(spdy_data2.AllWriteDataConsumed());
}

// If we have established a proxy tunnel through a two-hop proxy using SPDY,
// ensure that socket reuse occurs as expected for two different requests (test
// that there is only one CONNECT for the second proxy in the chain).
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxySpdySocketReuseDifferentRequests) {
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(nested_proxy_chain_);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:443 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // CONNECT is calculated correctly.
  SpdyTestUtil new_spdy_util;
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  // Since the first request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  // Fetch https://www.example.org/ via HTTP/1.x.
  // Since the first request will go over two tunnels, it needs to be
  // double-wrapped.
  const char kGet1[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      new_spdy_util.ConstructSpdyDataFrame(1, kGet1, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp(
      new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
  spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));

  const char kTrans1RespData[] = "1234567890";
  spdy::SpdySerializedFrame wrapped_body(
      new_spdy_util.ConstructSpdyDataFrame(1, kTrans1RespData, false));
  spdy::SpdySerializedFrame wrapped_wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));

  // CONNECT to www.example.com:443 via SPDY.
  spdy::SpdySerializedFrame second_trans_endpoint_connect(
      new_spdy_util.ConstructSpdyConnect(
          base::span<const std::string_view>(), 3,
          HttpProxyConnectJob::kH2QuicTunnelPriority,
          HostPortPair("www.example.com", 443)));
  spdy::SpdySerializedFrame second_trans_wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(second_trans_endpoint_connect, 1));

  spdy::SpdySerializedFrame second_trans_endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          3));
  spdy::SpdySerializedFrame second_trans_wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(second_trans_endpoint_connect_resp,
                                           1));

  // Fetch https://www.example.com/2 via HTTP/1.x.
  const char kGet2[] =
      "GET /2 HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Connection: keep-alive\r\n\r\n";
  SpdyTestUtil second_trans_spdy_util;
  spdy::SpdySerializedFrame second_trans_wrapped_get(
      second_trans_spdy_util.ConstructSpdyDataFrame(3, kGet2, false));
  spdy::SpdySerializedFrame second_trans_wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(second_trans_wrapped_get, 1));

  spdy::SpdySerializedFrame second_trans_wrapped_get_resp(
      second_trans_spdy_util.ConstructSpdyDataFrame(3, kResp, false));
  spdy::SpdySerializedFrame second_trans_wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(second_trans_wrapped_get_resp, 1));

  const char kTrans2RespData[] = "abcdefghij";
  spdy::SpdySerializedFrame second_trans_wrapped_body(
      second_trans_spdy_util.ConstructSpdyDataFrame(3, kTrans2RespData, false));
  spdy::SpdySerializedFrame second_trans_wrapped_wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(second_trans_wrapped_body, 1));

  MockWrite spdy_writes1[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_wrapped_get, 5),
      // For the second transaction, we expect the endpoint connect on this
      // socket with no duplicated proxy2 CONNECT.
      CreateMockWrite(second_trans_wrapped_endpoint_connect, 8),
      CreateMockWrite(second_trans_wrapped_wrapped_get, 11),
  };

  MockRead spdy_reads1[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
      CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 9),
      CreateMockRead(second_trans_wrapped_endpoint_connect_resp, 10),
      CreateMockRead(second_trans_wrapped_wrapped_get_resp, 12),
      CreateMockRead(second_trans_wrapped_wrapped_body, 13),
      MockRead(ASYNC, 0, 14),
  };

  SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback1;
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data1.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data1.Resume();

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_EQ(nested_proxy_chain_, response->proxy_chain);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kTrans1RespData, response_data);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.example.com/2");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  SSLSocketDataProvider ssl4(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);

  TestCompletionCallback callback2;
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data1.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data1.Resume();

  rv = callback2.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_EQ(nested_proxy_chain_, response->proxy_chain);

  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ(kTrans2RespData, response_data);
}

// Ensure that socket reuse occurs after an error from a SPDY connection through
// the nested proxy.
TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySpdySocketReuseAfterError) {
  ProxyList proxy_list;
  proxy_list.AddProxyChain(nested_proxy_chain_);
  ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to proxy2.test:71 via SPDY.
  spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      proxy_server_2_.host_port_pair()));

  spdy::SpdySerializedFrame proxy2_connect_resp(
      spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                       1));

  // CONNECT to www.example.org:443 via SPDY.
  // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
  // CONNECT is calculated correctly.
  SpdyTestUtil new_spdy_util;
  spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));

  // Since this request and response are sent over the tunnel established
  // previously, from a socket-perspective these need to be wrapped as data
  // frames.
  spdy::SpdySerializedFrame wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));

  spdy::SpdySerializedFrame endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
  spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));

  spdy::SpdySerializedFrame rst(
      new_spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
  spdy::SpdySerializedFrame wrapped_rst(
      spdy_util_.ConstructWrappedSpdyFrame(rst, 1));

  new_spdy_util.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame attempt2_endpoint_connect(
      new_spdy_util.ConstructSpdyConnect(
          base::span<const std::string_view>(), 3,
          HttpProxyConnectJob::kH2QuicTunnelPriority,
          HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame attempt2_wrapped_endpoint_connect(
      spdy_util_.ConstructWrappedSpdyFrame(attempt2_endpoint_connect, 1));

  spdy::SpdySerializedFrame attempt2_endpoint_connect_resp(
      new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          3));
  spdy::SpdySerializedFrame attempt2_wrapped_endpoint_connect_resp(
      spdy_util_.ConstructWrappedSpdyFrame(attempt2_endpoint_connect_resp, 1));

  // Fetch https://www.example.org/ via HTTPS/1.x.
  // Since this request will go over two tunnels, it needs to be double-wrapped.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  SpdyTestUtil attempt2_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame attempt2_wrapped_get(
      attempt2_spdy_util.ConstructSpdyDataFrame(3, kGet, false));
  spdy::SpdySerializedFrame attempt2_wrapped_wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(attempt2_wrapped_get, 1));

  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 10\r\n\r\n";
  spdy::SpdySerializedFrame attempt2_wrapped_get_resp(
      attempt2_spdy_util.ConstructSpdyDataFrame(3, kResp, false));
  spdy::SpdySerializedFrame attempt2_wrapped_wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(attempt2_wrapped_get_resp, 1));

  const char kRespData[] = "1234567890";
  spdy::SpdySerializedFrame attempt2_wrapped_body(
      attempt2_spdy_util.ConstructSpdyDataFrame(3, kRespData, false));
  spdy::SpdySerializedFrame attempt2_wrapped_wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(attempt2_wrapped_body, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(proxy2_connect, 0),
      CreateMockWrite(wrapped_endpoint_connect, 2),
      CreateMockWrite(wrapped_rst, 5),
      CreateMockWrite(attempt2_wrapped_endpoint_connect, 6),
      CreateMockWrite(attempt2_wrapped_wrapped_get, 9),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(proxy2_connect_resp, 1, ASYNC),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
      // The SSL socket error should occur here.
      MockRead(ASYNC, ERR_IO_PENDING, 7),
      CreateMockRead(attempt2_wrapped_endpoint_connect_resp, 8, ASYNC),
      CreateMockRead(attempt2_wrapped_wrapped_get_resp, 10, ASYNC),
      CreateMockRead(attempt2_wrapped_wrapped_body, 11, ASYNC),
      MockRead(ASYNC, 0, 12),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_proxy->host_and_port = proxy_server_1_.host_port_pair();

  SSLSocketDataProvider ssl3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl3.cert_request_info = cert_request_info_proxy;
  ssl3.expected_send_client_cert = false;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));

  SSLSocketDataProvider ssl4(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);

  TestCompletionCallback callback2;

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request1, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback2.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ(kRespData, response_data);
}

// Test the case where a proxied H2 session doesn't exist when an auth challenge
// is observed, but does exist by the time auth credentials are provided. In
// this case, auth and SSL are fully negotated on the second request, but then
// the socket is discarded to use the shared session.
TEST_P(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
  ProxyConfig proxy_config;
  proxy_config.set_auto_detect(true);
  proxy_config.set_pac_url(GURL("http://fooproxyurl"));

  CapturingProxyResolver capturing_proxy_resolver;
  capturing_proxy_resolver.set_proxy_chain(
      ProxyChain(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::make_unique<CapturingProxyResolverFactory>(
              &capturing_proxy_resolver),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  const char kMyUrl[] = "https://www.example.org/";
  spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
  spdy::SpdySerializedFrame get_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));

  spdy_util_.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame get2(
      spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
  spdy::SpdySerializedFrame get_resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));

  MockWrite auth_challenge_writes[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      MockWrite(ASYNC, 2,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead auth_challenge_reads[] = {
      MockRead(ASYNC, 1,
               "HTTP/1.1 407 Authentication Required\r\n"
               "Content-Length: 0\r\n"
               "Proxy-Connection: close\r\n"
               "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
  };

  MockWrite spdy_writes[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
      CreateMockWrite(get, 2),
      CreateMockWrite(get2, 5),
  };

  MockRead spdy_reads[] = {
      MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
      CreateMockRead(get_resp, 3, ASYNC),
      CreateMockRead(body, 4, ASYNC),
      CreateMockRead(get_resp2, 6, ASYNC),
      CreateMockRead(body2, 7, ASYNC),

      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
  };

  MockWrite auth_response_writes_discarded_socket[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  MockRead auth_response_reads_discarded_socket[] = {
      MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
  };

  SequencedSocketData auth_challenge1(auth_challenge_reads,
                                      auth_challenge_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);

  SequencedSocketData auth_challenge2(auth_challenge_reads,
                                      auth_challenge_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SequencedSocketData auth_response_discarded_socket(
      auth_response_reads_discarded_socket,
      auth_response_writes_discarded_socket);
  session_deps_.socket_factory->AddSocketDataProvider(
      &auth_response_discarded_socket);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback;
  std::string response_data;

  // Run first request until an auth challenge is observed.
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL(kMyUrl);
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(LOWEST, session.get());
  int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  // Run second request until an auth challenge is observed.
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL(kMyUrl);
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(LOWEST, session.get());
  rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  // Now provide credentials for the first request, and wait for it to complete.
  rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
  rv = callback.GetResult(rv);
  EXPECT_THAT(rv, IsOk());
  response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);

  // Now provide credentials for the second request. It should notice the
  // existing session, and reuse it.
  rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);
}

// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
// HTTPS Proxy to different servers.
TEST_P(HttpNetworkTransactionTest,
       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(
      SpdySessionDependencies::SpdyCreateSession(&session_deps_));

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.org/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));

  // Fetch https://www.example.org/ via HTTP/1.x.
  const char kGet1[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get1(
      spdy_util_.ConstructSpdyDataFrame(1, kGet1, false));
  const char kResp1[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 1\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp1(
      spdy_util_.ConstructSpdyDataFrame(1, kResp1, false));
  spdy::SpdySerializedFrame wrapped_body1(
      spdy_util_.ConstructSpdyDataFrame(1, "1", false));

  // CONNECT to mail.example.org:443 via SPDY.
  quiche::HttpHeaderBlock connect2_block;
  connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
  connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
  connect2_block["user-agent"] = "test-ua";
  spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
      3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
      false));

  spdy::SpdySerializedFrame conn_resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));

  // Fetch https://mail.example.org/ via HTTP/1.x.
  const char kGet2[] =
      "GET / HTTP/1.1\r\n"
      "Host: mail.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get2(
      spdy_util_.ConstructSpdyDataFrame(3, kGet2, false));
  const char kResp2[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 2\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp2(
      spdy_util_.ConstructSpdyDataFrame(3, kResp2, false));
  spdy::SpdySerializedFrame wrapped_body2(
      spdy_util_.ConstructSpdyDataFrame(3, "22", false));

  MockWrite spdy_writes[] = {
      CreateMockWrite(connect1, 0),
      CreateMockWrite(wrapped_get1, 2),
      CreateMockWrite(connect2, 5),
      CreateMockWrite(wrapped_get2, 7),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(conn_resp1, 1, ASYNC),
      CreateMockRead(wrapped_get_resp1, 3, ASYNC),
      CreateMockRead(wrapped_body1, 4, ASYNC),
      CreateMockRead(conn_resp2, 6, ASYNC),
      CreateMockRead(wrapped_get_resp2, 8, ASYNC),
      CreateMockRead(wrapped_body2, 9, ASYNC),
      MockRead(ASYNC, 0, 10),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
  rv = trans.Read(buf.get(), 256, callback.callback());
  EXPECT_EQ(1, callback.GetResult(rv));

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
  // Even though the SPDY connection is reused, a new tunnelled connection has
  // to be created, so the socket's load timing looks like a fresh connection.
  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);

  // The requests should have different IDs, since they each are using their own
  // separate stream.
  EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);

  rv = trans2.Read(buf.get(), 256, callback.callback());
  EXPECT_EQ(2, callback.GetResult(rv));
}

// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
// HTTPS Proxy to the same server.
TEST_P(HttpNetworkTransactionTest,
       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(
      SpdySessionDependencies::SpdyCreateSession(&session_deps_));

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.example.org/2");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // CONNECT to www.example.org:443 via SPDY.
  spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));

  // Fetch https://www.example.org/ via HTTP/1.x.
  const char kGet1[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get1(
      spdy_util_.ConstructSpdyDataFrame(1, kGet1, false));
  const char kResp1[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 1\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp1(
      spdy_util_.ConstructSpdyDataFrame(1, kResp1, false));
  spdy::SpdySerializedFrame wrapped_body1(
      spdy_util_.ConstructSpdyDataFrame(1, "1", false));

  // Fetch https://www.example.org/2 via HTTP/1.x.
  const char kGet2[] =
      "GET /2 HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get2(
      spdy_util_.ConstructSpdyDataFrame(1, kGet2, false));
  const char kResp2[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 2\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get_resp2(
      spdy_util_.ConstructSpdyDataFrame(1, kResp2, false));
  spdy::SpdySerializedFrame wrapped_body2(
      spdy_util_.ConstructSpdyDataFrame(1, "22", false));

  MockWrite spdy_writes[] = {
      CreateMockWrite(connect1, 0),
      CreateMockWrite(wrapped_get1, 2),
      CreateMockWrite(wrapped_get2, 5),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(conn_resp1, 1, ASYNC),
      CreateMockRead(wrapped_get_resp1, 3, ASYNC),
      CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
      CreateMockRead(wrapped_get_resp2, 6, ASYNC),
      CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
      MockRead(ASYNC, 0, 8),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
  EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
  trans.reset();

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
  TestLoadTimingReused(load_timing_info2);

  // The requests should have the same ID.
  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);

  EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
}

// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
// Proxy to different servers.
TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
  // Configure against https proxy server "proxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(
      SpdySessionDependencies::SpdyCreateSession(&session_deps_));

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("http://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("http://mail.example.org/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // http://www.example.org/
  quiche::HttpHeaderBlock headers(
      spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
  spdy::SpdySerializedFrame get1(
      spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
  spdy::SpdySerializedFrame get_resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body1(
      spdy_util_.ConstructSpdyDataFrame(1, "1", true));
  spdy_util_.UpdateWithStreamDestruction(1);

  // http://mail.example.org/
  quiche::HttpHeaderBlock headers2(
      spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
  spdy::SpdySerializedFrame get2(
      spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
  spdy::SpdySerializedFrame get_resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame body2(
      spdy_util_.ConstructSpdyDataFrame(3, "22", true));

  MockWrite spdy_writes[] = {
      CreateMockWrite(get1, 0),
      CreateMockWrite(get2, 3),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(get_resp1, 1, ASYNC),
      CreateMockRead(body1, 2, ASYNC),
      CreateMockRead(get_resp2, 4, ASYNC),
      CreateMockRead(body2, 5, ASYNC),
      MockRead(ASYNC, 0, 6),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
  rv = trans->Read(buf.get(), 256, callback.callback());
  EXPECT_EQ(1, callback.GetResult(rv));
  // Delete the first request, so the second one can reuse the socket.
  trans.reset();

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
  TestLoadTimingReused(load_timing_info2);

  // The requests should have the same ID.
  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);

  rv = trans2.Read(buf.get(), 256, callback.callback());
  EXPECT_EQ(2, callback.GetResult(rv));
}

// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
// direct (non-proxied) request to the proxy server are not pooled, as that
// would break socket pool isolation.
TEST_P(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
  ProxyConfig proxy_config;
  proxy_config.set_auto_detect(true);
  proxy_config.set_pac_url(GURL("http://fooproxyurl"));

  CapturingProxyResolver capturing_proxy_resolver;
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::make_unique<CapturingProxyResolverFactory>(
              &capturing_proxy_resolver),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  SpdyTestUtil spdy_util1(/*use_priority_header=*/true);
  // CONNECT to www.example.org:443 via HTTP/2.
  spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  // Fetch https://www.example.org/ via HTTP/2.
  const char kMyUrl[] = "https://www.example.org/";
  spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(get, 1));
  spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame get_resp(spdy_util1.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
  spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(body, 1));
  spdy::SpdySerializedFrame window_update_get_resp(
      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
  spdy::SpdySerializedFrame window_update_body(
      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));

  MockWrite spdy_writes1[] = {
      CreateMockWrite(connect, 0),
      CreateMockWrite(wrapped_get, 2),
      CreateMockWrite(window_update_get_resp, 6),
      CreateMockWrite(window_update_body, 7),
  };

  MockRead spdy_reads1[] = {
      CreateMockRead(conn_resp, 1, ASYNC),
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_get_resp, 4, ASYNC),
      CreateMockRead(wrapped_body, 5, ASYNC),
      MockRead(ASYNC, 0, 8),
  };

  SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);

  // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
  // a new pipe.
  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req(
      spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
  MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util2.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads2[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };
  SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  ssl3.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback;
  std::string response_data;

  // Make a request using proxy:70 as a HTTP/2 proxy.
  capturing_proxy_resolver.set_proxy_chain(
      ProxyChain(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpNetworkTransaction trans1(LOWEST, session.get());
  int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Allow the SpdyProxyClientSocket's write callback to complete.
  base::RunLoop().RunUntilIdle();
  // Now allow the read of the response to complete.
  spdy_data1.Resume();
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);
  RunUntilIdle();

  // Make a direct HTTP/2 request to proxy:70.
  capturing_proxy_resolver.set_proxy_chain(ProxyChain::Direct());
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://proxy:70/");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(LOWEST, session.get());
  EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
                                              NetLogWithSource())),
              IsOk());
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
}

// Same as above, but reverse request order, since the code to check for an
// existing session is different for tunnels and direct connections.
TEST_P(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
  // Configure against https proxy server "myproxy:80".
  ProxyConfig proxy_config;
  proxy_config.set_auto_detect(true);
  proxy_config.set_pac_url(GURL("http://fooproxyurl"));

  CapturingProxyResolver capturing_proxy_resolver;
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::make_unique<CapturingProxyResolverFactory>(
              &capturing_proxy_resolver),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  // Fetch https://proxy:70/ via HTTP/2.
  SpdyTestUtil spdy_util1(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req(
      spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
  MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util1.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads1[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };
  SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);

  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  // CONNECT to www.example.org:443 via HTTP/2.
  spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  // Fetch https://www.example.org/ via HTTP/2.
  const char kMyUrl[] = "https://www.example.org/";
  spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util_.ConstructWrappedSpdyFrame(get, 1));
  spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame get_resp(spdy_util2.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
  spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util_.ConstructWrappedSpdyFrame(body, 1));
  spdy::SpdySerializedFrame window_update_get_resp(
      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
  spdy::SpdySerializedFrame window_update_body(
      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));

  MockWrite spdy_writes2[] = {
      CreateMockWrite(connect, 0),
      CreateMockWrite(wrapped_get, 2),
      CreateMockWrite(window_update_get_resp, 6),
      CreateMockWrite(window_update_body, 7),
  };

  MockRead spdy_reads2[] = {
      CreateMockRead(conn_resp, 1, ASYNC),
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_get_resp, 4, ASYNC),
      CreateMockRead(wrapped_body, 5, ASYNC),
      MockRead(ASYNC, 0, 8),
  };

  SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  ssl3.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback;
  std::string response_data;

  // Make a direct HTTP/2 request to proxy:70.
  capturing_proxy_resolver.set_proxy_chain(ProxyChain::Direct());
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://proxy:70/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(LOWEST, session.get());
  EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
                                              NetLogWithSource())),
              IsOk());
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  RunUntilIdle();

  // Make a request using proxy:70 as a HTTP/2 proxy.
  capturing_proxy_resolver.set_proxy_chain(
      ProxyChain(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.example.org/");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpNetworkTransaction trans2(LOWEST, session.get());
  int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Allow the SpdyProxyClientSocket's write callback to complete.
  base::RunLoop().RunUntilIdle();
  // Now allow the read of the response to complete.
  spdy_data2.Resume();
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
  ASSERT_TRUE(response2);
  ASSERT_TRUE(response2->headers);
  EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());

  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);
}

// Test the challenge-response-retry sequence through an HTTPS Proxy
TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should use full url
  MockWrite data_writes1[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),

      // After calling trans.RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  // The proxy responds to the GET with a 407, using a persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Proxy-Connection: keep-alive\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
  EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
            response->proxy_chain);

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  load_timing_info = LoadTimingInfo();
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  // Retrying with HTTP AUTH is considered to be reusing a socket.
  TestLoadTimingReused(load_timing_info);

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_FALSE(response->did_use_server_http_auth);
  EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
            response->proxy_chain);

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
}

// Test the challenge-response-retry sequence through an HTTPS Proxy over a
// connection that requires a restart.
TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetryNoKeepAlive) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should use full url
  MockWrite data_writes1[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };

  // The proxy responds to the GET with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Proxy-Connection: close\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),
  };

  MockWrite data_writes2[] = {
      // After calling trans.RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  // One per each proxy connection.
  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
  EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
            response->proxy_chain);

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  load_timing_info = LoadTimingInfo();
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_FALSE(response->did_use_server_http_auth);
  EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
            response->proxy_chain);

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
}

// Test the challenge-response-retry sequence through an HTTPS Proxy over a
// connection that requires a restart, with a proxy change occurring over the
// restart.
TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetryNoKeepAliveChangeProxy) {
  const auto proxy_chain1 = PacResultElementToProxyChain("HTTPS myproxy:70");
  const auto proxy_chain2 = PacResultElementToProxyChain("HTTPS myproxy2:70");

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(proxy_chain1);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should use full url
  MockWrite data_writes1[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };

  // The proxy responds to the GET with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Proxy-Connection: close\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),
  };

  MockWrite data_writes2[] = {
      // After calling trans.RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  // One per each proxy connection.
  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
  EXPECT_EQ(proxy_chain1, response->proxy_chain);

  TestCompletionCallback callback2;

  // Configure against https proxy server "myproxy2:70".
  proxy_delegate->set_proxy_chain(proxy_chain2);

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  load_timing_info = LoadTimingInfo();
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_FALSE(response->did_use_server_http_auth);
  EXPECT_EQ(proxy_chain2, response->proxy_chain);

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
}

// Test the challenge-response-retry sequence through an HTTPS Proxy over a
// connection that requires a restart, with a change to a direct connection
// occurring over the restart.
TEST_P(HttpNetworkTransactionTest,
       HttpsProxyAuthRetryNoKeepAliveChangeToDirect) {
  const auto proxy_chain = PacResultElementToProxyChain("HTTPS myproxy:70");
  const auto direct = ProxyChain::Direct();

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(proxy_chain);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should use full url
  MockWrite data_writes1[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };

  // The proxy responds to the GET with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Proxy-Connection: close\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),
  };

  MockWrite data_writes2[] = {
      // After calling trans.RestartWithAuth(), this is the request we should
      // be issuing.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  // One per each connection.
  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
  EXPECT_EQ(proxy_chain, response->proxy_chain);

  TestCompletionCallback callback2;

  // Configure to use a direct connection.
  proxy_delegate->set_proxy_chain(direct);

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  load_timing_info = LoadTimingInfo();
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_EQ(direct, response->proxy_chain);

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());
}

void HttpNetworkTransactionTestBase::ConnectStatusHelperWithExpectedStatus(
    const MockRead& status,
    int expected_status) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead data_reads[] = {
      status,
      MockRead("Content-Length: 10\r\n\r\n"),
      // No response body because the test stops reading here.
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_EQ(expected_status, rv);
}

void HttpNetworkTransactionTestBase::ConnectStatusHelper(
    const MockRead& status) {
  ConnectStatusHelperWithExpectedStatus(status, ERR_TUNNEL_CONNECTION_FAILED);
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
  ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
  ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
  ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
  ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
  ConnectStatusHelper(
      MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
  ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
  ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
  ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
  ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
  ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
  ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
  ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
  ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
  ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
  ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
  ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
  ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
  ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
  ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
  ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
  ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
  ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
  ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
  ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
  ConnectStatusHelperWithExpectedStatus(
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      ERR_PROXY_AUTH_UNSUPPORTED);
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
  ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
  ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
  ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
  ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
  ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
  ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
  ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
  ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
  ConnectStatusHelper(
      MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
  ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
  ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
  ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
  ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
  ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
  ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
}

TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
  ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
}

// Test the flow when both the proxy server AND origin server require
// authentication. Again, this uses basic auth for both since that is
// the simplest to mock.
TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes1[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 407 Unauthorized\r\n"),
      // Give a couple authenticate options (only the middle one is actually
      // supported).
      MockRead("Proxy-Authenticate: Basic invalid\r\n"),  // Malformed.
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After calling trans.RestartWithAuth() the first time, this is the
  // request we should be issuing -- the final header line contains the
  // proxy's credentials.
  MockWrite data_writes2[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  // Now the proxy server lets the request pass through to origin server.
  // The origin server responds with a 401.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      // Note: We are using the same realm-name as the proxy server. This is
      // completely valid, as realms are unique across hosts.
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 2000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),  // Won't be reached.
  };

  // After calling trans.RestartWithAuth() the second time, we should send
  // the credentials for both the proxy and origin server.
  MockWrite data_writes3[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
  };

  // Lastly we get the desired content.
  MockRead data_reads3[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  StaticSocketDataProvider data3(data_reads3, data_writes3);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback3;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
                             callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
}

// For the NTLM implementation using SSPI, we skip the NTLM tests since we
// can't hook into its internals to cause it to generate predictable NTLM
// authorization headers.
#if defined(NTLM_PORTABLE)
// The NTLM authentication unit tests are based on known test data from the
// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
// flow rather than the implementation of the NTLM protocol. See net/ntlm
// for the implementation and testing of the protocol.
//
// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx

// Enter the correct password and authenticate successfully.
TEST_P(HttpNetworkTransactionTest, NTLMAuthV2) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://server/kids/login.aspx");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Ensure load is not disrupted by flags which suppress behaviour specific
  // to other auth schemes.
  request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;

  HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
      MockGetMSTime, MockGenerateRandom, MockGetHostName);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Generate the NTLM messages based on known test data.
  std::string negotiate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
      std::size(ntlm::test::kExpectedNegotiateMsg)));
  std::string challenge_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
      std::size(ntlm::test::kChallengeMsgFromSpecV2)));
  std::string authenticate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(
          ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
      std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));

  MockWrite data_writes1[] = {
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      // Negotiate and NTLM are often requested together.  However, we only want
      // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
      // the header that requests Negotiate for this test.
      MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      // Missing content -- won't matter, as connection will be reset.
  };

  MockWrite data_writes2[] = {
      // After restarting with a null identity, this is the
      // request we should be issuing -- the final header line contains a Type
      // 1 message.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(negotiate_msg),
      MockWrite("\r\n\r\n"),

      // After calling trans.RestartWithAuth(), we should send a Type 3 message
      // (using correct credentials).  The second request continues on the
      // same connection.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(authenticate_msg),
      MockWrite("\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      // The origin server responds with a Type 2 message.
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM "),
      MockRead(challenge_msg),
      MockRead("\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      MockRead("You are not authorized to view this page\r\n"),

      // Lastly we get the desired content.
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=utf-8\r\n"),
      MockRead("Content-Length: 14\r\n\r\n"),
      MockRead("Please Login\r\n"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
      callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  EXPECT_TRUE(trans.IsReadyToRestartForAuth());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->did_use_server_http_auth);
  EXPECT_FALSE(response->auth_challenge.has_value());

  TestCompletionCallback callback3;

  rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(14, response->headers->GetContentLength()->InBytes());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Please Login\r\n", response_data);

  EXPECT_TRUE(data1.AllReadDataConsumed());
  EXPECT_TRUE(data1.AllWriteDataConsumed());
  EXPECT_TRUE(data2.AllReadDataConsumed());
  EXPECT_TRUE(data2.AllWriteDataConsumed());
}

// Enter a wrong password, and then the correct one.
TEST_P(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://server/kids/login.aspx");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
      MockGetMSTime, MockGenerateRandom, MockGetHostName);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Generate the NTLM messages based on known test data.
  std::string negotiate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
      std::size(ntlm::test::kExpectedNegotiateMsg)));
  std::string challenge_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
      std::size(ntlm::test::kChallengeMsgFromSpecV2)));
  std::string authenticate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(
          ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
      std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));

  // The authenticate message when |kWrongPassword| is sent.
  std::string wrong_password_authenticate_msg(
      "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
      "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
      "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
      "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
      "QwBPAE0AUABVAFQARQBSAA==");

  // Sanity check that it's the same length as the correct authenticate message
  // and that it's different.
  ASSERT_EQ(authenticate_msg.length(),
            wrong_password_authenticate_msg.length());
  ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);

  MockWrite data_writes1[] = {
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      // Negotiate and NTLM are often requested together.  However, we only want
      // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
      // the header that requests Negotiate for this test.
      MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      // Missing content -- won't matter, as connection will be reset.
  };

  MockWrite data_writes2[] = {
      // After restarting with a null identity, this is the
      // request we should be issuing -- the final header line contains a Type
      // 1 message.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(negotiate_msg),
      MockWrite("\r\n\r\n"),

      // After calling trans.RestartWithAuth(), we should send a Type 3 message
      // (using incorrect credentials).  The second request continues on the
      // same connection.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(wrong_password_authenticate_msg),
      MockWrite("\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      // The origin server responds with a Type 2 message.
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg),
      MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      MockRead("You are not authorized to view this page\r\n"),

      // Wrong password.
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      // Missing content -- won't matter, as connection will be reset.
  };

  MockWrite data_writes3[] = {
      // After restarting with a null identity, this is the
      // request we should be issuing -- the final header line contains a Type
      // 1 message.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(negotiate_msg),
      MockWrite("\r\n\r\n"),

      // After calling trans.RestartWithAuth(), we should send a Type 3 message
      // (the credentials for the origin server).  The second request continues
      // on the same connection.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(authenticate_msg),
      MockWrite("\r\n\r\n"),
  };

  MockRead data_reads3[] = {
      // The origin server responds with a Type 2 message.
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM "),
      MockRead(challenge_msg),
      MockRead("\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      MockRead("You are not authorized to view this page\r\n"),

      // Lastly we get the desired content.
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=utf-8\r\n"),
      MockRead("Content-Length: 14\r\n\r\n"),
      MockRead("Please Login\r\n"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  StaticSocketDataProvider data3(data_reads3, data_writes3);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  // Enter the wrong password.
  rv = trans.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
      callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  EXPECT_TRUE(trans.IsReadyToRestartForAuth());
  TestCompletionCallback callback3;
  rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));

  TestCompletionCallback callback4;

  // Now enter the right password.
  rv = trans.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
      callback4.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback4.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  EXPECT_TRUE(trans.IsReadyToRestartForAuth());

  TestCompletionCallback callback5;

  // One more roundtrip
  rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback5.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(14, response->headers->GetContentLength()->InBytes());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Please Login\r\n", response_data);

  EXPECT_TRUE(data1.AllReadDataConsumed());
  EXPECT_TRUE(data1.AllWriteDataConsumed());
  EXPECT_TRUE(data2.AllReadDataConsumed());
  EXPECT_TRUE(data2.AllWriteDataConsumed());
  EXPECT_TRUE(data3.AllReadDataConsumed());
  EXPECT_TRUE(data3.AllWriteDataConsumed());
}

// Server requests NTLM authentication, which is not supported over HTTP/2.
// Subsequent request with authorization header should be sent over HTTP/1.1.
TEST_P(HttpNetworkTransactionTest, NTLMOverHttp2) {
  HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
      MockGetMSTime, MockGenerateRandom, MockGetHostName);

  const char kUrl[] = "https://server/kids/login.aspx";

  const SpdySessionKey kSpdySessionKey(
      HostPortPair("server", 443), PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
      SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
      SecureDnsPolicy::kAllow,
      /*disable_cert_verification_network_fetches=*/false);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL(kUrl);
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // First request without credentials.
  quiche::HttpHeaderBlock request_headers0(
      spdy_util_.ConstructGetHeaderBlock(kUrl));
  spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
      1, std::move(request_headers0), LOWEST, true));

  quiche::HttpHeaderBlock response_headers0;
  response_headers0[spdy::kHttp2StatusHeader] = "401";
  response_headers0["www-authenticate"] = "NTLM";
  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
      1, std::move(response_headers0), true));

  // Stream 1 is closed.
  spdy_util_.UpdateWithStreamDestruction(1);

  // GOAWAY is sent.
  spdy::SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
      /*last_good_stream_id=*/0,
      MapNetErrorToGoAwayStatus(ERR_HTTP_1_1_REQUIRED),
      std::string(SpdySession::kHTTP11RequiredErrorMessage)));

  // Generate the NTLM messages based on known test data.
  std::string negotiate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
      std::size(ntlm::test::kExpectedNegotiateMsg)));
  std::string challenge_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
      std::size(ntlm::test::kChallengeMsgFromSpecV2)));
  std::string authenticate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(
          ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
      std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));

  MockWrite writes0[] = {CreateMockWrite(request0, 0),
                         CreateMockWrite(go_away, 3)};
  MockRead reads0[] = {CreateMockRead(resp, 1),
                       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};

  // Retry yet again using HTTP/1.1.
  MockWrite writes1[] = {
      // After restarting with a null identity, this is the
      // request we should be issuing -- the final header line contains a Type
      // 1 message.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(negotiate_msg),
      MockWrite("\r\n\r\n"),

      // After calling trans.RestartWithAuth(), we should send a Type 3 message
      // (the credentials for the origin server).  The second request continues
      // on the same connection.
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(authenticate_msg),
      MockWrite("\r\n\r\n"),
  };

  MockRead reads1[] = {
      // The origin server responds with a Type 2 message.
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM "),
      MockRead(challenge_msg),
      MockRead("\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      MockRead("You are not authorized to view this page\r\n"),

      // Lastly we get the desired content.
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=utf-8\r\n"),
      MockRead("Content-Length: 14\r\n\r\n"),
      MockRead("Please Login\r\n"),
  };
  SequencedSocketData data0(reads0, writes0);
  StaticSocketDataProvider data1(reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data0);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  SSLSocketDataProvider ssl0(ASYNC, OK);
  ssl0.next_proto = NextProto::kProtoHTTP2;
  ssl0.next_protos_expected_in_ssl_config =
      NextProtoVector{NextProto::kProtoHTTP2, NextProto::kProtoHTTP11};
  SSLSocketDataProvider ssl1(ASYNC, OK);
  // When creating the second connection, only HTTP/1.1 should be allowed.
  ssl1.next_protos_expected_in_ssl_config =
      NextProtoVector{NextProto::kProtoHTTP11};
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback1;
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_TRUE(session->spdy_session_pool()->HasAvailableSession(
      kSpdySessionKey,
      /*enable_ip_based_pooling_for_h2=*/true, /*is_websocket=*/false));

  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
      callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  EXPECT_TRUE(trans.IsReadyToRestartForAuth());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());

  TestCompletionCallback callback3;

  rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(14, response->headers->GetContentLength()->InBytes());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Please Login\r\n", response_data);

  EXPECT_TRUE(data0.AllReadDataConsumed());
  EXPECT_TRUE(data0.AllWriteDataConsumed());
  EXPECT_TRUE(data1.AllReadDataConsumed());
  EXPECT_TRUE(data1.AllWriteDataConsumed());

  EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
      url::SchemeHostPort(request.url), NetworkAnonymizationKey()));
  EXPECT_FALSE(session->spdy_session_pool()->HasAvailableSession(
      kSpdySessionKey,
      /*enable_ip_based_pooling_for_h2=*/true, /*is_websocket=*/false));
}

// Same as NTLMOverHttp2, but with HTTP proxy.
TEST_P(HttpNetworkTransactionTest, NTLMOverHttp2WithHttpProxy) {
  HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
      MockGetMSTime, MockGenerateRandom, MockGetHostName);

  const char kPacString[] = "PROXY myproxy:70";
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          kPacString, TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  const char kUrl[] = "https://server/kids/login.aspx";

  const SpdySessionKey kSpdySessionKey(
      HostPortPair("server", 443), PRIVACY_MODE_DISABLED,
      PacResultElementToProxyChain(kPacString), SessionUsage::kDestination,
      SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
      /*disable_cert_verification_network_fetches=*/false);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL(kUrl);
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // First request without credentials.
  quiche::HttpHeaderBlock request_headers0(
      spdy_util_.ConstructGetHeaderBlock(kUrl));
  spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
      1, std::move(request_headers0), LOWEST, true));

  quiche::HttpHeaderBlock response_headers0;
  response_headers0[spdy::kHttp2StatusHeader] = "401";
  response_headers0["www-authenticate"] = "NTLM";
  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
      1, std::move(response_headers0), true));

  // Stream 1 is closed.
  spdy_util_.UpdateWithStreamDestruction(1);

  // GOAWAY is sent.
  spdy::SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
      /*last_good_stream_id=*/0,
      MapNetErrorToGoAwayStatus(ERR_HTTP_1_1_REQUIRED),
      std::string(SpdySession::kHTTP11RequiredErrorMessage)));

  // Generate the NTLM messages based on known test data.
  std::string negotiate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
      std::size(ntlm::test::kExpectedNegotiateMsg)));
  std::string challenge_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
      std::size(ntlm::test::kChallengeMsgFromSpecV2)));
  std::string authenticate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(
          ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
      std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));

  MockWrite writes0[] = {MockWrite(SYNCHRONOUS, 0,
                                   "CONNECT server:443 HTTP/1.1\r\n"
                                   "Host: server:443\r\n"
                                   "Proxy-Connection: keep-alive\r\n"
                                   "User-Agent: test-ua\r\n\r\n"),
                         CreateMockWrite(request0, 2),
                         CreateMockWrite(go_away, 5)};
  MockRead reads0[] = {
      MockRead(SYNCHRONOUS, 1, "HTTP/1.0 200 Connected\r\n\r\n"),
      CreateMockRead(resp, 3), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4)};

  // Retry yet again using HTTP/1.1.
  MockWrite writes1[] = {
      MockWrite("CONNECT server:443 HTTP/1.1\r\n"
                "Host: server:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(negotiate_msg),
      MockWrite("\r\n\r\n"),

      MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(authenticate_msg),
      MockWrite("\r\n\r\n"),
  };

  MockRead reads1[] = {
      MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM "),
      MockRead(challenge_msg),
      MockRead("\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      MockRead("You are not authorized to view this page\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=utf-8\r\n"),
      MockRead("Content-Length: 14\r\n\r\n"),
      MockRead("Please Login\r\n"),
  };

  SequencedSocketData data0(reads0, writes0);
  StaticSocketDataProvider data1(reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data0);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  SSLSocketDataProvider ssl0(ASYNC, OK);
  ssl0.next_proto = NextProto::kProtoHTTP2;
  ssl0.next_protos_expected_in_ssl_config =
      NextProtoVector{NextProto::kProtoHTTP2, NextProto::kProtoHTTP11};

  SSLSocketDataProvider ssl1(ASYNC, OK);
  // When creating the second connection, only HTTP/1.1 should be allowed.
  ssl1.next_protos_expected_in_ssl_config =
      NextProtoVector{NextProto::kProtoHTTP11};
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback1;
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_TRUE(session->spdy_session_pool()->HasAvailableSession(
      kSpdySessionKey,
      /*enable_ip_based_pooling_for_h2=*/true, /*is_websocket=*/false));

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_EQ(1u, response->proxy_chain.length());
  EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_http());
  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;
  rv = trans.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
      callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_TRUE(trans.IsReadyToRestartForAuth());

  TestCompletionCallback callback3;
  rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(14, response->headers->GetContentLength()->InBytes());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Please Login\r\n", response_data);

  EXPECT_TRUE(data0.AllReadDataConsumed());
  EXPECT_TRUE(data0.AllWriteDataConsumed());
  EXPECT_TRUE(data1.AllReadDataConsumed());
  EXPECT_TRUE(data1.AllWriteDataConsumed());

  EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
      url::SchemeHostPort(request.url), NetworkAnonymizationKey()));
  EXPECT_FALSE(session->spdy_session_pool()->HasAvailableSession(
      kSpdySessionKey,
      /*enable_ip_based_pooling_for_h2=*/true, /*is_websocket=*/false));
}

// This tests the unusual case where there's a live H2 session for a host with
// HTTP/1.1 required set. The test specifically test the case where an H2
// connection is made while another transaction to the same host is using
// HTTP/1.x and is just starting NTLM authentication on a non-reusable socket.
// In this case, the H2 session should not be used for completing the NTLM
// authentication, in favor of making a new HTTP/1.x connections.
//
// Note that the NTLM bits were largely stolen from the NTLMAuthV2 test.
TEST_P(HttpNetworkTransactionTest, Http11RequiredWithH2Session) {
  const GURL kUrl1("https://server/1");
  const GURL kUrl2("https://server/2");

  HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
      MockGetMSTime, MockGenerateRandom, MockGetHostName);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Generate the NTLM messages based on known test data.
  std::string negotiate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
      std::size(ntlm::test::kExpectedNegotiateMsg)));
  std::string challenge_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
      std::size(ntlm::test::kChallengeMsgFromSpecV2)));
  std::string authenticate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(
          ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
      std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));

  // Set up reads/writes for the initial NTLM challenge in response to the first
  // request, over an HTTP/1.x socket. It closes the connection, so a new
  // connection will be established after HTTP/1.1 required is set on the
  // HttpServerProperties.
  MockWrite http11_data_writes1[] = {
      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead http11_data_reads1[] = {
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      // Negotiate and NTLM are often requested together.  However, we only want
      // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
      // the header that requests Negotiate for this test.
      MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      // Missing content -- won't matter, as connection will be reset.
  };

  // Second set of HTTP/1.1 reads/writes for NTLM authentication.
  MockWrite http11_data_writes2[] = {
      // After restarting with a null identity, this is the
      // request we should be issuing -- the final header line contains a Type
      // 1 message.
      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(negotiate_msg),
      MockWrite("\r\n\r\n"),

      // After calling trans1.RestartWithAuth(), we should send a Type 3 message
      // (using correct credentials).  The second request continues on the
      // same connection.
      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: NTLM "),
      MockWrite(authenticate_msg),
      MockWrite("\r\n\r\n"),
  };

  MockRead http11_data_reads2[] = {
      // The origin server responds with a Type 2 message.
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM "),
      MockRead(challenge_msg),
      MockRead("\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      MockRead("You are not authorized to view this page\r\n"),

      // Lastly we get the desired content.
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=utf-8\r\n"),
      MockRead("Connection: close\r\n"),
      MockRead("Content-Length: 6\r\n\r\n"),
      MockRead("Hello1"),
  };

  // Set up the reads/writes for the first HTTP/1.x socket. The second HTTP/1.x
  // socket will actually be the third socket created, with an H2 session
  // created on a different socket between establishment of the two HTTP/1.x
  // connections.
  StaticSocketDataProvider http11_data1(http11_data_reads1,
                                        http11_data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&http11_data1);
  SSLSocketDataProvider http11_ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&http11_ssl1);

  // Set up an H2 session with 2 sequential request/response pairs, for the
  // second and third requests.
  spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet(
      kUrl2.spec().c_str(), /*stream_id=*/1, LOWEST));
  spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), /*stream_id=*/1));
  spdy::SpdySerializedFrame body2(
      spdy_util_.ConstructSpdyDataFrame(1, "Hello2", /*fin=*/true));
  MockWrite http2_writes[] = {
      CreateMockWrite(req2, 0),
  };
  MockRead http2_reads[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
                            MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
  SequencedSocketData http2_data(http2_reads, http2_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http2_data);
  AddSSLSocketData();

  // Set up the second HTTP/1.1 connection, which is the one where NTLM
  // authentication actually takes place.
  StaticSocketDataProvider http11_data2(http11_data_reads2,
                                        http11_data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&http11_data2);
  SSLSocketDataProvider http11_ssl2(ASYNC, OK);
  http11_ssl2.next_protos_expected_in_ssl_config = {NextProto::kProtoHTTP11};
  session_deps_.socket_factory->AddSSLSocketDataProvider(&http11_ssl2);

  // Start the first request, and run through all data on the first socket. The
  // second HTTP/1.1 socket won't be connected until the request is restarted
  // with auth information.
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = kUrl1;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  // Ensure load is not disrupted by flags which suppress behaviour specific
  // to other auth schemes.
  request1.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
  TestCompletionCallback callback1;
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
  int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans1.IsReadyToRestartForAuth());
  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));

  // Start the second request, and run until completion. It should use H2.
  HttpRequestInfo request2 = request1;
  request2.url = kUrl2;
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback2;
  int rv2 = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
  ASSERT_THAT(callback2.GetResult(rv2), IsOk());
  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
  ASSERT_TRUE(response2);
  EXPECT_TRUE(response2->was_fetched_via_spdy);
  EXPECT_TRUE(response2->was_alpn_negotiated);
  std::string response_data2;
  ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
  EXPECT_EQ("Hello2", response_data2);

  // Run `trans1` through the first round of auth, which should establish a new
  // HTTP/1.1 connection, ignoring the H2 session.
  TestCompletionCallback callback3;
  rv = trans1.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
      callback3.callback());
  EXPECT_THAT(callback3.GetResult(rv), IsOk());
  EXPECT_TRUE(trans1.IsReadyToRestartForAuth());
  response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());

  // Perform the second round of auth, completing authentication and getting the
  // final response. Check that the response was received over HTTP/1.1.
  TestCompletionCallback callback4;
  rv = trans1.RestartWithAuth(AuthCredentials(), callback4.callback());
  EXPECT_THAT(callback4.GetResult(rv), IsOk());
  response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);
  std::string response_data;
  rv = ReadTransaction(&trans1, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Hello1", response_data);

  // Check that all data was read, indicating the requests ran as expected.
  EXPECT_TRUE(http11_data1.AllReadDataConsumed());
  EXPECT_TRUE(http11_data1.AllWriteDataConsumed());
  EXPECT_TRUE(http2_data.AllReadDataConsumed());
  EXPECT_TRUE(http2_data.AllWriteDataConsumed());
  EXPECT_TRUE(http11_data2.AllReadDataConsumed());
  EXPECT_TRUE(http11_data2.AllWriteDataConsumed());
}

#if BUILDFLAG(ENABLE_WEBSOCKETS)

// Variant of above test using WebSockets.
TEST_P(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
  const GURL kInitialUrl("https://server/");
  const GURL kWebSocketUrl("wss://server/");

  const SpdySessionKey kSpdySessionKey(
      HostPortPair("server", 443), PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
      SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
      SecureDnsPolicy::kAllow,
      /*disable_cert_verification_network_fetches=*/false);

  HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
      MockGetMSTime, MockGenerateRandom, MockGetHostName);

  // Initial request establishes an H2 connection, which will then be reused for
  // WebSockets. This is needed since WebSockets will reuse H2 connections, but
  // it won't create a new one.
  quiche::HttpHeaderBlock initial_request_headers(
      spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
  spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
      1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
  spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());

  // Settings frame, indicating WebSockets is supported.
  spdy::SettingsMap settings;
  settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
  spdy::SpdySerializedFrame settings_frame(
      spdy_util_.ConstructSpdySettings(settings));

  // Response headers for first request. Body is never received, but that
  // shouldn't matter for the purposes of this test.
  spdy::SpdySerializedFrame initial_response(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));

  // First WebSocket request, which has no credentials.
  quiche::HttpHeaderBlock websocket_request_headers;
  websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
  websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
  websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
  websocket_request_headers[spdy::kHttp2PathHeader] = "/";
  websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
  websocket_request_headers["origin"] = "http://server";
  websocket_request_headers["sec-websocket-version"] = "13";
  websocket_request_headers["sec-websocket-extensions"] =
      "permessage-deflate; client_max_window_bits";
  spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
      3, std::move(websocket_request_headers), MEDIUM, false));

  // Auth challenge to WebSocket request.
  quiche::HttpHeaderBlock auth_challenge_headers;
  auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
  auth_challenge_headers["www-authenticate"] = "NTLM";
  spdy::SpdySerializedFrame websocket_auth_challenge(
      spdy_util_.ConstructSpdyResponseHeaders(
          3, std::move(auth_challenge_headers), true));

  // GOAWAY is sent.
  spdy::SpdySerializedFrame go_away(spdy_util_.ConstructSpdyGoAway(
      /*last_good_stream_id=*/0,
      MapNetErrorToGoAwayStatus(ERR_HTTP_1_1_REQUIRED),
      std::string(SpdySession::kHTTP11RequiredErrorMessage)));

  MockWrite writes0[] = {
      CreateMockWrite(initial_request, 0), CreateMockWrite(settings_ack, 2),
      CreateMockWrite(websocket_request, 4), CreateMockWrite(go_away, 7)};
  MockRead reads0[] = {CreateMockRead(settings_frame, 1),
                       CreateMockRead(initial_response, 3),
                       CreateMockRead(websocket_auth_challenge, 5),
                       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};

  // Generate the NTLM messages based on known test data.
  std::string negotiate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
      std::size(ntlm::test::kExpectedNegotiateMsg)));
  std::string challenge_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
      std::size(ntlm::test::kChallengeMsgFromSpecV2)));
  std::string authenticate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(
          ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
      std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));

  // Retry yet again using HTTP/1.1.
  MockWrite writes1[] = {
      // After restarting with a null identity, this is the
      // request we should be issuing -- the final header line contains a Type
      // 1 message.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: Upgrade\r\n"
                "Authorization: NTLM "),
      MockWrite(negotiate_msg),
      MockWrite("\r\n"),
      MockWrite("Origin: http://server\r\n"
                "Sec-WebSocket-Version: 13\r\n"
                "Upgrade: websocket\r\n"
                "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
                "Sec-WebSocket-Extensions: permessage-deflate; "
                "client_max_window_bits\r\n\r\n"),

      // After calling trans.RestartWithAuth(), we should send a Type 3 message
      // (the credentials for the origin server).  The second request continues
      // on the same connection.
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: server\r\n"
                "Connection: Upgrade\r\n"
                "Authorization: NTLM "),
      MockWrite(authenticate_msg),
      MockWrite("\r\n"),
      MockWrite("Origin: http://server\r\n"
                "Sec-WebSocket-Version: 13\r\n"
                "Upgrade: websocket\r\n"
                "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
                "Sec-WebSocket-Extensions: permessage-deflate; "
                "client_max_window_bits\r\n\r\n"),
  };

  MockRead reads1[] = {
      // The origin server responds with a Type 2 message.
      MockRead("HTTP/1.1 401 Access Denied\r\n"),
      MockRead("WWW-Authenticate: NTLM "),
      MockRead(challenge_msg),
      MockRead("\r\n"),
      MockRead("Content-Length: 42\r\n"),
      MockRead("Content-Type: text/html\r\n\r\n"),
      MockRead("You are not authorized to view this page\r\n"),

      // Lastly we get the desired content.
      MockRead("HTTP/1.1 101 Switching Protocols\r\n"
               "Upgrade: websocket\r\n"
               "Connection: Upgrade\r\n"
               "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
  };
  SequencedSocketData data0(reads0, writes0);
  session_deps_.socket_factory->AddSocketDataProvider(&data0);
  SSLSocketDataProvider ssl0(ASYNC, OK);
  ssl0.next_proto = NextProto::kProtoHTTP2;
  ssl0.next_protos_expected_in_ssl_config =
      NextProtoVector{NextProto::kProtoHTTP2, NextProto::kProtoHTTP11};
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);

  StaticSocketDataProvider data1(reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl1(ASYNC, OK);
  // When creating the second connection, only HTTP/1.1 should be allowed.
  ssl1.next_protos_expected_in_ssl_config =
      NextProtoVector{NextProto::kProtoHTTP11};
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo initial_request_info;
  initial_request_info.method = "GET";
  initial_request_info.url = kInitialUrl;
  initial_request_info.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback initial_callback;
  int rv = initial_trans.Start(&initial_request_info,
                               initial_callback.callback(), NetLogWithSource());
  EXPECT_THAT(initial_callback.GetResult(rv), IsOk());

  EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
      url::SchemeHostPort(kInitialUrl), NetworkAnonymizationKey()));

  HttpRequestInfo websocket_request_info;
  websocket_request_info.method = "GET";
  websocket_request_info.url = kWebSocketUrl;
  websocket_request_info.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  EXPECT_EQ(HostPortPair::FromURL(initial_request_info.url),
            HostPortPair::FromURL(websocket_request_info.url));
  websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
  websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
  // The following two headers must be removed by WebSocketHttp2HandshakeStream.
  websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
  websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");

  TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;

  HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
  websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
      &websocket_stream_create_helper);

  TestCompletionCallback websocket_callback;
  rv = websocket_trans.Start(&websocket_request_info,
                             websocket_callback.callback(), NetLogWithSource());
  EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
  EXPECT_TRUE(session->spdy_session_pool()->HasAvailableSession(
      kSpdySessionKey,
      /*enable_ip_based_pooling_for_h2=*/true, /*is_websocket=*/true));

  EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());

  const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));

  rv = websocket_trans.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
      websocket_callback.callback());
  EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());

  EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());

  response = websocket_trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());

  rv = websocket_trans.RestartWithAuth(AuthCredentials(),
                                       websocket_callback.callback());
  EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());

  // The server should have been marked as requiring HTTP/1.1. The important
  // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
  // WSS.
  EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
      url::SchemeHostPort(kInitialUrl), NetworkAnonymizationKey()));
  EXPECT_FALSE(session->spdy_session_pool()->HasAvailableSession(
      kSpdySessionKey,
      /*enable_ip_based_pooling_for_h2=*/true, /*is_websocket=*/true));
}

#endif  // BUILDFLAG(ENABLE_WEBSOCKETS)

// Test that, if we have an NTLM proxy and the origin resets the connection, we
// do no retry forever as a result of TLS retries. This is a regression test for
// https://crbug.com/823387. The version interference probe has since been
// removed, but we now have a legacy crypto fallback. (If that fallback is
// removed, this test should be kept but with the expectations tweaked, in case
// future fallbacks are added.)
TEST_P(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
  // The NTLM test data expects the proxy to be named 'server'. The origin is
  // https://origin/.
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);

  SSLContextConfig config;
  session_deps_.ssl_config_service =
      std::make_unique<TestSSLConfigService>(config);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://origin/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Ensure load is not disrupted by flags which suppress behaviour specific
  // to other auth schemes.
  request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;

  HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
      MockGetMSTime, MockGenerateRandom, MockGetHostName);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Generate the NTLM messages based on known test data.
  std::string negotiate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
      std::size(ntlm::test::kExpectedNegotiateMsg)));
  std::string challenge_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
      std::size(ntlm::test::kChallengeMsgFromSpecV2)));
  std::string authenticate_msg = base::Base64Encode(std::string_view(
      reinterpret_cast<const char*>(
          ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
      std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));

  MockWrite data_writes[] = {
      // The initial CONNECT request.
      MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
                "Host: origin:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      // After restarting with an identity.
      MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
                "Host: origin:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: NTLM "),
      MockWrite(negotiate_msg),
      // End headers.
      MockWrite("\r\n\r\n"),

      // The second restart.
      MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
                "Host: origin:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: NTLM "),
      MockWrite(authenticate_msg),
      // End headers.
      MockWrite("\r\n\r\n"),
  };

  MockRead data_reads[] = {
      // The initial NTLM response.
      MockRead("HTTP/1.1 407 Access Denied\r\n"
               "Content-Length: 0\r\n"
               "Proxy-Authenticate: NTLM\r\n\r\n"),

      // The NTLM challenge message.
      MockRead("HTTP/1.1 407 Access Denied\r\n"
               "Content-Length: 0\r\n"
               "Proxy-Authenticate: NTLM "),
      MockRead(challenge_msg),
      // End headers.
      MockRead("\r\n\r\n"),

      // Finally the tunnel is established.
      MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);

  StaticSocketDataProvider data2(data_reads, data_writes);
  SSLSocketDataProvider data2_ssl(ASYNC, ERR_CONNECTION_RESET);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&data2_ssl);

  // Start the transaction. The proxy responds with an NTLM authentication
  // request.
  TestCompletionCallback callback;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  int rv = callback.GetResult(
      trans.Start(&request, callback.callback(), NetLogWithSource()));

  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans.IsReadyToRestartForAuth());
  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));

  // Configure credentials and restart. The proxy responds with the challenge
  // message.
  rv = callback.GetResult(trans.RestartWithAuth(
      AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
      callback.callback()));
  EXPECT_THAT(rv, IsOk());
  EXPECT_TRUE(trans.IsReadyToRestartForAuth());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());

  // Restart once more. The tunnel will be established and the the SSL handshake
  // will reset. The fallback will then kick in and restart the process. The
  // proxy responds with another NTLM authentiation request, but we don't need
  // to provide credentials as the cached ones work.
  rv = callback.GetResult(
      trans.RestartWithAuth(AuthCredentials(), callback.callback()));
  EXPECT_THAT(rv, IsOk());
  EXPECT_TRUE(trans.IsReadyToRestartForAuth());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());

  // The proxy responds with the NTLM challenge message.
  rv = callback.GetResult(
      trans.RestartWithAuth(AuthCredentials(), callback.callback()));
  EXPECT_THAT(rv, IsOk());
  EXPECT_TRUE(trans.IsReadyToRestartForAuth());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());

  // Send the NTLM authenticate message. The tunnel is established and the
  // handshake resets again. We should not retry again.
  rv = callback.GetResult(
      trans.RestartWithAuth(AuthCredentials(), callback.callback()));
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

#endif  // NTLM_PORTABLE

// Test reading a server response which has only headers, and no body.
// After some maximum number of bytes is consumed, the transaction should
// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Respond with 300 kb of headers (we should fail after 256 kb).
  std::string large_headers_string;
  FillLargeHeadersString(&large_headers_string, 300 * 1024);

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead(ASYNC, large_headers_string),
      MockRead("\r\nBODY"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
}

// Make sure that we don't try to reuse a TCPClientSocket when failing to
// establish tunnel.
// http://code.google.com/p/chromium/issues/detail?id=3772
TEST_P(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 404, using a persistent
  // connection. Usually a proxy would return 501 (not implemented),
  // or 200 (tunnel established).
  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 404 Not Found\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  TestCompletionCallback callback1;

  int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the TCPClientSocket was not added back to
  // the pool.
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
  trans.reset();
  base::RunLoop().RunUntilIdle();
  // Make sure that the socket didn't get recycled after calling the destructor.
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Make sure that we recycle a socket after reading all of the response body.
TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      // A part of the response body is received with the response headers.
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
      // The rest of the response body is received in two parts.
      MockRead("lo"),
      MockRead(" world"),
      MockRead("junk"),  // Should not be read!!
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  std::string status_line = response->headers->GetStatusLine();
  EXPECT_EQ("HTTP/1.1 200 OK", status_line);

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Make sure that we recycle a SSL socket after reading all of the response
// body.
TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 11\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());

  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Grab a SSL socket, use it, and put it back into the pool.  Then, reuse it
// from the pool and make sure that we recover okay.
TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
      MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};

  SSLSocketDataProvider ssl(ASYNC, OK);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  StaticSocketDataProvider data(data_reads, data_writes);
  StaticSocketDataProvider data2(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());

  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  std::string response_data;
  rv = ReadTransaction(trans.get(), &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));

  // Now start the second transaction, which should reuse the previous socket.

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans->Start(&request, callback.callback(), NetLogWithSource());

  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  rv = ReadTransaction(trans.get(), &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

TEST_P(HttpNetworkTransactionTest, CloseConnectionOnDestruction) {
  enum class TestCase {
    kReadHeaders,
    kReadPartOfBodyRead,
    kReadAllOfBody,
  };

  for (auto test_case : {TestCase::kReadHeaders, TestCase::kReadPartOfBodyRead,
                         TestCase::kReadAllOfBody}) {
    SCOPED_TRACE(testing::Message()
                 << "Test case: " << static_cast<int>(test_case));
    for (bool close_connection : {false, true}) {
      if (test_case != TestCase::kReadAllOfBody || close_connection == false) {
        continue;
      }
      SCOPED_TRACE(testing::Message()
                   << "Close connection: " << close_connection);

      HttpRequestInfo request;
      request.method = "GET";
      request.url = GURL("http://foo.test/");
      request.traffic_annotation =
          MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

      std::unique_ptr<HttpNetworkSession> session(
          CreateSession(&session_deps_));

      std::unique_ptr<HttpNetworkTransaction> trans =
          std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
                                                   session.get());

      MockRead data_reads[] = {
          // A part of the response body is received with the response headers.
          MockRead("HTTP/1.1 200 OK\r\n"
                   "Content-Length: 11\r\n\r\n"
                   "hello world"),
          MockRead(SYNCHRONOUS, OK),
      };

      StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
      session_deps_.socket_factory->AddSocketDataProvider(&data);

      TestCompletionCallback callback;

      int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
      EXPECT_THAT(callback.GetResult(rv), IsOk());

      const HttpResponseInfo* response = trans->GetResponseInfo();
      ASSERT_TRUE(response);

      EXPECT_TRUE(response->headers);
      std::string status_line = response->headers->GetStatusLine();
      EXPECT_EQ("HTTP/1.1 200 OK", status_line);

      EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

      std::string response_data;
      switch (test_case) {
        case TestCase::kReadHeaders: {
          // Already read the headers, nothing else to do.
          break;
        }

        case TestCase::kReadPartOfBodyRead: {
          auto buf = base::MakeRefCounted<IOBufferWithSize>(5);
          rv = trans->Read(buf.get(), 5, callback.callback());
          ASSERT_EQ(5, callback.GetResult(rv));
          response_data.assign(buf->data(), 5);
          EXPECT_EQ("hello", response_data);
          break;
        }

        case TestCase::kReadAllOfBody: {
          rv = ReadTransaction(trans.get(), &response_data);
          EXPECT_THAT(rv, IsOk());
          EXPECT_EQ("hello world", response_data);
          break;
        }
      }

      if (close_connection) {
        trans->CloseConnectionOnDestruction();
      }
      trans.reset();

      // Wait for the socket to be drained and added to the socket pool or
      // destroyed.
      base::RunLoop().RunUntilIdle();

      // In the case all the body was read, the socket will have been released
      // before the CloseConnectionOnDestruction() call, so will not be
      // destroyed.
      if (close_connection && test_case != TestCase::kReadAllOfBody) {
        EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
      } else {
        EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
      }
    }
  }
}

// Grab a socket, use it, and put it back into the pool. Then, make
// low memory notification and ensure the socket pool is flushed.
TEST_P(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      // A part of the response body is received with the response headers.
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
      // The rest of the response body is received in two parts.
      MockRead("lo"),
      MockRead(" world"),
      MockRead("junk"),  // Should not be read!!
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->headers);
  std::string status_line = response->headers->GetStatusLine();
  EXPECT_EQ("HTTP/1.1 200 OK", status_line);

  // Make memory critical notification and ensure the transaction still has been
  // operating right.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();

  // Socket should not be flushed as long as it is not idle.
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));

  // Idle sockets should be flushed now.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Disable idle socket closing on memory pressure.
// Grab a socket, use it, and put it back into the pool. Then, make
// low memory notification and ensure the socket pool is NOT flushed.
TEST_P(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Disable idle socket closing on memory pressure.
  session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      // A part of the response body is received with the response headers.
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
      // The rest of the response body is received in two parts.
      MockRead("lo"),
      MockRead(" world"),
      MockRead("junk"),  // Should not be read!!
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->headers);
  std::string status_line = response->headers->GetStatusLine();
  EXPECT_EQ("HTTP/1.1 200 OK", status_line);

  // Make memory critical notification and ensure the transaction still has been
  // operating right.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();

  // Socket should not be flushed as long as it is not idle.
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));

  // Idle sockets should NOT be flushed on moderate memory pressure.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MEMORY_PRESSURE_LEVEL_MODERATE);
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));

  // Idle sockets should NOT be flushed on critical memory pressure.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Grab an SSL socket, use it, and put it back into the pool. Then, make
// low memory notification and ensure the socket pool is flushed.
TEST_P(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
      MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());

  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  // Make memory critical notification and ensure the transaction still has been
  // operating right.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));

  // Make memory notification once again and ensure idle socket is closed.
  base::MemoryPressureListener::NotifyMemoryPressure(
      base::MEMORY_PRESSURE_LEVEL_CRITICAL);
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Make sure that we recycle a socket after a zero-length response.
// http://crbug.com/9880
TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL(
      "http://www.example.org/csi?v=3&s=web&action=&"
      "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
      "e=17259,18167,19592,19773,19981,20133,20173,20233&"
      "rt=prt.2642,ol.2649,xjs.2951");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 204 No Content\r\n"
               "Content-Length: 0\r\n"
               "Content-Type: text/html\r\n\r\n"),
      MockRead("junk"),  // Should not be read!!
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  // Transaction must be created after the MockReads, so it's destroyed before
  // them.
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  std::string status_line = response->headers->GetStatusLine();
  EXPECT_EQ("HTTP/1.1 204 No Content", status_line);

  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("", response_data);

  // Empty the current queue.  This is necessary because idle sockets are
  // added to the connection pool asynchronously with a PostTask.
  base::RunLoop().RunUntilIdle();

  // We now check to make sure the socket was added back to the pool.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  std::array<HttpRequestInfo, 2> request;
  // Transaction 1: a GET request that succeeds.  The socket is recycled
  // after use.
  request[0].method = "GET";
  request[0].url = GURL("http://www.google.com/");
  request[0].load_flags = 0;
  request[0].traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  // Transaction 2: a POST request.  Reuses the socket kept alive from
  // transaction 1.  The first attempts fails when writing the POST data.
  // This causes the transaction to retry with a new socket.  The second
  // attempt succeeds.
  request[1].method = "POST";
  request[1].url = GURL("http://www.google.com/login.cgi");
  request[1].upload_data_stream = &upload_data_stream;
  request[1].load_flags = 0;
  request[1].traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // The first socket is used for transaction 1 and the first attempt of
  // transaction 2.

  // The response of transaction 1.
  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  // The mock write results of transaction 1 and the first attempt of
  // transaction 2.
  MockWrite data_writes1[] = {
      MockWrite(SYNCHRONOUS, 64),                      // GET
      MockWrite(SYNCHRONOUS, 93),                      // POST
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED),  // POST data
  };
  StaticSocketDataProvider data1(data_reads1, data_writes1);

  // The second socket is used for the second attempt of transaction 2.

  // The response of transaction 2.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
      MockRead("welcome"),
      MockRead(SYNCHRONOUS, OK),
  };
  // The mock write results of the second attempt of transaction 2.
  MockWrite data_writes2[] = {
      MockWrite(SYNCHRONOUS, 93),  // POST
      MockWrite(SYNCHRONOUS, 3),   // POST data
  };
  StaticSocketDataProvider data2(data_reads2, data_writes2);

  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  const auto kExpectedResponseData =
      std::to_array<const char*>({"hello world", "welcome"});

  for (int i = 0; i < 2; ++i) {
    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    TestCompletionCallback callback;

    int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);

    EXPECT_TRUE(response->headers);
    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

    std::string response_data;
    rv = ReadTransaction(&trans, &response_data);
    EXPECT_THAT(rv, IsOk());
    EXPECT_EQ(kExpectedResponseData[i], response_data);
  }

  histogram_tester_.ExpectTotalCount(kStreamRequestH3SuccessHistogram, 3);
}

// Test the request-challenge-retry sequence for basic auth when there is
// an identity in the URL. The request should be sent as normal, but when
// it fails the identity from the URL is used to answer the challenge.
TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://foo:b@r@www.example.org/");
  request.load_flags = LOAD_NORMAL;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // The password contains an escaped character -- for this test to pass it
  // will need to be unescaped by HttpNetworkTransaction.
  EXPECT_EQ("b%40r", request.url.GetPassword());

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After the challenge above, the transaction will be restarted using the
  // identity from the url (foo, b@r) to answer the challenge.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  TestCompletionCallback callback1;
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_TRUE(trans.IsReadyToRestartForAuth());

  TestCompletionCallback callback2;
  rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  // There is no challenge info, since the identity in URL worked.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());

  // Empty the current queue.
  base::RunLoop().RunUntilIdle();
}

// Test the request-challenge-retry sequence for basic auth when there is an
// incorrect identity in the URL. The identity from the URL should be used only
// once.
TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
  HttpRequestInfo request;
  request.method = "GET";
  // Note: the URL has a username:password in it.  The password "baz" is
  // wrong (should be "bar").
  request.url = GURL("http://foo:baz@www.example.org/");

  request.load_flags = LOAD_NORMAL;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After the challenge above, the transaction will be restarted using the
  // identity from the url (foo, baz) to answer the challenge.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After the challenge above, the transaction will be restarted using the
  // identity supplied by the user (foo, bar) to answer the challenge.
  MockWrite data_writes3[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  MockRead data_reads3[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  StaticSocketDataProvider data3(data_reads3, data_writes3);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  TestCompletionCallback callback1;

  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  EXPECT_TRUE(trans.IsReadyToRestartForAuth());
  TestCompletionCallback callback2;
  rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback3;
  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  // There is no challenge info, since the identity worked.
  EXPECT_FALSE(response->auth_challenge.has_value());

  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());

  // Empty the current queue.
  base::RunLoop().RunUntilIdle();
}

// Test the request-challenge-retry sequence for basic auth when there is a
// correct identity in the URL, but its use is being suppressed. The identity
// from the URL should never be used.
TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://foo:bar@www.example.org/");
  request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Length: 10\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After the challenge above, the transaction will be restarted using the
  // identity supplied by the user, not the one in the URL, to answer the
  // challenge.
  MockWrite data_writes3[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  MockRead data_reads3[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data3(data_reads3, data_writes3);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  TestCompletionCallback callback1;
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback3;
  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  EXPECT_FALSE(trans.IsReadyToRestartForAuth());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  // There is no challenge info, since the identity worked.
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());

  // Empty the current queue.
  base::RunLoop().RunUntilIdle();
}

// Test that previously tried username/passwords for a realm get re-used.
TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Transaction 1: authenticate (foo, bar) on MyRealm1
  {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/x/y/z");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    MockWrite data_writes1[] = {
        MockWrite("GET /x/y/z HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    MockRead data_reads1[] = {
        MockRead("HTTP/1.0 401 Unauthorized\r\n"),
        MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
        MockRead("Content-Length: 10000\r\n\r\n"),
        MockRead(SYNCHRONOUS, ERR_FAILED),
    };

    // Resend with authorization (username=foo, password=bar)
    MockWrite data_writes2[] = {
        MockWrite("GET /x/y/z HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    };

    // Sever accepts the authorization.
    MockRead data_reads2[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("Content-Length: 100\r\n\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider data1(data_reads1, data_writes1);
    StaticSocketDataProvider data2(data_reads2, data_writes2);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);
    session_deps_.socket_factory->AddSocketDataProvider(&data2);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback1.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

    TestCompletionCallback callback2;

    rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
                               callback2.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback2.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_FALSE(response->auth_challenge.has_value());
    EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  }

  // ------------------------------------------------------------------------

  // Transaction 2: authenticate (foo2, bar2) on MyRealm2
  {
    HttpRequestInfo request;
    request.method = "GET";
    // Note that Transaction 1 was at /x/y/z, so this is in the same
    // protection space as MyRealm1.
    request.url = GURL("http://www.example.org/x/y/a/b");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    MockWrite data_writes1[] = {
        MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  // Send preemptive authorization for MyRealm1
                  "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    };

    // The server didn't like the preemptive authorization, and
    // challenges us for a different realm (MyRealm2).
    MockRead data_reads1[] = {
        MockRead("HTTP/1.0 401 Unauthorized\r\n"),
        MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
        MockRead("Content-Length: 10000\r\n\r\n"),
        MockRead(SYNCHRONOUS, ERR_FAILED),
    };

    // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
    MockWrite data_writes2[] = {
        MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
    };

    // Sever accepts the authorization.
    MockRead data_reads2[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("Content-Length: 100\r\n\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider data1(data_reads1, data_writes1);
    StaticSocketDataProvider data2(data_reads2, data_writes2);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);
    session_deps_.socket_factory->AddSocketDataProvider(&data2);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback1.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->auth_challenge);
    EXPECT_FALSE(response->auth_challenge->is_proxy);
    EXPECT_EQ("http://www.example.org",
              response->auth_challenge->challenger.Serialize());
    EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
    EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);

    TestCompletionCallback callback2;

    rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
                               callback2.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback2.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_FALSE(response->auth_challenge.has_value());
    EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  }

  // ------------------------------------------------------------------------

  // Transaction 3: Resend a request in MyRealm's protection space --
  // succeed with preemptive authorization.
  {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/x/y/z2");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    MockWrite data_writes1[] = {
        MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  // The authorization for MyRealm1 gets sent preemptively
                  // (since the url is in the same protection space)
                  "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    };

    // Sever accepts the preemptive authorization
    MockRead data_reads1[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("Content-Length: 100\r\n\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider data1(data_reads1, data_writes1);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback1.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);

    EXPECT_FALSE(response->auth_challenge.has_value());
    EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  }

  // ------------------------------------------------------------------------

  // Transaction 4: request another URL in MyRealm (however the
  // url is not known to belong to the protection space, so no pre-auth).
  {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/x/1");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    MockWrite data_writes1[] = {
        MockWrite("GET /x/1 HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    MockRead data_reads1[] = {
        MockRead("HTTP/1.0 401 Unauthorized\r\n"),
        MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
        MockRead("Content-Length: 10000\r\n\r\n"),
        MockRead(SYNCHRONOUS, ERR_FAILED),
    };

    // Resend with authorization from MyRealm's cache.
    MockWrite data_writes2[] = {
        MockWrite("GET /x/1 HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    };

    // Sever accepts the authorization.
    MockRead data_reads2[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("Content-Length: 100\r\n\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider data1(data_reads1, data_writes1);
    StaticSocketDataProvider data2(data_reads2, data_writes2);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);
    session_deps_.socket_factory->AddSocketDataProvider(&data2);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback1.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    EXPECT_TRUE(trans.IsReadyToRestartForAuth());
    TestCompletionCallback callback2;
    rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
    rv = callback2.WaitForResult();
    EXPECT_THAT(rv, IsOk());
    EXPECT_FALSE(trans.IsReadyToRestartForAuth());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_FALSE(response->auth_challenge.has_value());
    EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  }

  // ------------------------------------------------------------------------

  // Transaction 5: request a URL in MyRealm, but the server rejects the
  // cached identity. Should invalidate and re-prompt.
  {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/p/q/t");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    MockWrite data_writes1[] = {
        MockWrite("GET /p/q/t HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    MockRead data_reads1[] = {
        MockRead("HTTP/1.0 401 Unauthorized\r\n"),
        MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
        MockRead("Content-Length: 10000\r\n\r\n"),
        MockRead(SYNCHRONOUS, ERR_FAILED),
    };

    // Resend with authorization from cache for MyRealm.
    MockWrite data_writes2[] = {
        MockWrite("GET /p/q/t HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    };

    // Sever rejects the authorization.
    MockRead data_reads2[] = {
        MockRead("HTTP/1.0 401 Unauthorized\r\n"),
        MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
        MockRead("Content-Length: 10000\r\n\r\n"),
        MockRead(SYNCHRONOUS, ERR_FAILED),
    };

    // At this point we should prompt for new credentials for MyRealm.
    // Restart with username=foo3, password=foo4.
    MockWrite data_writes3[] = {
        MockWrite("GET /p/q/t HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"
                  "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
    };

    // Sever accepts the authorization.
    MockRead data_reads3[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("Content-Length: 100\r\n\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider data1(data_reads1, data_writes1);
    StaticSocketDataProvider data2(data_reads2, data_writes2);
    StaticSocketDataProvider data3(data_reads3, data_writes3);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);
    session_deps_.socket_factory->AddSocketDataProvider(&data2);
    session_deps_.socket_factory->AddSocketDataProvider(&data3);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback1.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    EXPECT_TRUE(trans.IsReadyToRestartForAuth());
    TestCompletionCallback callback2;
    rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
    rv = callback2.WaitForResult();
    EXPECT_THAT(rv, IsOk());
    EXPECT_FALSE(trans.IsReadyToRestartForAuth());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

    TestCompletionCallback callback3;

    rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
                               callback3.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback3.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_FALSE(response->auth_challenge.has_value());
    EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  }
}

// Tests that nonce count increments when multiple auth attempts
// are started with the same nonce.
TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
  auto digest_factory = std::make_unique<HttpAuthHandlerDigest::Factory>();
  auto nonce_generator =
      std::make_unique<HttpAuthHandlerDigest::FixedNonceGenerator>(
          "0123456789abcdef");
  digest_factory->set_nonce_generator(std::move(nonce_generator));
  session_deps_.http_auth_handler_factory = std::move(digest_factory);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Transaction 1: authenticate (foo, bar) on MyRealm1
  {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/x/y/z");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    MockWrite data_writes1[] = {
        MockWrite("GET /x/y/z HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    MockRead data_reads1[] = {
        MockRead("HTTP/1.0 401 Unauthorized\r\n"),
        MockRead(
            "WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
            "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    // Resend with authorization (username=foo, password=bar)
    MockWrite data_writes2[] = {
        MockWrite(
            "GET /x/y/z HTTP/1.1\r\n"
            "Host: www.example.org\r\n"
            "Connection: keep-alive\r\n"
            "Authorization: Digest username=\"foo\", realm=\"digestive\", "
            "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
            "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
            "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
    };

    // Sever accepts the authorization.
    MockRead data_reads2[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider data1(data_reads1, data_writes1);
    StaticSocketDataProvider data2(data_reads2, data_writes2);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);
    session_deps_.socket_factory->AddSocketDataProvider(&data2);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback1.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));

    TestCompletionCallback callback2;

    rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
                               callback2.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback2.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(response->did_use_server_http_auth);
    EXPECT_FALSE(response->auth_challenge.has_value());
  }

  // ------------------------------------------------------------------------

  // Transaction 2: Request another resource in digestive's protection space.
  // This will preemptively add an Authorization header which should have an
  // "nc" value of 2 (as compared to 1 in the first use.
  {
    HttpRequestInfo request;
    request.method = "GET";
    // Note that Transaction 1 was at /x/y/z, so this is in the same
    // protection space as digest.
    request.url = GURL("http://www.example.org/x/y/a/b");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    MockWrite data_writes1[] = {
        MockWrite(
            "GET /x/y/a/b HTTP/1.1\r\n"
            "Host: www.example.org\r\n"
            "Connection: keep-alive\r\n"
            "Authorization: Digest username=\"foo\", realm=\"digestive\", "
            "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
            "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
            "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
    };

    // Sever accepts the authorization.
    MockRead data_reads1[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("Content-Length: 100\r\n\r\n"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider data1(data_reads1, data_writes1);
    session_deps_.socket_factory->AddSocketDataProvider(&data1);

    TestCompletionCallback callback1;

    int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback1.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_FALSE(response->auth_challenge.has_value());
  }
}

// Test the ResetStateForRestart() private method.
TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
  // Create a transaction (the dependencies aren't important).
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Setup some state (which we expect ResetStateForRestart() will clear).
  trans.read_buf_ = base::MakeRefCounted<IOBufferWithSize>(15);
  trans.read_buf_len_ = 15;
  trans.request_headers_.SetHeader("Authorization", "NTLM");

  // Setup state in response_
  HttpResponseInfo* response = &trans.response_;
  response->auth_challenge = std::nullopt;
  response->ssl_info.cert_status = static_cast<CertStatus>(-1);  // Nonsensical.
  response->response_time = base::Time::Now();
  response->was_cached = true;  // (Wouldn't ever actually be true...)

  // Cause the above state to be reset.
  trans.ResetStateForRestart();

  // Verify that the state that needed to be reset, has been reset.
  EXPECT_FALSE(trans.read_buf_);
  EXPECT_EQ(0, trans.read_buf_len_);
  EXPECT_TRUE(trans.request_headers_.IsEmpty());
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_FALSE(response->headers);
  EXPECT_FALSE(response->was_cached);
  EXPECT_EQ(0U, response->ssl_info.cert_status);
}

// Test HTTPS connections to a site with a bad certificate
TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider ssl_bad_certificate;
  StaticSocketDataProvider data(data_reads, data_writes);
  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
  SSLSocketDataProvider ssl(ASYNC, OK);

  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));

  rv = trans.RestartIgnoringLastError(callback.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();

  ASSERT_TRUE(response);
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
}

// Test HTTPS connections to a site with a bad certificate, going through a
// proxy
TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite proxy_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead proxy_reads[] = {MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
                            MockRead(SYNCHRONOUS, OK)};

  MockWrite data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
  StaticSocketDataProvider data(data_reads, data_writes);
  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
  SSLSocketDataProvider ssl(ASYNC, OK);

  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  for (int i = 0; i < 2; i++) {
    session_deps_.socket_factory->ResetNextMockIndexes();

    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));

    rv = trans.RestartIgnoringLastError(callback.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();

    ASSERT_TRUE(response);
    EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  }
}

// Test HTTPS connections to a site, going through an HTTPS proxy
TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  SSLSocketDataProvider proxy_ssl(ASYNC, OK);   // SSL to the proxy
  SSLSocketDataProvider tunnel_ssl(ASYNC, OK);  // SSL through the tunnel

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  const HttpResponseInfo* response = trans.GetResponseInfo();

  ASSERT_TRUE(response);

  ASSERT_EQ(1u, response->proxy_chain.length());
  EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);
}

// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  const base::TimeDelta kTimeIncrement = base::Seconds(4);
  session_deps_.host_resolver->set_ondemand_mode(true);

  HttpRequestInfo request;
  request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead data_reads[] = {
      // Pause on first read.
      MockRead(ASYNC, ERR_IO_PENDING, 1),
      MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
      MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
      MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
  };

  SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());

  // Host resolution takes |kTimeIncrement|.
  FastForwardBy(kTimeIncrement);
  // Resolving the current request with |ResolveNow| will cause the pending
  // request to instantly complete, and the async connect will start as well.
  session_deps_.host_resolver->ResolveOnlyRequestNow();

  // Connecting takes |kTimeIncrement|.
  FastForwardBy(kTimeIncrement);
  data.RunUntilPaused();

  // The server takes |kTimeIncrement| to respond.
  FastForwardBy(kTimeIncrement);
  data.Resume();

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
}

// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
TEST_P(HttpNetworkTransactionTest,
       RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
      MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
      MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
  };

  SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
}

// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
// request for main frames.
TEST_P(HttpNetworkTransactionTest,
       RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
  session_deps_.proxy_resolution_service = ConfiguredProxyResolutionService::
      CreateFixedFromAutoDetectedPacResultForTest("HTTPS proxy:70",
                                                  TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  HttpRequestInfo request;
  request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
      MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
      MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
  };

  SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
}

// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
// frames.
TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  const base::TimeDelta kTimeIncrement = base::Seconds(4);
  session_deps_.host_resolver->set_ondemand_mode(true);

  HttpRequestInfo request;
  request.method = "GET";
  request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame goaway(
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
  MockWrite data_writes[] = {
      CreateMockWrite(conn, 0, SYNCHRONOUS),
      CreateMockWrite(goaway, 3, SYNCHRONOUS),
  };

  static const std::string_view kExtraHeaders[] = {
      "location",
      "http://login.example.com/",
  };
  spdy::SpdySerializedFrame resp(
      spdy_util_.ConstructSpdyReplyError("302", kExtraHeaders, 1));
  MockRead data_reads[] = {
      // Pause on first read.
      MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
      MockRead(ASYNC, 0, 4),  // EOF
  };

  SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
  proxy_ssl.next_proto = NextProto::kProtoHTTP2;

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());

  // Host resolution takes |kTimeIncrement|.
  FastForwardBy(kTimeIncrement);
  // Resolving the current request with |ResolveNow| will cause the pending
  // request to instantly complete, and the async connect will start as well.
  session_deps_.host_resolver->ResolveOnlyRequestNow();

  // Connecting takes |kTimeIncrement|.
  FastForwardBy(kTimeIncrement);
  data.RunUntilPaused();

  FastForwardBy(kTimeIncrement);
  data.Resume();
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
}

// Test that an HTTPS proxy's response to a CONNECT request is filtered.
TEST_P(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 404 Not Found\r\n"),
      MockRead("Content-Length: 23\r\n\r\n"),
      MockRead("The host does not exist"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));

  // TODO(juliatuttle): Anything else to check here?
}

// Test that a SPDY proxy's response to a CONNECT request is filtered.
TEST_P(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
  MockWrite data_writes[] = {
      CreateMockWrite(conn, 0),
      CreateMockWrite(rst, 3),
  };

  static const std::string_view kExtraHeaders[] = {
      "location",
      "http://login.example.com/",
  };
  spdy::SpdySerializedFrame resp(
      spdy_util_.ConstructSpdyReplyError("404", kExtraHeaders, 1));
  spdy::SpdySerializedFrame body(
      spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
  MockRead data_reads[] = {
      CreateMockRead(resp, 1), CreateMockRead(body, 2),
      MockRead(ASYNC, 0, 4),  // EOF
  };

  SequencedSocketData data(data_reads, data_writes);
  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
  proxy_ssl.next_proto = NextProto::kProtoHTTP2;

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));

  // TODO(juliatuttle): Anything else to check here?
}

// Test the request-challenge-retry sequence for basic auth, through
// a SPDY proxy over a single SPDY session.
TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  // when the no authentication data flag is set.
  request.privacy_mode = PRIVACY_MODE_ENABLED;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against https proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
  spdy_util_.UpdateWithStreamDestruction(1);

  // After calling trans.RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  const std::string_view kAuthCredentials[] = {
      "user-agent",
      "test-ua",
      "proxy-authorization",
      "Basic Zm9vOmJhcg==",
  };
  spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
      kAuthCredentials, 3, HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("www.example.org", 443)));
  // Fetch https://www.example.org/ via HTTP/1.x.
  const char kGet[] =
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n";
  spdy::SpdySerializedFrame wrapped_get(
      spdy_util_.ConstructSpdyDataFrame(3, kGet, false));

  MockWrite spdy_writes[] = {
      CreateMockWrite(req, 0, ASYNC),
      CreateMockWrite(rst, 2, ASYNC),
      CreateMockWrite(connect2, 3),
      CreateMockWrite(wrapped_get, 5),
  };

  // The proxy responds to the connect with a 407, using a persistent
  // connection.
  const char kAuthStatus[] = "407";
  const std::string_view kAuthChallenge[] = {
      "proxy-authenticate",
      "Basic realm=\"MyRealm1\"",
  };
  spdy::SpdySerializedFrame conn_auth_resp(
      spdy_util_.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, 1));

  spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  const char kResp[] =
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 5\r\n\r\n";

  spdy::SpdySerializedFrame wrapped_get_resp(
      spdy_util_.ConstructSpdyDataFrame(3, kResp, false));
  spdy::SpdySerializedFrame wrapped_body(
      spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
  MockRead spdy_reads[] = {
      CreateMockRead(conn_auth_resp, 1, ASYNC),
      CreateMockRead(conn_resp, 4, ASYNC),
      CreateMockRead(wrapped_get_resp, 6, ASYNC),
      CreateMockRead(wrapped_body, 7, ASYNC),
      MockRead(ASYNC, OK, 8),  // EOF.  May or may not be read.
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
  // Negotiate SPDY to the proxy
  SSLSocketDataProvider proxy(ASYNC, OK);
  proxy.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
  // Vanilla SSL to the server
  SSLSocketDataProvider server(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&server);

  TestCompletionCallback callback1;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(response->auth_challenge.has_value());
  EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv =
      trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(5, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  // The password prompt info should not be set.
  EXPECT_FALSE(response->auth_challenge.has_value());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test HTTPS connections to a site with a bad certificate, going through an
// HTTPS proxy
TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Attempt to fetch the URL from a server with a bad cert
  MockWrite bad_cert_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  MockRead bad_cert_reads[] = {MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
                               MockRead(SYNCHRONOUS, OK)};

  // Attempt to fetch the URL with a good cert
  MockWrite good_data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead good_cert_reads[] = {
      MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
  StaticSocketDataProvider data(good_cert_reads, good_data_writes);
  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
  SSLSocketDataProvider ssl(ASYNC, OK);

  // SSL to the proxy, then CONNECT request, then SSL with bad certificate
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);

  // SSL to the proxy, then CONNECT request, then valid SSL certificate
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));

  rv = trans.RestartIgnoringLastError(callback.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();

  ASSERT_TRUE(response);
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
                                  "Chromium Ultra Awesome X Edition");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
  // Test user agent values, used both for the request header of the original
  // request, and the value returned by the HttpUserAgentSettings. nullptr means
  // no request header / no HttpUserAgentSettings object.
  const char* kTestUserAgents[] = {nullptr, "", "Foopy"};

  for (const char* setting_user_agent : kTestUserAgents) {
    if (!setting_user_agent) {
      session_deps_.http_user_agent_settings.reset();
    } else {
      session_deps_.http_user_agent_settings =
          std::make_unique<StaticHttpUserAgentSettings>(
              std::string() /* accept-language */, setting_user_agent);
    }
    session_deps_.proxy_resolution_service =
        ConfiguredProxyResolutionService::CreateFixedForTest(
            "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
    for (const char* request_user_agent : kTestUserAgents) {
      HttpRequestInfo request;
      request.method = "GET";
      request.url = GURL("https://www.example.org/");
      if (request_user_agent) {
        request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
                                        request_user_agent);
      }
      request.traffic_annotation =
          MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

      HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

      std::string expected_request;
      if (!setting_user_agent || strlen(setting_user_agent) == 0) {
        expected_request =
            "CONNECT www.example.org:443 HTTP/1.1\r\n"
            "Host: www.example.org:443\r\n"
            "Proxy-Connection: keep-alive\r\n\r\n";
      } else {
        expected_request = base::StringPrintf(
            "CONNECT www.example.org:443 HTTP/1.1\r\n"
            "Host: www.example.org:443\r\n"
            "Proxy-Connection: keep-alive\r\n"
            "User-Agent: %s\r\n\r\n",
            setting_user_agent);
      }
      MockWrite data_writes[] = {
          MockWrite(expected_request),
      };
      MockRead data_reads[] = {
          // Return an error, so the transaction stops here (this test isn't
          // interested in the rest).
          MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
          MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
          MockRead("Proxy-Connection: close\r\n\r\n"),
      };

      StaticSocketDataProvider data(data_reads, data_writes);
      session_deps_.socket_factory->AddSocketDataProvider(&data);

      TestCompletionCallback callback;

      int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
      EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

      rv = callback.WaitForResult();
      EXPECT_THAT(rv, IsOk());
    }
  }
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
                                  "http://the.previous.site.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Referer: http://the.previous.site.com/\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
  HttpRequestInfo request;
  request.method = "PUT";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("PUT / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
  HttpRequestInfo request;
  request.method = "HEAD";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("HEAD / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.load_flags = LOAD_BYPASS_CACHE;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Pragma: no-cache\r\n"
                "Cache-Control: no-cache\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.load_flags = LOAD_VALIDATE_CACHE;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Cache-Control: max-age=0\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.extra_headers.SetHeader("FooHeader", "Bar");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "FooHeader: Bar\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.extra_headers.SetHeader(net::HttpRequestHeaders::kReferer,
                                  "www.foo.com");
  request.extra_headers.SetHeader("hEllo", "Kitty");
  request.extra_headers.SetHeader("FoO", "bar");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Referer: www.foo.com\r\n"
                "hEllo: Kitty\r\n"
                "FoO: bar\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());
}

TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  char write_buffer[] = {0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0};
  char read_buffer[] = {0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0};

  MockWrite data_writes[] = {MockWrite(ASYNC, base::as_byte_span(write_buffer)),
                             MockWrite("GET / HTTP/1.1\r\n"
                                       "Host: www.example.org\r\n"
                                       "Connection: keep-alive\r\n\r\n")};

  MockRead data_reads[] = {
      MockRead(ASYNC, base::as_byte_span(read_buffer)),
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
      MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  ASSERT_EQ(1u, response->proxy_chain.length());
  EXPECT_EQ(ProxyServer::SCHEME_SOCKS4,
            response->proxy_chain.GetProxyServer(0).scheme());
  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  std::string response_text;
  rv = ReadTransaction(&trans, &response_text);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Payload", response_text);
}

TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  const unsigned char write_buffer[] = {0x04, 0x01, 0x01, 0xBB, 127,
                                        0,    0,    1,    0};
  const unsigned char read_buffer[] = {0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0};

  MockWrite data_writes[] = {MockWrite(ASYNC, base::span(write_buffer)),
                             MockWrite("GET / HTTP/1.1\r\n"
                                       "Host: www.example.org\r\n"
                                       "Connection: keep-alive\r\n\r\n")};

  MockRead data_reads[] = {
      MockRead(ASYNC, base::span(read_buffer)), MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
      MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_EQ(1u, response->proxy_chain.length());
  EXPECT_EQ(ProxyServer::SCHEME_SOCKS4,
            response->proxy_chain.GetProxyServer(0).scheme());

  std::string response_text;
  rv = ReadTransaction(&trans, &response_text);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Payload", response_text);
}

TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  const char write_buffer[] = {0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0};
  const char read_buffer[] = {0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0};

  MockWrite data_writes[] = {MockWrite(ASYNC, base::span(write_buffer)),
                             MockWrite("GET / HTTP/1.1\r\n"
                                       "Host: www.example.org\r\n"
                                       "Connection: keep-alive\r\n\r\n")};

  MockRead data_reads[] = {
      MockRead(ASYNC, base::span(read_buffer)), MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
      MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReused(load_timing_info,
                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  std::string response_text;
  rv = ReadTransaction(&trans, &response_text);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Payload", response_text);
}

TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  const char kSOCKS5ExampleOkRequest[] = {
      0x05,  // Version
      0x01,  // Command (CONNECT)
      0x00,  // Reserved.
      0x03,  // Address type (DOMAINNAME).
      0x0F,  // Length of domain (15)
      'w',  'w', 'w', '.', 'e',  'x',
      'a',  'm', 'p', 'l', 'e',         // Domain string
      '.',  'o', 'r', 'g', 0x00, 0x50,  // 16-bit port (80)
  };

  MockWrite data_writes[] = {
      MockWrite(ASYNC, kSOCKS5GreetRequest),
      MockWrite(ASYNC, base::as_byte_span(kSOCKS5ExampleOkRequest)),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n")};

  MockRead data_reads[] = {
      MockRead(ASYNC, kSOCKS5GreetResponse),
      MockRead(ASYNC, kSOCKS5OkResponse),
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
      MockRead("Payload"),
      MockRead(SYNCHRONOUS, OK)};

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_EQ(1u, response->proxy_chain.length());
  EXPECT_EQ(ProxyServer::SCHEME_SOCKS5,
            response->proxy_chain.GetProxyServer(0).scheme());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);

  std::string response_text;
  rv = ReadTransaction(&trans, &response_text);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Payload", response_text);
}

TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  const unsigned char kSOCKS5ExampleOkRequest[] = {
      0x05,  // Version
      0x01,  // Command (CONNECT)
      0x00,  // Reserved.
      0x03,  // Address type (DOMAINNAME).
      0x0F,  // Length of domain (15)
      'w',  'w', 'w', '.', 'e',  'x',
      'a',  'm', 'p', 'l', 'e',         // Domain string
      '.',  'o', 'r', 'g', 0x01, 0xBB,  // 16-bit port (443)
  };

  const char kSOCKS5SslOkResponse[] = {0x05, 0x00, 0x00, 0x01, 0,
                                       0,    0,    0,    0x00, 0x00};

  MockWrite data_writes[] = {
      MockWrite(ASYNC, kSOCKS5GreetRequest),
      MockWrite(ASYNC, base::as_byte_span(kSOCKS5ExampleOkRequest)),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n")};

  MockRead data_reads[] = {
      MockRead(ASYNC, kSOCKS5GreetResponse),
      MockRead(ASYNC, base::as_byte_span(kSOCKS5SslOkResponse)),
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
      MockRead("Payload"),
      MockRead(SYNCHRONOUS, OK)};

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_EQ(1u, response->proxy_chain.length());
  EXPECT_EQ(ProxyServer::SCHEME_SOCKS5,
            response->proxy_chain.GetProxyServer(0).scheme());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  std::string response_text;
  rv = ReadTransaction(&trans, &response_text);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Payload", response_text);
}

namespace {

// Tests that for connection endpoints the group ids are correctly set.

struct GroupIdTest {
  std::string proxy_chain;
  std::string url;
  ClientSocketPool::GroupId expected_group_id;
  HttpStreamKey expected_http_stream_key;
  bool ssl;
};

std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
    SpdySessionDependencies* session_deps_) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  AlternativeService alternative_service(NextProto::kProtoHTTP2, "", 444);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort("https", "host.with.alternate", 443),
      NetworkAnonymizationKey(), alternative_service, expiration);

  return session;
}

int GroupIdTransactionHelper(const std::string& url,
                             HttpNetworkSession* session) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL(url);
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);

  TestCompletionCallback callback;

  // We do not complete this request, the dtor will clean the transaction up.
  return trans.Start(&request, callback.callback(), NetLogWithSource());
}

int HttpStreamKeyTransactionHelper(std::string_view url,
                                   HttpNetworkSession* session) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL(url);
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);

  TestCompletionCallback callback;

  // Unlike GroupIdTransactionHelper(), we complete the request because
  // HttpStreamKey is only set after the transaction switched to the
  // HttpStreamPool.
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  CHECK_EQ(rv, ERR_IO_PENDING);
  return callback.WaitForResult();
}

}  // namespace

TEST_P(HttpNetworkTransactionTest, GroupIdOrHttpStreamKeyForDirectConnections) {
  const GroupIdTest tests[] = {
      {
          "",  // unused
          "http://www.example.org/direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(
              url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
              PrivacyMode::PRIVACY_MODE_DISABLED, SocketTag(),
              NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
              /*disable_cert_network_fetches=*/false),
          false,
      },
      {
          "",  // unused
          "http://[2001:1418:13:1::25]/direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpScheme, "[2001:1418:13:1::25]", 80),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(
              url::SchemeHostPort(url::kHttpScheme, "[2001:1418:13:1::25]", 80),
              PrivacyMode::PRIVACY_MODE_DISABLED, SocketTag(),
              NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
              /*disable_cert_network_fetches=*/false),
          false,
      },

      // SSL Tests
      {
          "",  // unused
          "https://www.example.org/direct_ssl",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(
              url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
              PrivacyMode::PRIVACY_MODE_DISABLED, SocketTag(),
              NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
              /*disable_cert_network_fetches=*/false),
          true,
      },
      {
          "",  // unused
          "https://[2001:1418:13:1::25]/direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "[2001:1418:13:1::25]",
                                  443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(url::SchemeHostPort(url::kHttpsScheme,
                                            "[2001:1418:13:1::25]", 443),
                        PrivacyMode::PRIVACY_MODE_DISABLED, SocketTag(),
                        NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
                        /*disable_cert_network_fetches=*/false),
          true,
      },
      {
          "",  // unused
          "https://host.with.alternate/direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
                                  443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(url::SchemeHostPort(url::kHttpsScheme,
                                            "host.with.alternate", 443),
                        PrivacyMode::PRIVACY_MODE_DISABLED, SocketTag(),
                        NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
                        /*disable_cert_network_fetches=*/false),
          true,
      },
  };

  for (const auto& test : tests) {
    session_deps_.proxy_resolution_service =
        ConfiguredProxyResolutionService::CreateFixedForTest(
            test.proxy_chain, TRAFFIC_ANNOTATION_FOR_TESTS);
    std::unique_ptr<HttpNetworkSession> session(
        SetupSessionForGroupIdTests(&session_deps_));

    HttpNetworkSessionPeer peer(session.get());

    if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
      // The result doesn't matter, so just fail the connections (one for
      // origin, anothor for an alternative service).
      StaticSocketDataProvider data;
      data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
      session_deps_.socket_factory->AddSocketDataProvider(&data);
      StaticSocketDataProvider alt_data;
      alt_data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
      session_deps_.socket_factory->AddSocketDataProvider(&alt_data);

      auto http_pool_delegate =
          std::make_unique<CaptureKeyHttpStreamPoolDelegate>();
      CaptureKeyHttpStreamPoolDelegate* http_pool_delegate_ptr =
          http_pool_delegate.get();
      session->http_stream_pool()->SetDelegateForTesting(
          std::move(http_pool_delegate));

      EXPECT_EQ(ERR_FAILED,
                HttpStreamKeyTransactionHelper(test.url, session.get()));
      EXPECT_EQ(test.expected_http_stream_key,
                http_pool_delegate_ptr->last_key());
    } else {
      auto transport_conn_pool =
          std::make_unique<CaptureGroupIdTransportSocketPool>(
              &dummy_connect_job_params_);
      auto* transport_conn_pool_ptr = transport_conn_pool.get();
      auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
      mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
                                       std::move(transport_conn_pool));
      peer.SetClientSocketPoolManager(std::move(mock_pool_manager));

      EXPECT_EQ(ERR_IO_PENDING,
                GroupIdTransactionHelper(test.url, session.get()));
      EXPECT_EQ(test.expected_group_id,
                transport_conn_pool_ptr->last_group_id_received());
      EXPECT_TRUE(transport_conn_pool_ptr->socket_requested());
    }
  }
}

TEST_P(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
  const GroupIdTest tests[] = {
      {
          "http_proxy",
          "http://www.example.org/http_proxy_normal",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          false,
      },

      // SSL Tests
      {
          "http_proxy",
          "https://www.example.org/http_connect_ssl",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          true,
      },

      {
          "http_proxy",
          "https://host.with.alternate/direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
                                  443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          true,
      },
  };

  for (const auto& test : tests) {
    session_deps_.proxy_resolution_service =
        ConfiguredProxyResolutionService::CreateFixedForTest(
            test.proxy_chain, TRAFFIC_ANNOTATION_FOR_TESTS);
    std::unique_ptr<HttpNetworkSession> session(
        SetupSessionForGroupIdTests(&session_deps_));

    HttpNetworkSessionPeer peer(session.get());

    ProxyChain proxy_chain(ProxyServer::SCHEME_HTTP,
                           HostPortPair("http_proxy", 80));
    auto http_proxy_pool = std::make_unique<CaptureGroupIdTransportSocketPool>(
        &dummy_connect_job_params_);
    auto* http_proxy_pool_ptr = http_proxy_pool.get();
    auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
    mock_pool_manager->SetSocketPool(proxy_chain, std::move(http_proxy_pool));
    peer.SetClientSocketPoolManager(std::move(mock_pool_manager));

    EXPECT_EQ(ERR_IO_PENDING,
              GroupIdTransactionHelper(test.url, session.get()));
    EXPECT_EQ(test.expected_group_id,
              http_proxy_pool_ptr->last_group_id_received());
  }
}

TEST_P(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
  const GroupIdTest tests[] = {
      {
          "socks4://socks_proxy:1080",
          "http://www.example.org/socks4_direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          false,
      },
      {
          "socks5://socks_proxy:1080",
          "http://www.example.org/socks5_direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          false,
      },

      // SSL Tests
      {
          "socks4://socks_proxy:1080",
          "https://www.example.org/socks4_ssl",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          true,
      },
      {
          "socks5://socks_proxy:1080",
          "https://www.example.org/socks5_ssl",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          true,
      },

      {
          "socks4://socks_proxy:1080",
          "https://host.with.alternate/direct",
          ClientSocketPool::GroupId(
              url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
                                  443),
              PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
              SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
          HttpStreamKey(),  // unused
          true,
      },
  };

  for (const auto& test : tests) {
    session_deps_.proxy_resolution_service =
        ConfiguredProxyResolutionService::CreateFixedForTest(
            test.proxy_chain, TRAFFIC_ANNOTATION_FOR_TESTS);
    std::unique_ptr<HttpNetworkSession> session(
        SetupSessionForGroupIdTests(&session_deps_));

    HttpNetworkSessionPeer peer(session.get());

    ProxyChain proxy_chain =
        ProxyUriToProxyChain(test.proxy_chain, ProxyServer::SCHEME_HTTP);
    ASSERT_TRUE(proxy_chain.IsValid());
    auto socks_conn_pool = std::make_unique<CaptureGroupIdTransportSocketPool>(
        &dummy_connect_job_params_);
    auto* socks_conn_pool_ptr = socks_conn_pool.get();
    auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
    mock_pool_manager->SetSocketPool(proxy_chain, std::move(socks_conn_pool));
    peer.SetClientSocketPoolManager(std::move(mock_pool_manager));

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    EXPECT_EQ(ERR_IO_PENDING,
              GroupIdTransactionHelper(test.url, session.get()));
    EXPECT_EQ(test.expected_group_id,
              socks_conn_pool_ptr->last_group_id_received());
  }
}

TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);

  // This simulates failure resolving all hostnames; that means we will fail
  // connecting to both proxies (myproxy:70 and foobar:80).
  session_deps_.host_resolver->rules()->AddSimulatedFailure("*");

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
}

// Make sure we can handle an error when writing the request.
TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite write_failure[] = {
      MockWrite(ASYNC, ERR_CONNECTION_RESET),
  };
  StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));

  IPEndPoint endpoint;
  EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
  EXPECT_LT(0u, endpoint.address().size());
}

// Check that a connection closed after the start of the headers finishes ok.
TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.foo.com/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockRead data_reads[] = {
      MockRead("HTTP/1."),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("", response_data);

  IPEndPoint endpoint;
  EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
  EXPECT_LT(0u, endpoint.address().size());
}

// Make sure that a dropped connection while draining the body for auth
// restart does the right thing.
TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Unauthorized\r\n"),
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 14\r\n\r\n"),
      MockRead("Unauth"),
      MockRead(ASYNC, ERR_CONNECTION_RESET),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // After calling trans.RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));

  TestCompletionCallback callback2;

  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
}

// Test HTTPS connections going through a proxy that sends extra data.
TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockRead proxy_reads[] = {
      MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
      MockRead(SYNCHRONOUS, OK)};

  StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
  SSLSocketDataProvider ssl(ASYNC, OK);

  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  session_deps_.socket_factory->ResetNextMockIndexes();

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
}

TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
}

TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
  base::FilePath temp_file_path;
  ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
  const uint64_t kFakeSize = 100000;  // file is actually blank
  UploadFileElementReader::ScopedOverridingContentLengthForTests
      overriding_content_length(kFakeSize);

  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadFileElementReader>(
      base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
      0, std::numeric_limits<uint64_t>::max(), base::Time()));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.example.org/upload");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_FALSE(response->headers);

  base::DeleteFile(temp_file_path);
}

TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
  base::FilePath temp_file;
  ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
  std::string temp_file_content("Unreadable file.");
  ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content));
  ASSERT_TRUE(base::MakeFileUnreadable(temp_file));

  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadFileElementReader>(
      base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file, 0,
      std::numeric_limits<uint64_t>::max(), base::Time()));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.example.org/upload");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // If we try to upload an unreadable file, the transaction should fail.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  StaticSocketDataProvider data;
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));

  base::DeleteFile(temp_file);
}

TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
  class FakeUploadElementReader : public UploadElementReader {
   public:
    FakeUploadElementReader() = default;
    ~FakeUploadElementReader() override = default;

    CompletionOnceCallback TakeCallback() { return std::move(callback_); }

    // UploadElementReader overrides:
    int Init(CompletionOnceCallback callback) override {
      callback_ = std::move(callback);
      return ERR_IO_PENDING;
    }
    uint64_t GetContentLength() const override { return 0; }
    uint64_t BytesRemaining() const override { return 0; }
    int Read(IOBuffer* buf,
             int buf_length,
             CompletionOnceCallback callback) override {
      return ERR_FAILED;
    }

   private:
    CompletionOnceCallback callback_;
  };

  auto fake_reader = std::make_unique<FakeUploadElementReader>();
  auto* fake_reader_ptr = fake_reader.get();
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::move(fake_reader));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.example.org/upload");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  StaticSocketDataProvider data;
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  base::RunLoop().RunUntilIdle();

  // Transaction is pending on request body initialization.
  CompletionOnceCallback init_callback = fake_reader_ptr->TakeCallback();
  ASSERT_FALSE(init_callback.is_null());

  // Return Init()'s result after the transaction gets destroyed.
  trans.reset();
  std::move(init_callback).Run(OK);  // Should not crash.
}

// Tests that changes to Auth realms are treated like auth rejections.
TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // First transaction will request a resource and receive a Basic challenge
  // with realm="first_realm".
  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "\r\n"),
  };
  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Unauthorized\r\n"
               "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
               "\r\n"),
  };

  // After calling trans.RestartWithAuth(), provide an Authentication header
  // for first_realm. The server will reject and provide a challenge with
  // second_realm.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zmlyc3Q6YmF6\r\n"
                "\r\n"),
  };
  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 401 Unauthorized\r\n"
               "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
               "\r\n"),
  };

  // This again fails, and goes back to first_realm. Make sure that the
  // entry is removed from cache.
  MockWrite data_writes3[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
                "\r\n"),
  };
  MockRead data_reads3[] = {
      MockRead("HTTP/1.1 401 Unauthorized\r\n"
               "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
               "\r\n"),
  };

  // Try one last time (with the correct password) and get the resource.
  MockWrite data_writes4[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zmlyc3Q6YmFy\r\n"
                "\r\n"),
  };
  MockRead data_reads4[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html; charset=iso-8859-1\r\n"
               "Content-Length: 5\r\n"
               "\r\n"
               "hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  StaticSocketDataProvider data3(data_reads3, data_writes3);
  StaticSocketDataProvider data4(data_reads4, data_writes4);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);
  session_deps_.socket_factory->AddSocketDataProvider(&data4);

  TestCompletionCallback callback1;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Issue the first request with Authorize headers. There should be a
  // password prompt for first_realm waiting to be filled in after the
  // transaction completes.
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  std::optional<AuthChallengeInfo> challenge = response->auth_challenge;
  ASSERT_TRUE(challenge);
  EXPECT_FALSE(challenge->is_proxy);
  EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
  EXPECT_EQ("first_realm", challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, challenge->scheme);

  // Issue the second request with an incorrect password. There should be a
  // password prompt for second_realm waiting to be filled in after the
  // transaction completes.
  TestCompletionCallback callback2;
  rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
                             callback2.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback2.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  challenge = response->auth_challenge;
  ASSERT_TRUE(challenge);
  EXPECT_FALSE(challenge->is_proxy);
  EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
  EXPECT_EQ("second_realm", challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, challenge->scheme);

  // Issue the third request with another incorrect password. There should be
  // a password prompt for first_realm waiting to be filled in. If the password
  // prompt is not present, it indicates that the HttpAuthCacheEntry for
  // first_realm was not correctly removed.
  TestCompletionCallback callback3;
  rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
                             callback3.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback3.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  challenge = response->auth_challenge;
  ASSERT_TRUE(challenge);
  EXPECT_FALSE(challenge->is_proxy);
  EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
  EXPECT_EQ("first_realm", challenge->realm);
  EXPECT_EQ(kBasicAuthScheme, challenge->scheme);

  // Issue the fourth request with the correct password and username.
  TestCompletionCallback callback4;
  rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
                             callback4.callback());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback4.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
}

// Regression test for https://crbug.com/754395.
TEST_P(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  url::SchemeHostPort test_server(request.url);
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());
}

TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  url::SchemeHostPort test_server(request.url);
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  AlternativeServiceInfoVector alternative_service_info_vector =
      http_server_properties->GetAlternativeServiceInfos(
          test_server, NetworkAnonymizationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  AlternativeService alternative_service(NextProto::kProtoHTTP2,
                                         "mail.example.org", 443);
  EXPECT_EQ(alternative_service,
            alternative_service_info_vector[0].alternative_service());
}

TEST_P(HttpNetworkTransactionTest,
       HonorAlternativeServiceHeaderWithNetworkAnonymizationKey) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionConnectionsByNetworkIsolationKey);
  // Since HttpServerProperties caches the feature value, have to create a new
  // one.
  session_deps_.http_server_properties =
      std::make_unique<HttpServerProperties>();

  const SchemefulSite kSite1(GURL("https://foo.test/"));
  const auto kNetworkAnonymizationKey1 =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
  const SchemefulSite kSite2(GURL("https://bar.test/"));
  const auto kNetworkAnonymizationKey2 =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request.network_isolation_key = kNetworkIsolationKey1;
  request.network_anonymization_key = kNetworkAnonymizationKey1;

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  url::SchemeHostPort test_server(request.url);
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, kNetworkAnonymizationKey1)
          .empty());

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  AlternativeServiceInfoVector alternative_service_info_vector =
      http_server_properties->GetAlternativeServiceInfos(
          test_server, kNetworkAnonymizationKey1);
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  AlternativeService alternative_service(NextProto::kProtoHTTP2,
                                         "mail.example.org", 443);
  EXPECT_EQ(alternative_service,
            alternative_service_info_vector[0].alternative_service());

  // Make sure the alternative service information is only associated with
  // kNetworkAnonymizationKey1.
  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());
  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, kNetworkAnonymizationKey2)
          .empty());
}

// Regression test for https://crbug.com/615497.
TEST_P(HttpNetworkTransactionTest,
       DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  url::SchemeHostPort test_server(request.url);
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());
}

// HTTP/2 Alternative Services should be disabled by default.
// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
TEST_P(HttpNetworkTransactionTest,
       DisableHTTP2AlternativeServicesWithDifferentHost) {
  session_deps_.enable_http2_alternative_service = false;

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  AlternativeService alternative_service(NextProto::kProtoHTTP2,
                                         "different.example.org", 444);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(request.url), NetworkAnonymizationKey(),
      alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  // Alternative service is not used, request fails.
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
}

// Regression test for https://crbug.com/615497:
// Alternative Services should be disabled for http origin.
TEST_P(HttpNetworkTransactionTest,
       DisableAlternativeServicesForInsecureOrigin) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  AlternativeService alternative_service(NextProto::kProtoHTTP2, "", 444);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(request.url), NetworkAnonymizationKey(),
      alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  // Alternative service is not used, request fails.
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
}

TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
  // Set an alternative service for origin.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  url::SchemeHostPort test_server("https", "www.example.org", 443);
  AlternativeService alternative_service(NextProto::kProtoQUIC, "", 80);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetQuicAlternativeService(
      test_server, NetworkAnonymizationKey(), alternative_service, expiration,
      session->context().quic_context->params()->supported_versions);
  EXPECT_EQ(1u, http_server_properties
                    ->GetAlternativeServiceInfos(test_server,
                                                 NetworkAnonymizationKey())
                    .size());

  // Send a clear header.
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Alt-Svc: clear\r\n"),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());
}

TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Alt-Svc: h2=\"www.example.com:443\","),
      MockRead("h2=\":1234\"\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  url::SchemeHostPort test_server("https", "www.example.org", 443);
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  EXPECT_TRUE(
      http_server_properties
          ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
          .empty());

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  AlternativeServiceInfoVector alternative_service_info_vector =
      http_server_properties->GetAlternativeServiceInfos(
          test_server, NetworkAnonymizationKey());
  ASSERT_EQ(2u, alternative_service_info_vector.size());

  AlternativeService alternative_service(NextProto::kProtoHTTP2,
                                         "www.example.com", 443);
  EXPECT_EQ(alternative_service,
            alternative_service_info_vector[0].alternative_service());
  AlternativeService alternative_service_2(NextProto::kProtoHTTP2,
                                           "www.example.org", 1234);
  EXPECT_EQ(alternative_service_2,
            alternative_service_info_vector[1].alternative_service());
}

TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
  url::SchemeHostPort server("https", "origin.example.org", 443);
  HostPortPair alternative("alternative.example.org", 443);
  std::string origin_url = "https://origin.example.org:443";
  std::string alternative_url = "https://alternative.example.org:443";

  // Negotiate HTTP/1.1 with alternative.example.org.
  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // HTTP/1.1 data for request.
  MockWrite http_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: alternative.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead http_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html; charset=iso-8859-1\r\n"
               "Content-Length: 40\r\n\r\n"
               "first HTTP/1.1 response from alternative"),
  };
  StaticSocketDataProvider http_data(http_reads, http_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  StaticSocketDataProvider data_refused;
  data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
  session_deps_.socket_factory->AddSocketDataProvider(&data_refused);

  // Set up a QUIC alternative service for server.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  AlternativeService alternative_service(NextProto::kProtoQUIC, alternative);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetQuicAlternativeService(
      server, NetworkAnonymizationKey(), alternative_service, expiration,
      DefaultSupportedQuicVersions());
  // Mark the QUIC alternative service as broken.
  http_server_properties->MarkAlternativeServiceBroken(
      alternative_service, NetworkAnonymizationKey());

  HttpRequestInfo request;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  request.method = "GET";
  request.url = GURL(origin_url);
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;
  NetErrorDetails details;
  EXPECT_FALSE(details.quic_broken);

  trans.Start(&request, callback.callback(), NetLogWithSource());
  trans.PopulateNetErrorDetails(&details);
  EXPECT_TRUE(details.quic_broken);
}

TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
  url::SchemeHostPort server("https", "origin.example.org", 443);
  HostPortPair alternative1("alternative1.example.org", 443);
  HostPortPair alternative2("alternative2.example.org", 443);
  std::string origin_url = "https://origin.example.org:443";
  std::string alternative_url1 = "https://alternative1.example.org:443";
  std::string alternative_url2 = "https://alternative2.example.org:443";

  // Negotiate HTTP/1.1 with alternative1.example.org.
  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // HTTP/1.1 data for request.
  MockWrite http_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: alternative1.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead http_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html; charset=iso-8859-1\r\n"
               "Content-Length: 40\r\n\r\n"
               "first HTTP/1.1 response from alternative1"),
  };
  StaticSocketDataProvider http_data(http_reads, http_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  StaticSocketDataProvider data_refused;
  data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
  session_deps_.socket_factory->AddSocketDataProvider(&data_refused);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpServerProperties* http_server_properties =
      session->http_server_properties();

  // Set up two QUIC alternative services for server.
  AlternativeServiceInfoVector alternative_service_info_vector;
  base::Time expiration = base::Time::Now() + base::Days(1);

  AlternativeService alternative_service1(NextProto::kProtoQUIC, alternative1);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          alternative_service1, expiration,
          session->context().quic_context->params()->supported_versions));
  AlternativeService alternative_service2(NextProto::kProtoQUIC, alternative2);
  alternative_service_info_vector.push_back(
      AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
          alternative_service2, expiration,
          session->context().quic_context->params()->supported_versions));

  http_server_properties->SetAlternativeServices(
      server, NetworkAnonymizationKey(), alternative_service_info_vector);

  // Mark one of the QUIC alternative service as broken.
  http_server_properties->MarkAlternativeServiceBroken(
      alternative_service1, NetworkAnonymizationKey());
  EXPECT_EQ(2u,
            http_server_properties
                ->GetAlternativeServiceInfos(server, NetworkAnonymizationKey())
                .size());

  HttpRequestInfo request;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  request.method = "GET";
  request.url = GURL(origin_url);
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;
  NetErrorDetails details;
  EXPECT_FALSE(details.quic_broken);

  trans.Start(&request, callback.callback(), NetLogWithSource());
  trans.PopulateNetErrorDetails(&details);
  EXPECT_FALSE(details.quic_broken);
}

TEST_P(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  const url::SchemeHostPort server(request.url);
  // Port must be < 1024, or the header will be ignored (since initial port was
  // port 80 (another restricted port).
  // Port is ignored by MockConnect anyway.
  const AlternativeService alternative_service(NextProto::kProtoHTTP2,
                                               "www.example.org", 666);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      server, NetworkAnonymizationKey(), alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  const AlternativeServiceInfoVector alternative_service_info_vector =
      http_server_properties->GetAlternativeServiceInfos(
          server, NetworkAnonymizationKey());
  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(alternative_service,
            alternative_service_info_vector[0].alternative_service());
  EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
      alternative_service, NetworkAnonymizationKey()));
}

// Ensure that we are not allowed to redirect traffic via an alternate protocol
// to an unrestricted (port >= 1024) when the original traffic was on a
// restricted port (port < 1024).  Ensure that we can redirect in all other
// cases.
TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
  HttpRequestInfo restricted_port_request;
  restricted_port_request.method = "GET";
  restricted_port_request.url = GURL("https://www.example.org:1023/");
  restricted_port_request.load_flags = 0;
  restricted_port_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  const int kUnrestrictedAlternatePort = 1024;
  AlternativeService alternative_service(
      NextProto::kProtoHTTP2, "www.example.org", kUnrestrictedAlternatePort);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(restricted_port_request.url),
      NetworkAnonymizationKey(), alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&restricted_port_request, callback.callback(),
                       NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  // Invalid change to unrestricted port should fail.
  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
}

// Ensure that we are allowed to redirect traffic via an alternate protocol to
// an unrestricted (port >= 1024) when the original traffic was on a restricted
// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
  session_deps_.enable_user_alternate_protocol_ports = true;

  HttpRequestInfo restricted_port_request;
  restricted_port_request.method = "GET";
  restricted_port_request.url = GURL("https://www.example.org:1023/");
  restricted_port_request.load_flags = 0;
  restricted_port_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  const int kUnrestrictedAlternatePort = 1024;
  AlternativeService alternative_service(
      NextProto::kProtoHTTP2, "www.example.org", kUnrestrictedAlternatePort);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(restricted_port_request.url),
      NetworkAnonymizationKey(), alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  EXPECT_EQ(ERR_IO_PENDING,
            trans.Start(&restricted_port_request, callback.callback(),
                        NetLogWithSource()));
  // Change to unrestricted port should succeed.
  EXPECT_THAT(callback.WaitForResult(), IsOk());
}

// Ensure that we are not allowed to redirect traffic via an alternate protocol
// to an unrestricted (port >= 1024) when the original traffic was on a
// restricted port (port < 1024).  Ensure that we can redirect in all other
// cases.
TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
  HttpRequestInfo restricted_port_request;
  restricted_port_request.method = "GET";
  restricted_port_request.url = GURL("https://www.example.org:1023/");
  restricted_port_request.load_flags = 0;
  restricted_port_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  const int kRestrictedAlternatePort = 80;
  AlternativeService alternative_service(
      NextProto::kProtoHTTP2, "www.example.org", kRestrictedAlternatePort);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(restricted_port_request.url),
      NetworkAnonymizationKey(), alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&restricted_port_request, callback.callback(),
                       NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  // Valid change to restricted port should pass.
  EXPECT_THAT(callback.WaitForResult(), IsOk());
}

// Ensure that we are not allowed to redirect traffic via an alternate protocol
// to an unrestricted (port >= 1024) when the original traffic was on a
// restricted port (port < 1024).  Ensure that we can redirect in all other
// cases.
TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
  HttpRequestInfo unrestricted_port_request;
  unrestricted_port_request.method = "GET";
  unrestricted_port_request.url = GURL("https://www.example.org:1024/");
  unrestricted_port_request.load_flags = 0;
  unrestricted_port_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  const int kRestrictedAlternatePort = 80;
  AlternativeService alternative_service(
      NextProto::kProtoHTTP2, "www.example.org", kRestrictedAlternatePort);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(unrestricted_port_request.url),
      NetworkAnonymizationKey(), alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&unrestricted_port_request, callback.callback(),
                       NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  // Valid change to restricted port should pass.
  EXPECT_THAT(callback.WaitForResult(), IsOk());
}

// Ensure that we are not allowed to redirect traffic via an alternate protocol
// to an unrestricted (port >= 1024) when the original traffic was on a
// restricted port (port < 1024).  Ensure that we can redirect in all other
// cases.
TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
  HttpRequestInfo unrestricted_port_request;
  unrestricted_port_request.method = "GET";
  unrestricted_port_request.url = GURL("https://www.example.org:1024/");
  unrestricted_port_request.load_flags = 0;
  unrestricted_port_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider first_data;
  first_data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&first_data);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  const int kUnrestrictedAlternatePort = 1025;
  AlternativeService alternative_service(
      NextProto::kProtoHTTP2, "www.example.org", kUnrestrictedAlternatePort);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(unrestricted_port_request.url),
      NetworkAnonymizationKey(), alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&unrestricted_port_request, callback.callback(),
                       NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  // Valid change to an unrestricted port should pass.
  EXPECT_THAT(callback.WaitForResult(), IsOk());
}

// Ensure that we are not allowed to redirect traffic via an alternate protocol
// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
// the alternate protocol request fails.
TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // The alternate protocol request will error out before we attempt to connect,
  // so only the standard HTTP request will try to connect.
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  const int kUnsafePort = 7;
  AlternativeService alternative_service(NextProto::kProtoHTTP2,
                                         "www.example.org", kUnsafePort);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      url::SchemeHostPort(request.url), NetworkAnonymizationKey(),
      alternative_service, expiration);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  // The HTTP request should succeed.
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);
}

TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
      MockRead(ASYNC, OK)};

  StaticSocketDataProvider first_transaction(data_reads,
                                             base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  AddSSLSocketData();

  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
  StaticSocketDataProvider hanging_non_alternate_protocol_socket;
  hanging_non_alternate_protocol_socket.set_connect_data(
      never_finishing_connect);
  session_deps_.socket_factory->AddSocketDataProvider(
      &hanging_non_alternate_protocol_socket);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);

  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // First transaction receives Alt-Svc header over HTTP/1.1.
  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
      MockRead(ASYNC, OK),
  };

  StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&http11_data);

  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl_http11.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  // Second transaction starts an alternative and a non-alternative Job.
  // Both sockets hang.
  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
  StaticSocketDataProvider hanging_socket1;
  hanging_socket1.set_connect_data(never_finishing_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);

  StaticSocketDataProvider hanging_socket2;
  hanging_socket2.set_connect_data(never_finishing_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);

  // Third transaction starts an alternative and a non-alternative job.
  // The non-alternative job hangs, but the alternative one succeeds.
  // The second transaction, still pending, binds to this socket.
  spdy::SpdySerializedFrame req1(
      spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
  spdy::SpdySerializedFrame req2(
      spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
  MockWrite spdy_writes[] = {
      CreateMockWrite(req1, 0),
      CreateMockWrite(req2, 1),
  };
  spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
      CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
      MockRead(ASYNC, 0, 6),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  AddSSLSocketData();

  StaticSocketDataProvider hanging_socket3;
  hanging_socket3.set_connect_data(never_finishing_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  TestCompletionCallback callback1;
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback1.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  TestCompletionCallback callback2;
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  TestCompletionCallback callback3;
  HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
  rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback2.WaitForResult(), IsOk());
  EXPECT_THAT(callback3.WaitForResult(), IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  response = trans3.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

TEST_P(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
  session_deps_.host_resolver->set_synchronous_mode(true);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
      MockRead(ASYNC, OK),
  };

  StaticSocketDataProvider first_transaction(data_reads,
                                             base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
  StaticSocketDataProvider hanging_alternate_protocol_socket;
  hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
  session_deps_.socket_factory->AddSocketDataProvider(
      &hanging_alternate_protocol_socket);

  // 2nd request is just a copy of the first one, over HTTP/1.1 again.
  StaticSocketDataProvider second_transaction(data_reads,
                                              base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);

  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);
}

// Test that proxy is resolved using the origin url,
// regardless of the alternative server.
TEST_P(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
  // Configure proxy to bypass www.example.org, which is the origin URL.
  ProxyConfig proxy_config;
  proxy_config.proxy_rules().ParseFromString("myproxy:70");
  proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
  auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
      ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));

  CapturingProxyResolver capturing_proxy_resolver;
  auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
      &capturing_proxy_resolver);

  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::move(proxy_config_service), std::move(proxy_resolver_factory),
          /*host_resolver_for_override_rules=*/nullptr, NetLog::Get(),
          /*quick_check_enabled=*/true);

  session_deps_.net_log = NetLog::Get();

  // Configure alternative service with a hostname that is not bypassed by the
  // proxy.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  url::SchemeHostPort server("https", "www.example.org", 443);
  HostPortPair alternative("www.example.com", 443);
  AlternativeService alternative_service(NextProto::kProtoHTTP2, alternative);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      server, NetworkAnonymizationKey(), alternative_service, expiration);

  // Non-alternative job should hang.
  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
  StaticSocketDataProvider hanging_alternate_protocol_socket;
  hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
  session_deps_.socket_factory->AddSocketDataProvider(
      &hanging_alternate_protocol_socket);

  AddSSLSocketData();

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));

  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  // Origin host bypasses proxy, no resolution should have happened.
  ASSERT_TRUE(capturing_proxy_resolver.lookup_info().empty());
}

TEST_P(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
  ProxyConfig proxy_config;
  proxy_config.set_auto_detect(true);
  proxy_config.set_pac_url(GURL("http://fooproxyurl"));

  CapturingProxyResolver capturing_proxy_resolver;
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::make_unique<CapturingProxyResolverFactory>(
              &capturing_proxy_resolver),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);
  session_deps_.net_log = NetLog::Get();

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
      MockRead(ASYNC, OK),
  };

  StaticSocketDataProvider first_transaction(data_reads,
                                             base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  AddSSLSocketData();

  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
  MockWrite spdy_writes[] = {
      MockWrite(ASYNC, 0,
                "CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
      CreateMockWrite(req, 2),
  };

  std::string_view kCONNECTResponse = "HTTP/1.1 200 Connected\r\n\r\n";

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads[] = {
      MockRead(ASYNC, 1, kCONNECTResponse),
      CreateMockRead(resp, 3),
      CreateMockRead(data, 4),
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
  StaticSocketDataProvider hanging_non_alternate_protocol_socket;
  hanging_non_alternate_protocol_socket.set_connect_data(
      never_finishing_connect);
  session_deps_.socket_factory->AddSocketDataProvider(
      &hanging_non_alternate_protocol_socket);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);

  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
  ASSERT_EQ(2u, capturing_proxy_resolver.lookup_info().size());
  EXPECT_EQ("https://www.example.org/",
            capturing_proxy_resolver.lookup_info()[0].url.spec());
  EXPECT_EQ("https://www.example.org/",
            capturing_proxy_resolver.lookup_info()[1].url.spec());

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);
}

TEST_P(HttpNetworkTransactionTest,
       UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };

  StaticSocketDataProvider first_transaction(data_reads,
                                             base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
  SSLSocketDataProvider ssl_http11(ASYNC, OK);
  ssl_http11.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);

  AddSSLSocketData();

  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  // Set up an initial SpdySession in the pool to reuse.
  HostPortPair host_port_pair("www.example.org", 443);
  SpdySessionKey key(host_port_pair, PRIVACY_MODE_DISABLED,
                     ProxyChain::Direct(), SessionUsage::kDestination,
                     SocketTag(), NetworkAnonymizationKey(),
                     SecureDnsPolicy::kAllow,
                     /*disable_cert_verification_network_fetches=*/false);
  base::WeakPtr<SpdySession> spdy_session =
      CreateSpdySession(session.get(), key, NetLogWithSource());

  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  ConnectedHandler connected_handler;
  trans->SetConnectedCallback(connected_handler.Callback());

  rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kDirect;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 443);
  expected_transport.negotiated_protocol = NextProto::kProtoHTTP2;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);

  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

// GenerateAuthToken is a mighty big test.
// It tests all permutation of GenerateAuthToken behavior:
//   - Synchronous and Asynchronous completion.
//   - OK or error on completion.
//   - Direct connection, non-authenticating proxy, and authenticating proxy.
//   - HTTP or HTTPS backend (to include proxy tunneling).
//   - Non-authenticating and authenticating backend.
//
// In all, there are 44 reasonable permuations (for example, if there are
// problems generating an auth token for an authenticating proxy, we don't
// need to test all permutations of the backend server).
//
// The test proceeds by going over each of the configuration cases, and
// potentially running up to three rounds in each of the tests. The TestConfig
// specifies both the configuration for the test as well as the expectations
// for the results.
TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
  static const char kServer[] = "http://www.example.com";
  static const char kSecureServer[] = "https://www.example.com";
  static const char kProxy[] = "myproxy:70";

  enum AuthTiming {
    AUTH_NONE,
    AUTH_SYNC,
    AUTH_ASYNC,
  };

  const MockWrite kGet(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Connection: keep-alive\r\n\r\n");
  const MockWrite kGetProxy(
      "GET http://www.example.com/ HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Proxy-Connection: keep-alive\r\n\r\n");
  const MockWrite kGetAuth(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Connection: keep-alive\r\n"
      "Authorization: auth_token\r\n\r\n");
  const MockWrite kGetProxyAuth(
      "GET http://www.example.com/ HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "Proxy-Authorization: auth_token\r\n\r\n");
  const MockWrite kGetAuthThroughProxy(
      "GET http://www.example.com/ HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "Authorization: auth_token\r\n\r\n");
  const MockWrite kGetAuthWithProxyAuth(
      "GET http://www.example.com/ HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "Proxy-Authorization: auth_token\r\n"
      "Authorization: auth_token\r\n\r\n");
  const MockWrite kConnect(
      "CONNECT www.example.com:443 HTTP/1.1\r\n"
      "Host: www.example.com:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n\r\n");
  const MockWrite kConnectProxyAuth(
      "CONNECT www.example.com:443 HTTP/1.1\r\n"
      "Host: www.example.com:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      "Proxy-Authorization: auth_token\r\n\r\n");

  const MockRead kSuccess(
      "HTTP/1.1 200 OK\r\n"
      "Content-Type: text/html; charset=iso-8859-1\r\n"
      "Content-Length: 3\r\n\r\n"
      "Yes");
  const MockRead kFailure("Should not be called.");
  const MockRead kServerChallenge(
      "HTTP/1.1 401 Unauthorized\r\n"
      "WWW-Authenticate: Mock realm=server\r\n"
      "Content-Type: text/html; charset=iso-8859-1\r\n"
      "Content-Length: 14\r\n\r\n"
      "Unauthorized\r\n");
  const MockRead kProxyChallenge(
      "HTTP/1.1 407 Unauthorized\r\n"
      "Proxy-Authenticate: Mock realm=proxy\r\n"
      "Proxy-Connection: close\r\n"
      "Content-Type: text/html; charset=iso-8859-1\r\n"
      "Content-Length: 14\r\n\r\n"
      "Unauthorized\r\n");
  const MockRead kProxyConnected("HTTP/1.1 200 Connection Established\r\n\r\n");

  // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
  // no constructors, but the C++ compiler on Windows warns about
  // unspecified data in compound literals. So, moved to using constructors,
  // and TestRound's created with the default constructor should not be used.
  struct TestRound {
    TestRound()
        : expected_rv(ERR_UNEXPECTED),
          extra_write(nullptr),
          extra_read(nullptr) {}
    TestRound(const MockWrite& write_arg,
              const MockRead& read_arg,
              int expected_rv_arg)
        : write(write_arg),
          read(read_arg),
          expected_rv(expected_rv_arg),
          extra_write(nullptr),
          extra_read(nullptr) {}
    TestRound(const MockWrite& write_arg,
              const MockRead& read_arg,
              int expected_rv_arg,
              const MockWrite* extra_write_arg,
              const MockRead* extra_read_arg)
        : write(write_arg),
          read(read_arg),
          expected_rv(expected_rv_arg),
          extra_write(extra_write_arg),
          extra_read(extra_read_arg) {}
    MockWrite write;
    MockRead read;
    int expected_rv;
    raw_ptr<const MockWrite> extra_write = nullptr;
    raw_ptr<const MockRead> extra_read = nullptr;
  };

  static const int kNoSSL = 500;

  struct TestConfig {
    int line_number;
    const char* const proxy_url;
    AuthTiming proxy_auth_timing;
    int first_generate_proxy_token_rv;
    const char* const server_url;
    AuthTiming server_auth_timing;
    int first_generate_server_token_rv;
    int num_auth_rounds;
    int first_ssl_round;
    std::array<TestRound, 4> rounds;
  } test_configs[] = {
      // Non-authenticating HTTP server with a direct connection.
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_NONE,
       OK,
       1,
       kNoSSL,
       {TestRound(kGet, kSuccess, OK)}},
      // Authenticating HTTP server with a direct connection.
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_SYNC,
       OK,
       2,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK),
        TestRound(kGet, kServerChallenge, OK),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_SYNC,
       ERR_UNSUPPORTED_AUTH_SCHEME,
       2,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_SYNC,
       ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
       2,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       ERR_FAILED,
       kServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxy, kFailure, ERR_FAILED)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       ERR_FAILED,
       kServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxy, kFailure, ERR_FAILED)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_SYNC,
       ERR_FAILED,
       2,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK),
        TestRound(kGet, kFailure, ERR_FAILED)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_ASYNC,
       ERR_FAILED,
       2,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK),
        TestRound(kGet, kFailure, ERR_FAILED)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_ASYNC,
       OK,
       2,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       kNoSSL,
       {TestRound(kGet, kServerChallenge, OK),
        // The second round uses a HttpAuthHandlerMock that always succeeds.
        TestRound(kGet, kServerChallenge, OK),
        TestRound(kGetAuth, kSuccess, OK)}},
      // Non-authenticating HTTP server through a non-authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_NONE,
       OK,
       1,
       kNoSSL,
       {TestRound(kGetProxy, kSuccess, OK)}},
      // Authenticating HTTP server through a non-authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_SYNC,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kServerChallenge, OK),
        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kServerChallenge, OK),
        TestRound(kGetProxy, kServerChallenge, OK),
        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_ASYNC,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kServerChallenge, OK),
        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kServerChallenge, OK),
        TestRound(kGetProxy, kSuccess, OK)}},
      // Non-authenticating HTTP server through an authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxy, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxy, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kServer,
       AUTH_NONE,
       OK,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      // Authenticating HTTP server through an authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kServer,
       AUTH_SYNC,
       OK,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kServer,
       AUTH_SYNC,
       OK,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kServer,
       AUTH_ASYNC,
       OK,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kServer,
       AUTH_ASYNC,
       OK,
       4,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kServer,
       AUTH_ASYNC,
       OK,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       4,
       kNoSSL,
       {TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxy, kProxyChallenge, OK),
        TestRound(kGetProxyAuth, kServerChallenge, OK),
        TestRound(kGetProxyAuth, kSuccess, OK)}},
      // Non-authenticating HTTPS server with a direct connection.
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_NONE,
       OK,
       1,
       0,
       {TestRound(kGet, kSuccess, OK)}},
      // Authenticating HTTPS server with a direct connection.
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_SYNC,
       OK,
       2,
       0,
       {TestRound(kGet, kServerChallenge, OK),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       2,
       0,
       {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       OK,
       2,
       0,
       {TestRound(kGet, kServerChallenge, OK),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       nullptr,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       2,
       0,
       {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
      // Non-authenticating HTTPS server with a non-authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_NONE,
       OK,
       1,
       0,
       {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
      // Authenticating HTTPS server through a non-authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_SYNC,
       OK,
       2,
       0,
       {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       2,
       0,
       {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
        TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       OK,
       2,
       0,
       {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_NONE,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       2,
       0,
       {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
        TestRound(kGet, kSuccess, OK)}},
      // Non-Authenticating HTTPS server through an authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kSecureServer,
       AUTH_NONE,
       OK,
       2,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kSecureServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       ERR_UNSUPPORTED_AUTH_SCHEME,
       kSecureServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       ERR_UNEXPECTED,
       kSecureServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kSecureServer,
       AUTH_NONE,
       OK,
       2,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kSecureServer,
       AUTH_NONE,
       OK,
       2,
       kNoSSL,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
      // Authenticating HTTPS server through an authenticating proxy.
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kSecureServer,
       AUTH_SYNC,
       OK,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kSecureServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kSecureServer,
       AUTH_SYNC,
       OK,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kSecureServer,
       AUTH_SYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       OK,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_SYNC,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       OK,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGetAuth, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       OK,
       kSecureServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       3,
       1,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGet, kSuccess, OK)}},
      {__LINE__,
       kProxy,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       kSecureServer,
       AUTH_ASYNC,
       ERR_INVALID_AUTH_CREDENTIALS,
       4,
       2,
       {TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnect, kProxyChallenge, OK),
        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
                  &kServerChallenge),
        TestRound(kGet, kSuccess, OK)}},
  };

  for (const auto& test_config : test_configs) {
    SCOPED_TRACE(::testing::Message()
                 << "Test config at " << test_config.line_number);
    auto auth_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
    auto* auth_factory_ptr = auth_factory.get();
    session_deps_.http_auth_handler_factory = std::move(auth_factory);
    SSLInfo empty_ssl_info;

    // Set up authentication handlers as necessary.
    if (test_config.proxy_auth_timing != AUTH_NONE) {
      for (int n = 0; n < 3; n++) {
        auto auth_handler = std::make_unique<HttpAuthHandlerMock>();
        url::SchemeHostPort scheme_host_port(GURL(test_config.proxy_url));
        HttpAuthChallengeTokenizer tokenizer("Mock realm=proxy");
        auth_handler->InitFromChallenge(
            &tokenizer, HttpAuth::AUTH_PROXY, empty_ssl_info,
            NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource());
        auth_handler->SetGenerateExpectation(
            test_config.proxy_auth_timing == AUTH_ASYNC,
            n == 0 ? test_config.first_generate_proxy_token_rv : OK);
        auth_factory_ptr->AddMockHandler(std::move(auth_handler),
                                         HttpAuth::AUTH_PROXY);
      }
    }
    if (test_config.server_auth_timing != AUTH_NONE) {
      auto auth_handler = std::make_unique<HttpAuthHandlerMock>();
      url::SchemeHostPort scheme_host_port(GURL(test_config.server_url));
      HttpAuthChallengeTokenizer tokenizer("Mock realm=server");
      auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
                                      empty_ssl_info, NetworkAnonymizationKey(),
                                      scheme_host_port, NetLogWithSource());
      auth_handler->SetGenerateExpectation(
          test_config.server_auth_timing == AUTH_ASYNC,
          test_config.first_generate_server_token_rv);
      auth_factory_ptr->AddMockHandler(std::move(auth_handler),
                                       HttpAuth::AUTH_SERVER);

      // The second handler always succeeds. It should only be used where there
      // are multiple auth sessions for server auth in the same network
      // transaction using the same auth scheme.
      std::unique_ptr<HttpAuthHandlerMock> second_handler =
          std::make_unique<HttpAuthHandlerMock>();
      second_handler->InitFromChallenge(
          &tokenizer, HttpAuth::AUTH_SERVER, empty_ssl_info,
          NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource());
      second_handler->SetGenerateExpectation(true, OK);
      auth_factory_ptr->AddMockHandler(std::move(second_handler),
                                       HttpAuth::AUTH_SERVER);
    }
    if (test_config.proxy_url) {
      session_deps_.proxy_resolution_service =
          ConfiguredProxyResolutionService::CreateFixedForTest(
              test_config.proxy_url, TRAFFIC_ANNOTATION_FOR_TESTS);
    } else {
      session_deps_.proxy_resolution_service =
          ConfiguredProxyResolutionService::CreateDirect();
    }

    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL(test_config.server_url);
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

    SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);

    std::vector<std::vector<MockRead>> mock_reads(1);
    std::vector<std::vector<MockWrite>> mock_writes(1);
    for (int round = 0; round < test_config.num_auth_rounds; ++round) {
      SCOPED_TRACE(round);
      const TestRound& read_write_round = test_config.rounds[round];

      // Set up expected reads and writes.
      mock_reads.back().push_back(read_write_round.read);
      mock_writes.back().push_back(read_write_round.write);

      // kProxyChallenge uses Proxy-Connection: close which means that the
      // socket is closed and a new one will be created for the next request.
      if (read_write_round.read.data == kProxyChallenge.data) {
        mock_reads.emplace_back();
        mock_writes.emplace_back();
      }

      if (read_write_round.extra_read) {
        mock_reads.back().push_back(*read_write_round.extra_read);
      }
      if (read_write_round.extra_write) {
        mock_writes.back().push_back(*read_write_round.extra_write);
      }

      // Add an SSL sequence if necessary.
      if (round >= test_config.first_ssl_round) {
        session_deps_.socket_factory->AddSSLSocketDataProvider(
            &ssl_socket_data_provider);
      }
    }

    std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
    for (size_t i = 0; i < mock_reads.size(); ++i) {
      data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
          mock_reads[i], mock_writes[i]));
      session_deps_.socket_factory->AddSocketDataProvider(
          data_providers.back().get());
    }

    // Transaction must be created after DataProviders, so it's destroyed before
    // they are as well.
    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    for (int round = 0; round < test_config.num_auth_rounds; ++round) {
      SCOPED_TRACE(round);
      const TestRound& read_write_round = test_config.rounds[round];
      // Start or restart the transaction.
      TestCompletionCallback callback;
      int rv;
      if (round == 0) {
        rv = trans.Start(&request, callback.callback(), NetLogWithSource());
      } else {
        rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
                                   callback.callback());
      }
      if (rv == ERR_IO_PENDING) {
        rv = callback.WaitForResult();
      }

      // Compare results with expected data.
      EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
      const HttpResponseInfo* response = trans.GetResponseInfo();
      if (read_write_round.expected_rv != OK) {
        EXPECT_EQ(round + 1, test_config.num_auth_rounds);
        continue;
      }
      if (round + 1 < test_config.num_auth_rounds) {
        EXPECT_TRUE(response->auth_challenge.has_value());
      } else {
        EXPECT_FALSE(response->auth_challenge.has_value());
        EXPECT_FALSE(trans.IsReadyToRestartForAuth());
      }
    }
  }
}

TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
  // Do multi-round authentication and make sure it works correctly.
  auto auth_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
  auto* auth_factory_ptr = auth_factory.get();
  session_deps_.http_auth_handler_factory = std::move(auth_factory);
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateDirect();
  session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");

  auto auth_handler = std::make_unique<HttpAuthHandlerMock>();
  auto* auth_handler_ptr = auth_handler.get();
  auth_handler->set_connection_based(true);
  GURL url("http://www.example.com");
  HttpAuthChallengeTokenizer tokenizer("Mock realm=server");
  SSLInfo empty_ssl_info;
  auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
                                  empty_ssl_info, NetworkAnonymizationKey(),
                                  url::SchemeHostPort(url), NetLogWithSource());
  auth_factory_ptr->AddMockHandler(std::move(auth_handler),
                                   HttpAuth::AUTH_SERVER);

  int rv = OK;
  const HttpResponseInfo* response = nullptr;
  HttpRequestInfo request;
  request.method = "GET";
  request.url = url;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Use a TCP Socket Pool with only one connection per group. This is used
  // to validate that the TCP socket is not released to the pool between
  // each round of multi-round authentication.
  constexpr size_t kMaxSocketsPerPool = 50u;
  constexpr size_t kMaxSocketsPerGroup = 1u;
  HttpNetworkSessionPeer session_peer(session.get());
  CommonConnectJobParams common_connect_job_params(
      session->CreateCommonConnectJobParams());
  auto transport_pool = std::make_unique<TransportClientSocketPool>(
      kMaxSocketsPerPool,   // Max sockets for pool
      kMaxSocketsPerGroup,  // Max sockets per group
      SocketPoolAdditionalCapacity::Create(),
      /*unused_idle_socket_timeout=*/base::Seconds(10), ProxyChain::Direct(),
      /*is_for_websockets=*/false, &common_connect_job_params);
  auto* transport_pool_ptr = transport_pool.get();
  auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
  mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
                                   std::move(transport_pool));
  session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));

  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    session->http_stream_pool()->set_max_stream_sockets_per_group_for_testing(
        kMaxSocketsPerGroup);
    session->http_stream_pool()->set_max_stream_sockets_per_pool_for_testing(
        kMaxSocketsPerPool);
  }

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;

  const MockWrite kGet(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Connection: keep-alive\r\n\r\n");
  const MockWrite kGetAuth(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.com\r\n"
      "Connection: keep-alive\r\n"
      "Authorization: auth_token\r\n\r\n");

  const MockRead kServerChallenge(
      "HTTP/1.1 401 Unauthorized\r\n"
      "WWW-Authenticate: Mock realm=server\r\n"
      "Content-Type: text/html; charset=iso-8859-1\r\n"
      "Content-Length: 14\r\n\r\n"
      "Unauthorized\r\n");
  const MockRead kSuccess(
      "HTTP/1.1 200 OK\r\n"
      "Content-Type: text/html; charset=iso-8859-1\r\n"
      "Content-Length: 3\r\n\r\n"
      "Yes");

  MockWrite writes[] = {
      // First round
      kGet,
      // Second round
      kGetAuth,
      // Third round
      kGetAuth,
      // Fourth round
      kGetAuth,
      // Competing request
      kGet,
  };
  MockRead reads[] = {
      // First round
      kServerChallenge,
      // Second round
      kServerChallenge,
      // Third round
      kServerChallenge,
      // Fourth round
      kSuccess,
      // Competing response
      kSuccess,
  };
  StaticSocketDataProvider data_provider(reads, writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data_provider);

  const ClientSocketPool::GroupId kSocketGroup(
      url::SchemeHostPort(url::kHttpScheme, "www.example.com", 80),
      PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
      SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false);
  const HttpStreamKey kHttpStreamKey(GroupIdToHttpStreamKey(kSocketGroup));

  auto IdleSocketCountInGroup = [&] {
    if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
      return session->http_stream_pool()
          ->GetOrCreateGroupForTesting(kHttpStreamKey)
          .IdleStreamSocketCount();
    } else {
      return transport_pool_ptr->IdleSocketCountInGroup(kSocketGroup);
    }
  };

  // First round of authentication.
  auth_handler_ptr->SetGenerateExpectation(false, OK);
  rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_THAT(rv, IsOk());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_TRUE(response->auth_challenge.has_value());
  EXPECT_EQ(0u, IdleSocketCountInGroup());
  EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
            auth_handler_ptr->state());

  // In between rounds, another request comes in for the same domain.
  // It should not be able to grab the TCP socket that trans has already
  // claimed.
  HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback_compete;
  rv = trans_compete.Start(&request, callback_compete.callback(),
                           NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  // callback_compete.WaitForResult at this point would stall forever,
  // since the HttpNetworkTransaction does not release the request back to
  // the pool until after authentication completes.

  // Second round of authentication.
  auth_handler_ptr->SetGenerateExpectation(false, OK);
  rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_THAT(rv, IsOk());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(0u, IdleSocketCountInGroup());
  EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
            auth_handler_ptr->state());

  // Third round of authentication.
  auth_handler_ptr->SetGenerateExpectation(false, OK);
  rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_THAT(rv, IsOk());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(0u, IdleSocketCountInGroup());
  EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
            auth_handler_ptr->state());

  // Fourth round of authentication, which completes successfully.
  auth_handler_ptr->SetGenerateExpectation(false, OK);
  rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_THAT(rv, IsOk());
  response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_FALSE(response->auth_challenge.has_value());
  EXPECT_EQ(0u, IdleSocketCountInGroup());

  // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
  // auth handler should transition to a DONE state in concert with the remote
  // server. But that's not something we can test here with a mock handler.
  EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
            auth_handler_ptr->state());

  // Read the body since the fourth round was successful. This will also
  // release the socket back to the pool.
  scoped_refptr<IOBufferWithSize> io_buf =
      base::MakeRefCounted<IOBufferWithSize>(50);
  rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_EQ(3, rv);
  rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
  EXPECT_EQ(0, rv);
  // There are still 0 idle sockets, since the trans_compete transaction
  // will be handed it immediately after trans releases it to the group.
  EXPECT_EQ(0u, IdleSocketCountInGroup());

  // The competing request can now finish. Wait for the headers and then
  // read the body.
  rv = callback_compete.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  EXPECT_EQ(3, rv);
  rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
  EXPECT_EQ(0, rv);

  // Finally, the socket is released to the group.
  EXPECT_EQ(1u, IdleSocketCountInGroup());
}

// This tests the case that a request is issued via http instead of spdy after
// npn is negotiated.
TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead(kAlternativeServiceHttpHeader),
      MockRead("\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP11;

  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());

  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
}

// Simulate the SSL handshake completing with a ALPN negotiation followed by an
// immediate server closing of the socket.
// Regression test for https://crbug.com/46369.
TEST_P(HttpNetworkTransactionTest, SpdyPostALPNServerHangup) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(
      base::span<const std::string_view>(), 1, LOWEST));
  MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};

  MockRead spdy_reads[] = {
      MockRead(SYNCHRONOUS, 0, 0)  // Not async - return 0 immediately.
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  TestCompletionCallback callback;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
}

// A subclass of HttpAuthHandlerMock that records the request URL when
// it gets it. This is needed since the auth handler may get destroyed
// before we get a chance to query it.
class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
 public:
  explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}

  ~UrlRecordingHttpAuthHandlerMock() override = default;

 protected:
  int GenerateAuthTokenImpl(const AuthCredentials* credentials,
                            const HttpRequestInfo* request,
                            CompletionOnceCallback callback,
                            std::string* auth_token) override {
    *url_ = request->url;
    return HttpAuthHandlerMock::GenerateAuthTokenImpl(
        credentials, request, std::move(callback), auth_token);
  }

 private:
  raw_ptr<GURL> url_ = nullptr;
};

// Test that if we cancel the transaction as the connection is completing, that
// everything tears down correctly.
TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
  // Setup everything about the connection to complete synchronously, so that
  // after calling HttpNetworkTransaction::Start, the only thing we're waiting
  // for is the callback from the HttpStreamRequest.
  // Then cancel the transaction.
  // Verify that we don't crash.
  MockConnect mock_connect(SYNCHRONOUS, OK);
  MockRead data_reads[] = {
      MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
      MockRead(SYNCHRONOUS, "hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans->Start(&request, callback.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  trans.reset();  // Cancel the transaction here.

  base::RunLoop().RunUntilIdle();
}

// Test that if a transaction is cancelled after receiving the headers, the
// stream is drained properly and added back to the socket pool.  The main
// purpose of this test is to make sure that an HttpStreamParser can be read
// from after the HttpNetworkTransaction and the objects it owns have been
// deleted.
// See http://crbug.com/368418
TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
  MockRead data_reads[] = {
      MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
      MockRead(ASYNC, "Content-Length: 2\r\n"),
      MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"), MockRead(ASYNC, "1"),
      // 2 async reads are necessary to trigger a ReadResponseBody call after
      // the HttpNetworkTransaction has been deleted.
      MockRead(ASYNC, "2"),
      MockRead(SYNCHRONOUS, ERR_IO_PENDING),  // Should never read this.
  };
  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.example.org/");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
    TestCompletionCallback callback;

    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
    callback.WaitForResult();

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    EXPECT_TRUE(response->headers);
    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());

    // The transaction and HttpRequestInfo are deleted.
  }

  // Let the HttpResponseBodyDrainer drain the socket.
  base::RunLoop().RunUntilIdle();

  // Socket should now be idle, waiting to be reused.
  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Test a basic GET request through a proxy.
TEST_P(HttpNetworkTransactionTest, ProxyGet) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes1[] = {
      MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  ConnectedHandler connected_handler;
  trans.SetConnectedCallback(connected_handler.Callback());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(response->WasFetchedViaProxy());
  EXPECT_FALSE(response->proxy_chain.is_for_ip_protection());
  EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
                       HostPortPair::FromString("myproxy:70")),
            response->proxy_chain);
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
}

// Test a basic HTTPS GET request through a proxy.
TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  ConnectedHandler connected_handler;
  trans.SetConnectedCallback(connected_handler.Callback());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(response->WasFetchedViaProxy());
  EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
                       HostPortPair::FromString("myproxy:70")),
            response->proxy_chain);

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kProxied;
  expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
  expected_transport.negotiated_protocol = NextProto::kProtoUnknown;
  EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);
}

// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
// literal host.
TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://[::2]:443/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
                "Host: [::2]:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: [::2]\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());
  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers->IsKeepAlive());
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(100, response->headers->GetContentLength()->InBytes());
  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
  EXPECT_TRUE(response->WasFetchedViaProxy());
  EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
                       HostPortPair::FromString("myproxy:70")),
            response->proxy_chain);

  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
  TestLoadTimingNotReusedWithPac(load_timing_info,
                                 CONNECT_TIMING_HAS_SSL_TIMES);
}

// Test a basic HTTPS GET request through a proxy, but the server hangs up
// while establishing the tunnel.
TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  RecordingNetLogObserver net_log_observer;
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead(ASYNC, 0, 0),  // EOF
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
  auto entries = net_log_observer.GetEntries();
  size_t pos = ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
      NetLogEventPhase::NONE);
  ExpectLogContainsSomewhere(
      entries, pos,
      NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
      NetLogEventPhase::NONE);
}

// Test for crbug.com/55424.
TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy_reads[] = {
      CreateMockRead(resp, 1),
      CreateMockRead(data, 2),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data(spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Set up an initial SpdySession in the pool to reuse.
  HostPortPair host_port_pair("www.example.org", 443);
  SpdySessionKey key(host_port_pair, PRIVACY_MODE_DISABLED,
                     ProxyChain::Direct(), SessionUsage::kDestination,
                     SocketTag(), NetworkAnonymizationKey(),
                     SecureDnsPolicy::kAllow,
                     /*disable_cert_verification_network_fetches=*/false);
  base::WeakPtr<SpdySession> spdy_session =
      CreateSpdySession(session.get(), key, NetLogWithSource());

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());
}

// Given a net error, cause that error to be returned from the first Write()
// call and verify that the HttpNetworkTransaction fails with that error.
void HttpNetworkTransactionTestBase::CheckErrorIsPassedBack(int error,
                                                            IoMode mode) {
  HttpRequestInfo request_info;
  request_info.url = GURL("https://www.example.com/");
  request_info.method = "GET";
  request_info.load_flags = LOAD_NORMAL;
  request_info.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  SSLSocketDataProvider ssl_data(mode, OK);
  MockWrite data_writes[] = {
      MockWrite(mode, error),
  };
  StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
  if (rv == ERR_IO_PENDING) {
    rv = callback.WaitForResult();
  }
  ASSERT_EQ(error, rv);
}

TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
  // Just check a grab bag of cert errors.
  static const int kErrors[] = {
      ERR_CERT_COMMON_NAME_INVALID,
      ERR_CERT_AUTHORITY_INVALID,
      ERR_CERT_DATE_INVALID,
  };
  for (int error : kErrors) {
    CheckErrorIsPassedBack(error, ASYNC);
    CheckErrorIsPassedBack(error, SYNCHRONOUS);
  }
}

// Ensure that a client certificate is removed from the SSL client auth
// cache when:
//  1) No proxy is involved.
//  2) TLS False Start is disabled.
//  3) The initial TLS handshake requests a client certificate.
//  4) The client supplies an invalid/unacceptable certificate.
TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
  HttpRequestInfo request_info;
  request_info.url = GURL("https://www.example.com/");
  request_info.method = "GET";
  request_info.load_flags = LOAD_NORMAL;
  request_info.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request->host_and_port = HostPortPair("www.example.com", 443);

  // [ssl_]data1 contains the data for the first SSL handshake. When a
  // CertificateRequest is received for the first time, the handshake will
  // be aborted to allow the caller to provide a certificate.
  SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl_data1.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
  StaticSocketDataProvider data1;
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // [ssl_]data2 contains the data for the second SSL handshake. When TLS
  // False Start is not being used, the result of the SSL handshake will be
  // returned as part of the SSLClientSocket::Connect() call. This test
  // matches the result of a server sending a handshake_failure alert,
  // rather than a Finished message, because it requires a client
  // certificate and none was supplied.
  SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
  ssl_data2.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
  StaticSocketDataProvider data2;
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  // [ssl_]data3 contains the data for the third SSL handshake. When a
  // connection to a server fails during an SSL handshake,
  // HttpNetworkTransaction will attempt to fallback with legacy cryptography
  // enabled on some errors. This is transparent to the caller
  // of the HttpNetworkTransaction. Because this test failure is due to
  // requiring a client certificate, this fallback handshake should also
  // fail.
  SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
  ssl_data3.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
  StaticSocketDataProvider data3;
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Begin the SSL handshake with the peer. This consumes ssl_data1.
  TestCompletionCallback callback;
  int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
  ASSERT_THAT(rv, IsError(ERR_IO_PENDING));

  // Complete the SSL handshake, which should abort due to requiring a
  // client certificate.
  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));

  // Indicate that no certificate should be supplied. From the perspective
  // of SSLClientCertCache, NULL is just as meaningful as a real
  // certificate, so this is the same as supply a
  // legitimate-but-unacceptable certificate.
  rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
  ASSERT_THAT(rv, IsError(ERR_IO_PENDING));

  // Ensure the certificate was added to the client auth cache before
  // allowing the connection to continue restarting.
  scoped_refptr<X509Certificate> client_cert;
  scoped_refptr<SSLPrivateKey> client_private_key;
  ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
      HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
  ASSERT_FALSE(client_cert);

  // Restart the handshake. This will consume ssl_data2, which fails, and
  // then consume ssl_data3 and ssl_data4, both of which should also fail.
  // The result code is checked against what ssl_data4 should return.
  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));

  // Ensure that the client certificate is removed from the cache on a
  // handshake failure.
  ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
      HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
}

// Ensure that a client certificate is removed from the SSL client auth
// cache when:
//  1) No proxy is involved.
//  2) TLS False Start is enabled.
//  3) The initial TLS handshake requests a client certificate.
//  4) The client supplies an invalid/unacceptable certificate.
TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
  HttpRequestInfo request_info;
  request_info.url = GURL("https://www.example.com/");
  request_info.method = "GET";
  request_info.load_flags = LOAD_NORMAL;
  request_info.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request->host_and_port = HostPortPair("www.example.com", 443);

  // When TLS False Start is used, SSLClientSocket::Connect() calls will
  // return successfully after reading up to the peer's Certificate message.
  // This is to allow the caller to call SSLClientSocket::Write(), which can
  // enqueue application data to be sent in the same packet as the
  // ChangeCipherSpec and Finished messages.
  // The actual handshake will be finished when SSLClientSocket::Read() is
  // called, which expects to process the peer's ChangeCipherSpec and
  // Finished messages. If there was an error negotiating with the peer,
  // such as due to the peer requiring a client certificate when none was
  // supplied, the alert sent by the peer won't be processed until Read() is
  // called.

  // Like the non-False Start case, when a client certificate is requested by
  // the peer, the handshake is aborted during the Connect() call.
  // [ssl_]data1 represents the initial SSL handshake with the peer.
  SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl_data1.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
  StaticSocketDataProvider data1;
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // When a client certificate is supplied, Connect() will not be aborted
  // when the peer requests the certificate. Instead, the handshake will
  // artificially succeed, allowing the caller to write the HTTP request to
  // the socket. The handshake messages are not processed until Read() is
  // called, which then detects that the handshake was aborted, due to the
  // peer sending a handshake_failure because it requires a client
  // certificate.
  SSLSocketDataProvider ssl_data2(ASYNC, OK);
  ssl_data2.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
  MockRead data2_reads[] = {
      MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
  };
  StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
  // the data for the SSL handshake once the TLSv1.1 connection falls back to
  // TLSv1. It has the same behaviour as [ssl_]data2.
  SSLSocketDataProvider ssl_data3(ASYNC, OK);
  ssl_data3.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
  StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
  // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
  SSLSocketDataProvider ssl_data4(ASYNC, OK);
  ssl_data4.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
  StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data4);

  // Need one more if TLSv1.2 is enabled.
  SSLSocketDataProvider ssl_data5(ASYNC, OK);
  ssl_data5.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
  StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data5);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Begin the initial SSL handshake.
  TestCompletionCallback callback;
  int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
  ASSERT_THAT(rv, IsError(ERR_IO_PENDING));

  // Complete the SSL handshake, which should abort due to requiring a
  // client certificate.
  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));

  // Indicate that no certificate should be supplied. From the perspective
  // of SSLClientCertCache, NULL is just as meaningful as a real
  // certificate, so this is the same as supply a
  // legitimate-but-unacceptable certificate.
  rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
  ASSERT_THAT(rv, IsError(ERR_IO_PENDING));

  // Ensure the certificate was added to the client auth cache before
  // allowing the connection to continue restarting.
  scoped_refptr<X509Certificate> client_cert;
  scoped_refptr<SSLPrivateKey> client_private_key;
  ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
      HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
  ASSERT_FALSE(client_cert);

  // Restart the handshake. This will consume ssl_data2, which fails, and
  // then consume ssl_data3 and ssl_data4, both of which should also fail.
  // The result code is checked against what ssl_data4 should return.
  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));

  // Ensure that the client certificate is removed from the cache on a
  // handshake failure.
  ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
      HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
}

// Ensure that a client certificate is removed from the SSL client auth
// cache when:
//  1) An HTTPS proxy is involved.
//  3) The HTTPS proxy requests a client certificate.
//  4) The client supplies an invalid/unacceptable certificate for the
//     proxy.
TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();

  auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request->host_and_port = HostPortPair("proxy", 70);

  // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
  // an HTTP endpoint.
  std::array<HttpRequestInfo, 2> requests;
  requests[0].url = GURL("https://www.example.com/");
  requests[0].method = "GET";
  requests[0].load_flags = LOAD_NORMAL;
  requests[0].traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // HTTPS requests are tunneled.
  MockWrite https_writes[] = {
      MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
                "Host: www.example.com:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  requests[1].url = GURL("http://www.example.com/");
  requests[1].method = "GET";
  requests[1].load_flags = LOAD_NORMAL;
  requests[1].traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // HTTP requests are not.
  MockWrite http_writes[] = {
      MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
                "Host: www.example.com\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n"),
  };

  // When the server rejects the client certificate, it will close the
  // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
  // TLS 1.2 with False Start), the error is returned out of the first Read().
  for (bool reject_in_connect : {true, false}) {
    SCOPED_TRACE(reject_in_connect);
    // Client certificate errors are typically signaled with
    // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
    // protocol error.
    for (Error reject_error :
         {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
      SCOPED_TRACE(reject_error);
      // Tunneled and non-tunneled requests are handled differently. Test both.
      for (const HttpRequestInfo& request : requests) {
        SCOPED_TRACE(request.url);

        session_deps_.socket_factory =
            std::make_unique<MockClientSocketFactory>();

        // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
        // [ssl_]data[1-3].
        SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
        ssl_data1.cert_request_info = cert_request;
        session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
        StaticSocketDataProvider data1;
        session_deps_.socket_factory->AddSocketDataProvider(&data1);

        std::optional<SSLSocketDataProvider> ssl_data2;
        std::optional<StaticSocketDataProvider> data2;
        MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
        if (reject_in_connect) {
          ssl_data2.emplace(ASYNC, reject_error);
          // There are no reads or writes.
          data2.emplace();
        } else {
          ssl_data2.emplace(ASYNC, OK);
          // We will get one Write() in before observing the error in Read().
          if (request.url.SchemeIsCryptographic()) {
            data2.emplace(error_in_read, https_writes);
          } else {
            data2.emplace(error_in_read, http_writes);
          }
        }
        ssl_data2->cert_request_info = cert_request.get();
        session_deps_.socket_factory->AddSSLSocketDataProvider(
            &ssl_data2.value());
        session_deps_.socket_factory->AddSocketDataProvider(&data2.value());

        // If the handshake returns ERR_SSL_PROTOCOL_ERROR, we attempt to
        // connect twice.
        std::optional<SSLSocketDataProvider> ssl_data3;
        std::optional<StaticSocketDataProvider> data3;
        if (reject_in_connect && reject_error == ERR_SSL_PROTOCOL_ERROR) {
          ssl_data3.emplace(ASYNC, reject_error);
          data3.emplace();  // There are no reads or writes.
          ssl_data3->cert_request_info = cert_request.get();
          session_deps_.socket_factory->AddSSLSocketDataProvider(
              &ssl_data3.value());
          session_deps_.socket_factory->AddSocketDataProvider(&data3.value());
        }

        std::unique_ptr<HttpNetworkSession> session =
            CreateSession(&session_deps_);
        HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

        // Begin the SSL handshake with the proxy.
        TestCompletionCallback callback;
        int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
        ASSERT_THAT(rv, IsError(ERR_IO_PENDING));

        // Complete the SSL handshake, which should abort due to requiring a
        // client certificate.
        rv = callback.WaitForResult();
        ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));

        // Indicate that no certificate should be supplied. From the
        // perspective of SSLClientCertCache, NULL is just as meaningful as a
        // real certificate, so this is the same as supply a
        // legitimate-but-unacceptable certificate.
        rv =
            trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
        ASSERT_THAT(rv, IsError(ERR_IO_PENDING));

        // Ensure the certificate was added to the client auth cache before
        // allowing the connection to continue restarting.
        scoped_refptr<X509Certificate> client_cert;
        scoped_refptr<SSLPrivateKey> client_private_key;
        ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
            HostPortPair("proxy", 70), &client_cert, &client_private_key));
        ASSERT_FALSE(client_cert);
        // Ensure the certificate was NOT cached for the endpoint. This only
        // applies to HTTPS requests, but is fine to check for HTTP requests.
        ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
            HostPortPair("www.example.com", 443), &client_cert,
            &client_private_key));

        // Restart the handshake. This will consume ssl_data2. The result code
        // is checked against what ssl_data2 should return.
        rv = callback.WaitForResult();
        ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
                              IsError(reject_error)));

        // Now that the new handshake has failed, ensure that the client
        // certificate was removed from the client auth cache.
        ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
            HostPortPair("proxy", 70), &client_cert, &client_private_key));
        ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
            HostPortPair("www.example.com", 443), &client_cert,
            &client_private_key));
      }
    }
  }
}

// Test that HttpNetworkTransaction correctly handles (mocked) certificate
// requests during a TLS renegotiation.
TEST_P(HttpNetworkTransactionTest, CertificateRequestInRenego) {
  HttpRequestInfo request_info;
  request_info.url = GURL("https://www.example.com/");
  request_info.method = "GET";
  request_info.load_flags = LOAD_NORMAL;
  request_info.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request->host_and_port = HostPortPair("www.example.com", 443);

  std::unique_ptr<FakeClientCertIdentity> identity =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
  ASSERT_TRUE(identity);

  // The first connection's handshake succeeds, but we get
  // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
  SSLSocketDataProvider ssl_data1(ASYNC, OK);
  ssl_data1.cert_request_info = cert_request;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
  MockWrite data1_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead data1_reads[] = {
      MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
  };
  StaticSocketDataProvider data1(data1_reads, data1_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // After supplying with certificate, we restart the request from the top,
  // which succeeds this time.
  SSLSocketDataProvider ssl_data2(ASYNC, OK);
  ssl_data2.expected_send_client_cert = true;
  ssl_data2.expected_client_cert = identity->certificate();
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
  MockWrite data2_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead data2_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Length: 0\r\n\r\n"),
  };
  StaticSocketDataProvider data2(data2_reads, data2_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = callback.GetResult(
      trans.Start(&request_info, callback.callback(), NetLogWithSource()));
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));

  rv = trans.RestartWithCertificate(identity->certificate(),
                                    identity->ssl_private_key(),
                                    callback.callback());
  ASSERT_THAT(rv, IsError(ERR_IO_PENDING));

  // Ensure the certificate was added to the client auth cache
  // allowing the connection to continue restarting.
  scoped_refptr<X509Certificate> client_cert;
  scoped_refptr<SSLPrivateKey> client_private_key;
  ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
      HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
  EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));

  // Complete the handshake. The request now succeeds.
  rv = callback.WaitForResult();
  ASSERT_THAT(rv, IsError(OK));
  EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());

  // The client certificate remains in the cache.
  ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
      HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
  EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
}

TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
  session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  AddSSLSocketData();

  spdy::SpdySerializedFrame host1_req(
      spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
  spdy_util_.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame host2_req(
      spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
  MockWrite spdy_writes[] = {
      CreateMockWrite(host1_req, 0),
      CreateMockWrite(host2_req, 3),
  };
  spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame host1_resp_body(
      spdy_util_.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame host2_resp_body(
      spdy_util_.ConstructSpdyDataFrame(3, true));
  MockRead spdy_reads[] = {
      CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
      CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
      MockRead(ASYNC, 0, 6),
  };

  IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
  MockConnect connect(ASYNC, OK, peer_addr);
  SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  LoadTimingInternalInfo load_timing_internal1;
  trans1.PopulateLoadTimingInternalInfo(&load_timing_internal1);
  EXPECT_THAT(load_timing_internal1.session_source,
              ::testing::Optional(SessionSource::kNew));

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  // Preload mail.example.com into HostCache.
  rv = session_deps_.host_resolver->LoadIntoCache(
      HostPortPair("mail.example.com", 443), NetworkAnonymizationKey(),
      std::nullopt);
  EXPECT_THAT(rv, IsOk());

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.com/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  ConnectedHandler connected_handler2;
  trans2.SetConnectedCallback(connected_handler2.Callback());

  rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  TransportInfo expected_transport;
  expected_transport.type = TransportType::kDirect;
  expected_transport.endpoint = IPEndPoint(IPAddress(1, 2, 3, 4), 443);
  expected_transport.negotiated_protocol = NextProto::kProtoHTTP2;
  EXPECT_THAT(connected_handler2.transports(), ElementsAre(expected_transport));

  LoadTimingInternalInfo load_timing_internal2;
  trans2.PopulateLoadTimingInternalInfo(&load_timing_internal2);
  EXPECT_THAT(load_timing_internal2.session_source,
              ::testing::Optional(SessionSource::kExisting));

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
  session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  AddSSLSocketData();

  spdy::SpdySerializedFrame host1_req(
      spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
  spdy_util_.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame host2_req(
      spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
  MockWrite spdy_writes[] = {
      CreateMockWrite(host1_req, 0),
      CreateMockWrite(host2_req, 3),
  };
  spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame host1_resp_body(
      spdy_util_.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame host2_resp_body(
      spdy_util_.ConstructSpdyDataFrame(3, true));
  MockRead spdy_reads[] = {
      CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
      CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
      MockRead(ASYNC, 0, 6),
  };

  IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
  MockConnect connect(ASYNC, OK, peer_addr);
  SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.com/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

// Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
// won't alias with a session directly to a host even if direct connections to
// the proxy server host and to the other host would alias. The request through
// the proxy is made using SPDY.
TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForProxyAndHostSpdy) {
  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
  session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(example_proxy_server_chain_);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to request1.test:443 via SPDY.
  spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("request1.test", 443)));
  spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));

  // Fetch https://request1.test/ via SPDY.
  SpdyTestUtil req1_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame get1(
      req1_spdy_util.ConstructSpdyGet("https://request1.test/", 1, LOWEST));
  spdy::SpdySerializedFrame wrapped_get1(
      spdy_util_.ConstructWrappedSpdyFrame(get1, 1));
  spdy::SpdySerializedFrame get_resp1(req1_spdy_util.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame wrapped_get_resp1(
      spdy_util_.ConstructWrappedSpdyFrame(get_resp1, 1));

  spdy::SpdySerializedFrame body1(
      req1_spdy_util.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_body1(
      spdy_util_.ConstructWrappedSpdyFrame(body1, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(connect1, 0),
      CreateMockWrite(wrapped_get1, 2),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(conn_resp1, 1),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(wrapped_get_resp1, 4),
      CreateMockRead(wrapped_body1, 5),
      // Pause reads so that the socket will remain open (so we can see whether
      // it gets re-used below).
      MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7)};

  IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
  MockConnect connect(ASYNC, OK, peer_addr);
  SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  AddSSLSocketData();
  AddSSLSocketData();

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://request1.test/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);

  proxy_delegate->set_proxy_chain(ProxyChain::Direct());

  SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req2(
      req2_spdy_util.ConstructSpdyGet("https://mail.example.com/", 1, LOWEST));

  spdy::SpdySerializedFrame resp2(req2_spdy_util.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data2(
      req2_spdy_util.ConstructSpdyDataFrame(1, true));

  MockWrite spdy_writes2[] = {
      CreateMockWrite(req2, 0),
  };
  MockRead spdy_reads2[] = {
      CreateMockRead(resp2, 1),
      CreateMockRead(data2, 2),
      MockRead(ASYNC, 0, 3),
  };
  SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);

  AddSSLSocketData();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.com/");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback2;

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

// Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
// won't alias with a session directly to a host even if direct connections to
// the proxy server host and to the other host would alias. The request through
// the proxy is made using HTTP.
TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForProxyAndHostHttp) {
  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
  session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(example_proxy_server_chain_);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("http://request1.test/", 1, LOWEST));
  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));

  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  MockRead spdy_reads[] = {CreateMockRead(resp, 1), CreateMockRead(data, 2),
                           // Pause reads so that the socket will remain open
                           // (so we can see whether it gets re-used below).
                           MockRead(ASYNC, ERR_IO_PENDING, 3),
                           MockRead(ASYNC, 0, 4)};

  IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
  MockConnect connect(ASYNC, OK, peer_addr);
  SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  AddSSLSocketData();

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("http://request1.test/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);

  proxy_delegate->set_proxy_chain(ProxyChain::Direct());

  SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req2(
      req2_spdy_util.ConstructSpdyGet("https://mail.example.com/", 1, LOWEST));

  spdy::SpdySerializedFrame resp2(req2_spdy_util.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data2(
      req2_spdy_util.ConstructSpdyDataFrame(1, true));

  MockWrite spdy_writes2[] = {
      CreateMockWrite(req2, 0),
  };
  MockRead spdy_reads2[] = {
      CreateMockRead(resp2, 1),
      CreateMockRead(data2, 2),
      MockRead(ASYNC, 0, 3),
  };
  SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);

  AddSSLSocketData();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.com/");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback2;

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

// Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
// won't alias with another proxy session even if direct connections to the
// proxy servers hosts themselves would alias. The requests through the proxy
// are made using SPDY.
TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForTwoProxiesSpdy) {
  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
  session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");

  const ProxyServer kExampleProxyServer2{ProxyServer::SCHEME_HTTPS,
                                         HostPortPair("mail.example.com", 443)};
  const ProxyChain kExampleProxyServer2Chain{{
      kExampleProxyServer2,
  }};

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(example_proxy_server_chain_);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);

  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // CONNECT to request1.test:443 via SPDY.
  spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("request1.test", 443)));
  spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));

  // Fetch https://request1.test/ via SPDY.
  SpdyTestUtil req1_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame get1(
      req1_spdy_util.ConstructSpdyGet("https://request1.test/", 1, LOWEST));
  spdy::SpdySerializedFrame wrapped_get1(
      spdy_util_.ConstructWrappedSpdyFrame(get1, 1));
  spdy::SpdySerializedFrame get_resp1(req1_spdy_util.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame wrapped_get_resp1(
      spdy_util_.ConstructWrappedSpdyFrame(get_resp1, 1));

  spdy::SpdySerializedFrame body1(
      req1_spdy_util.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_body1(
      spdy_util_.ConstructWrappedSpdyFrame(body1, 1));

  MockWrite spdy_writes[] = {
      CreateMockWrite(connect1, 0),
      CreateMockWrite(wrapped_get1, 2),
  };

  MockRead spdy_reads[] = {
      CreateMockRead(conn_resp1, 1),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(wrapped_get_resp1, 4),
      CreateMockRead(wrapped_body1, 5),
      // Pause reads so that the socket will remain open (so we can see whether
      // it gets re-used below).
      MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7)};

  IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
  MockConnect connect(ASYNC, OK, peer_addr);
  SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  AddSSLSocketData();
  AddSSLSocketData();

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://request1.test/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data.Resume();

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);

  proxy_delegate->set_proxy_chain(kExampleProxyServer2Chain);

  // CONNECT to request2.test:443 via SPDY.
  SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame connect2(req2_spdy_util.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority,
      HostPortPair("request2.test", 443)));
  spdy::SpdySerializedFrame conn_resp2(req2_spdy_util.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));

  // Fetch https://request2.test/ via SPDY.
  SpdyTestUtil wrapped_req2_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame get2(wrapped_req2_spdy_util.ConstructSpdyGet(
      "https://request2.test/", 1, LOWEST));
  spdy::SpdySerializedFrame wrapped_get2(
      req2_spdy_util.ConstructWrappedSpdyFrame(get2, 1));
  spdy::SpdySerializedFrame get_resp2(
      wrapped_req2_spdy_util.ConstructSpdyGetReply(
          base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame wrapped_get_resp2(
      req2_spdy_util.ConstructWrappedSpdyFrame(get_resp2, 1));

  spdy::SpdySerializedFrame body2(
      wrapped_req2_spdy_util.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_body2(
      req2_spdy_util.ConstructWrappedSpdyFrame(body2, 1));

  MockWrite spdy_writes2[] = {
      CreateMockWrite(connect2, 0),
      CreateMockWrite(wrapped_get2, 2),
  };

  MockRead spdy_reads2[] = {
      CreateMockRead(conn_resp2, 1),
      // TODO(crbug.com/41180906): We have to manually delay this read so
      // that the higher-level SPDY stream doesn't get notified of an available
      // read before the write it initiated (the second CONNECT) finishes,
      // triggering a DCHECK.
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_get_resp2, 4),
      CreateMockRead(wrapped_body2, 5),
      MockRead(ASYNC, 0, 6),
  };

  SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);

  AddSSLSocketData();
  AddSSLSocketData();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://request2.test/");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback2;

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  spdy_data2.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  spdy_data2.Resume();

  rv = callback2.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

// Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
// won't alias with another proxy session even if direct connections to the
// proxy servers hosts themselves would alias. The requests through the proxy
// are made using HTTP.
TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForTwoProxiesHttp) {
  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
  session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");

  const ProxyServer kExampleProxyServer2{ProxyServer::SCHEME_HTTPS,
                                         HostPortPair("mail.example.com", 443)};
  const ProxyChain kExampleProxyServer2Chain{{
      kExampleProxyServer2,
  }};

  session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
  auto* proxy_delegate =
      static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(example_proxy_server_chain_);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  spdy::SpdySerializedFrame req(
      spdy_util_.ConstructSpdyGet("http://request1.test/", 1, LOWEST));
  spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));

  MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};

  MockRead spdy_reads[] = {CreateMockRead(resp, 1), CreateMockRead(data, 2),
                           // Pause reads so that the socket will remain open
                           // (so we can see whether it gets re-used below).
                           MockRead(ASYNC, ERR_IO_PENDING, 3),
                           MockRead(ASYNC, 0, 4)};

  IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
  MockConnect connect(ASYNC, OK, peer_addr);
  SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  AddSSLSocketData();

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("http://request1.test/");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback1;

  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback1.callback(),
                        NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ(kUploadData, response_data);

  proxy_delegate->set_proxy_chain(kExampleProxyServer2Chain);

  SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req2(
      req2_spdy_util.ConstructSpdyGet("http://request2.test/", 1, LOWEST));

  spdy::SpdySerializedFrame resp2(req2_spdy_util.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame data2(
      req2_spdy_util.ConstructSpdyDataFrame(1, true));

  MockWrite spdy_writes2[] = {CreateMockWrite(req2, 0)};

  MockRead spdy_reads2[] = {
      CreateMockRead(resp2, 1),
      CreateMockRead(data2, 2),
      MockRead(ASYNC, 0, 3),
  };

  SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);

  AddSSLSocketData();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("http://request2.test/");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback2;

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback2.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback2.WaitForResult();
  ASSERT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

// Regression test for https://crbug.com/546991.
// The server might not be able to serve an IP pooled request, and might send a
// 421 Misdirected Request response status to indicate this.
// HttpNetworkTransaction should reset the request and retry without IP pooling.
TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
  // Two hosts resolve to the same IP address.
  const std::string ip_addr = "1.2.3.4";
  IPAddress ip;
  ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
  IPEndPoint peer_addr = IPEndPoint(ip, 443);

  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
  session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Two requests on the first H2 connection.
  spdy::SpdySerializedFrame req1(
      spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
  spdy_util_.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame req2(
      spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
  MockWrite writes1[] = {
      CreateMockWrite(req1, 0),
      CreateMockWrite(req2, 3),
      CreateMockWrite(rst, 6),
  };

  // The first request succeeds, the second request gets error 421 Misdirected
  // Request. The first H2 connection remains available after getting 421.
  spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
  quiche::HttpHeaderBlock response_headers;
  response_headers[spdy::kHttp2StatusHeader] = "421";
  spdy::SpdySerializedFrame resp2(
      spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
  MockRead reads1[] = {
      CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
      CreateMockRead(resp2, 4),
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) /* stalls forever */};

  MockConnect connect1(ASYNC, OK, peer_addr);
  SequencedSocketData data1(connect1, reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  AddSSLSocketData();

  // Retry the second request on the second H2 connection.
  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req3(
      spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
  MockWrite writes2[] = {
      CreateMockWrite(req3, 0),
  };

  spdy::SpdySerializedFrame resp3(spdy_util2.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
  MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
                       MockRead(ASYNC, 0, 3)};

  MockConnect connect2(ASYNC, OK, peer_addr);
  SequencedSocketData data2(connect2, reads2, writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  AddSSLSocketData();

  // Preload mail.example.org into HostCache.
  int rv = session_deps_.host_resolver->LoadIntoCache(
      HostPortPair("mail.example.org", 443), NetworkAnonymizationKey(),
      std::nullopt);
  EXPECT_THAT(rv, IsOk());

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  rv = trans1.Start(&request1, callback.callback(),
                    NetLogWithSource::Make(NetLogSourceType::URL_REQUEST));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.org/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  RecordingNetLogObserver net_log_observer;
  rv = trans2.Start(&request2, callback.callback(),
                    NetLogWithSource::Make(NetLogSourceType::URL_REQUEST));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  auto entries = net_log_observer.GetEntries();
  ExpectLogContainsSomewhere(
      entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
      NetLogEventPhase::NONE);
}

// Test that HTTP 421 responses are properly returned to the caller if received
// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
// portions of the response.
TEST_P(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
  // Two hosts resolve to the same IP address.
  const std::string ip_addr = "1.2.3.4";
  IPAddress ip;
  ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
  IPEndPoint peer_addr = IPEndPoint(ip, 443);

  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
  session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Two requests on the first connection.
  spdy::SpdySerializedFrame req1(
      spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
  spdy_util_.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame req2(
      spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
  MockWrite writes1[] = {
      CreateMockWrite(req1, 0),
      CreateMockWrite(req2, 3),
      CreateMockWrite(rst, 6),
  };

  // The first one succeeds, the second gets error 421 Misdirected Request.
  spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
  quiche::HttpHeaderBlock response_headers;
  response_headers[spdy::kHttp2StatusHeader] = "421";
  spdy::SpdySerializedFrame resp2(
      spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
  MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
                       CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};

  MockConnect connect1(ASYNC, OK, peer_addr);
  SequencedSocketData data1(connect1, reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  AddSSLSocketData();

  // Retry the second request on a second connection. It returns 421 Misdirected
  // Retry again.
  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req3(
      spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
  MockWrite writes2[] = {
      CreateMockWrite(req3, 0),
  };

  spdy::SpdySerializedFrame resp3(
      spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
  spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
  MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
                       MockRead(ASYNC, 0, 3)};

  MockConnect connect2(ASYNC, OK, peer_addr);
  SequencedSocketData data2(connect2, reads2, writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  AddSSLSocketData();

  // Preload mail.example.org into HostCache.
  int rv = session_deps_.host_resolver->LoadIntoCache(
      HostPortPair("mail.example.org", 443), NetworkAnonymizationKey(),
      std::nullopt);
  EXPECT_THAT(rv, IsOk());

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.org/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback.callback(),
                    NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  // After a retry, the 421 Misdirected Request is reported back up to the
  // caller.
  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  EXPECT_TRUE(response->ssl_info.cert);
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

TEST_P(HttpNetworkTransactionTest,
       Response421WithStreamingBodyWithNonNullSource) {
  const std::string ip_addr = "1.2.3.4";
  IPAddress ip;
  ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
  IPEndPoint peer_addr = IPEndPoint(ip, 443);

  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  const std::string request_body = "hello";
  spdy::SpdySerializedFrame req1 =
      spdy_util_.ConstructChunkedSpdyPost(base::span<const std::string_view>());
  spdy::SpdySerializedFrame req1_body =
      spdy_util_.ConstructSpdyDataFrame(1, request_body, /*fin=*/true);
  spdy::SpdySerializedFrame rst =
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL);
  MockWrite writes1[] = {
      CreateMockWrite(req1, 0),
      CreateMockWrite(req1_body, 1),
      CreateMockWrite(rst, 4),
  };

  quiche::HttpHeaderBlock response_headers;
  response_headers[spdy::kHttp2StatusHeader] = "421";
  spdy::SpdySerializedFrame resp1 =
      spdy_util_.ConstructSpdyReply(1, std::move(response_headers));
  MockRead reads1[] = {CreateMockRead(resp1, 2), MockRead(ASYNC, 0, 3)};

  MockConnect connect1(ASYNC, OK, peer_addr);
  SequencedSocketData data1(connect1, reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  AddSSLSocketData();

  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req2 =
      spdy_util2.ConstructChunkedSpdyPost(base::span<const std::string_view>());
  spdy::SpdySerializedFrame req2_body =
      spdy_util2.ConstructSpdyDataFrame(1, request_body, /*fin=*/true);
  MockWrite writes2[] = {
      CreateMockWrite(req2, 0),
      CreateMockWrite(req2_body, 1),
  };

  quiche::HttpHeaderBlock resp2_headers;
  resp2_headers[spdy::kHttp2StatusHeader] = "200";
  spdy::SpdySerializedFrame resp2 =
      spdy_util2.ConstructSpdyReply(1, std::move(resp2_headers));
  spdy::SpdySerializedFrame resp2_body(
      spdy_util2.ConstructSpdyDataFrame(1, true));
  MockRead reads2[] = {CreateMockRead(resp2, 2), CreateMockRead(resp2_body, 3),
                       MockRead(ASYNC, 0, 4)};

  MockConnect connect2(ASYNC, OK, peer_addr);
  SequencedSocketData data2(connect2, reads2, writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  AddSSLSocketData();

  TestCompletionCallback callback;
  HttpRequestInfo request;
  ChunkedUploadDataStream upload_data_stream(0, /*has_null_source=*/false);
  upload_data_stream.AppendData(base::as_byte_span(request_body),
                                /*is_done=*/true);
  request.method = "POST";
  request.url = GURL("https://www.example.org");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request.upload_data_stream = &upload_data_stream;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  std::string response_data;
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  EXPECT_TRUE(response->ssl_info.cert);
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

TEST_P(HttpNetworkTransactionTest, Response421WithStreamingBodyWithNullSource) {
  const std::string ip_addr = "1.2.3.4";
  IPAddress ip;
  ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
  IPEndPoint peer_addr = IPEndPoint(ip, 443);

  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  const std::string request_body = "hello";
  spdy::SpdySerializedFrame req1 =
      spdy_util_.ConstructChunkedSpdyPost(base::span<const std::string_view>());
  spdy::SpdySerializedFrame req1_body =
      spdy_util_.ConstructSpdyDataFrame(1, request_body, /*fin=*/true);
  spdy::SpdySerializedFrame rst =
      spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL);
  MockWrite writes1[] = {
      CreateMockWrite(req1, 0),
      CreateMockWrite(req1_body, 1),
      CreateMockWrite(rst, 5),
  };

  quiche::HttpHeaderBlock response_headers;
  response_headers[spdy::kHttp2StatusHeader] = "421";
  spdy::SpdySerializedFrame resp1 =
      spdy_util_.ConstructSpdyReply(1, std::move(response_headers));
  spdy::SpdySerializedFrame resp1_body(
      spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead reads1[] = {CreateMockRead(resp1, 2), CreateMockRead(resp1_body, 3),
                       MockRead(ASYNC, 0, 4)};

  MockConnect connect1(ASYNC, OK, peer_addr);
  SequencedSocketData data1(connect1, reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  AddSSLSocketData();

  TestCompletionCallback callback;
  HttpRequestInfo request;
  ChunkedUploadDataStream upload_data_stream(0, /*has_null_source=*/true);
  upload_data_stream.AppendData(base::as_byte_span(request_body),
                                /*is_done=*/true);
  request.method = "POST";
  request.url = GURL("https://www.example.org");
  request.load_flags = 0;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request.upload_data_stream = &upload_data_stream;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  std::string response_data;
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  EXPECT_TRUE(response->ssl_info.cert);
  ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

TEST_P(HttpNetworkTransactionTest,
       UseIPConnectionPoolingWithHostCacheExpiration) {
  // Set up HostResolver to invalidate cached entries after 1 cached resolve.
  session_deps_.host_resolver =
      std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
  session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  AddSSLSocketData();

  spdy::SpdySerializedFrame host1_req(
      spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
  spdy_util_.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame host2_req(
      spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
  MockWrite spdy_writes[] = {
      CreateMockWrite(host1_req, 0),
      CreateMockWrite(host2_req, 3),
  };
  spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame host1_resp_body(
      spdy_util_.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame host2_resp_body(
      spdy_util_.ConstructSpdyDataFrame(3, true));
  MockRead spdy_reads[] = {
      CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
      CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
      MockRead(ASYNC, 0, 6),
  };

  IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
  MockConnect connect(ASYNC, OK, peer_addr);
  SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());

  int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans1.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  // Preload cache entries into HostCache.
  rv = session_deps_.host_resolver->LoadIntoCache(
      HostPortPair("mail.example.com", 443), NetworkAnonymizationKey(),
      std::nullopt);
  EXPECT_THAT(rv, IsOk());

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.com/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());

  rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans2.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
}

TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
  const std::string https_url = "https://www.example.org:8080/";
  const std::string http_url = "http://www.example.org:8080/";

  // SPDY GET for HTTPS URL
  spdy::SpdySerializedFrame req1(
      spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));

  MockWrite writes1[] = {
      CreateMockWrite(req1, 0),
  };

  spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
                       MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};

  SequencedSocketData data1(reads1, writes1);
  MockConnect connect_data1(ASYNC, OK);
  data1.set_connect_data(connect_data1);

  // HTTP GET for the HTTP URL
  MockWrite writes2[] = {
      MockWrite(ASYNC, 0,
                "GET / HTTP/1.1\r\n"
                "Host: www.example.org:8080\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead reads2[] = {
      MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead(ASYNC, 2, "hello"),
      MockRead(ASYNC, OK, 3),
  };

  SequencedSocketData data2(reads2, writes2);

  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Start the first transaction to set up the SpdySession
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL(https_url);
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(LOWEST, session.get());
  TestCompletionCallback callback1;
  EXPECT_EQ(ERR_IO_PENDING,
            trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
  base::RunLoop().RunUntilIdle();

  EXPECT_THAT(callback1.WaitForResult(), IsOk());
  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);

  // Now, start the HTTP request
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL(http_url);
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(MEDIUM, session.get());
  TestCompletionCallback callback2;
  EXPECT_EQ(ERR_IO_PENDING,
            trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
  base::RunLoop().RunUntilIdle();

  EXPECT_THAT(callback2.WaitForResult(), IsOk());
  EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
}

// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
// with the alternative server.  That connection should not be used.
TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
  url::SchemeHostPort server("https", "www.example.org", 443);
  HostPortPair alternative("www.example.org", 444);

  // Negotiate HTTP/1.1 with alternative.
  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // No data should be read from the alternative, because HTTP/1.1 is
  // negotiated.
  StaticSocketDataProvider data;
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  // This test documents that an alternate Job should not be used if HTTP/1.1 is
  // negotiated.  In order to test this, a failed connection to the server is
  // mocked.  This way the request relies on the alternate Job.
  StaticSocketDataProvider data_refused;
  data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
  session_deps_.socket_factory->AddSocketDataProvider(&data_refused);

  // Set up alternative service for server.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  AlternativeService alternative_service(NextProto::kProtoHTTP2, alternative);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      server, NetworkAnonymizationKey(), alternative_service, expiration);

  HttpRequestInfo request;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  request.method = "GET";
  request.url = GURL("https://www.example.org:443");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  TestCompletionCallback callback;

  // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
  // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
}

// A request to a server with an alternative service fires two Jobs: one to the
// server, and an alternate one to the alternative server.  If the former
// succeeds, the request should succeed,  even if the latter fails because
// HTTP/1.1 is negotiated which is insufficient for alternative service.
TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
  url::SchemeHostPort server("https", "www.example.org", 443);
  HostPortPair alternative("www.example.org", 444);

  // Negotiate HTTP/1.1 with alternative.
  SSLSocketDataProvider alternative_ssl(ASYNC, OK);
  alternative_ssl.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);

  // No data should be read from the alternative, because HTTP/1.1 is
  // negotiated.
  StaticSocketDataProvider data;
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  // Negotiate HTTP/1.1 with server.
  SSLSocketDataProvider origin_ssl(ASYNC, OK);
  origin_ssl.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);

  MockWrite http_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
      MockWrite("GET /second HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead http_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html\r\n"),
      MockRead("Content-Length: 6\r\n\r\n"),
      MockRead("foobar"),
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html\r\n"),
      MockRead("Content-Length: 7\r\n\r\n"),
      MockRead("another"),
  };
  StaticSocketDataProvider http_data(http_reads, http_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  // Set up alternative service for server.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  AlternativeService alternative_service(NextProto::kProtoHTTP2, alternative);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      server, NetworkAnonymizationKey(), alternative_service, expiration);

  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org:443");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  TestCompletionCallback callback1;

  int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
  rv = callback1.GetResult(rv);
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response1 = trans1.GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());

  std::string response_data1;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
  EXPECT_EQ("foobar", response_data1);

  // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
  // for alternative service.
  EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
      alternative_service, NetworkAnonymizationKey()));

  // Since |alternative_service| is broken, a second transaction to server
  // should not start an alternate Job.  It should pool to existing connection
  // to server.
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.example.org:443/second");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  TestCompletionCallback callback2;

  rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
  rv = callback2.GetResult(rv);
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
  ASSERT_TRUE(response2);
  ASSERT_TRUE(response2->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());

  std::string response_data2;
  ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
  EXPECT_EQ("another", response_data2);
}

// Alternative service requires HTTP/2 (or SPDY), but there is already a
// HTTP/1.1 socket open to the alternative server.  That socket should not be
// used.
TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
  url::SchemeHostPort server("https", "origin.example.org", 443);
  HostPortPair alternative("alternative.example.org", 443);
  std::string origin_url = "https://origin.example.org:443";
  std::string alternative_url = "https://alternative.example.org:443";

  // Negotiate HTTP/1.1 with alternative.example.org.
  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.next_proto = NextProto::kProtoHTTP11;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // HTTP/1.1 data for |request1| and |request2|.
  MockWrite http_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: alternative.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: alternative.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead http_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html; charset=iso-8859-1\r\n"
               "Content-Length: 40\r\n\r\n"
               "first HTTP/1.1 response from alternative"),
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html; charset=iso-8859-1\r\n"
               "Content-Length: 41\r\n\r\n"
               "second HTTP/1.1 response from alternative"),
  };
  StaticSocketDataProvider http_data(http_reads, http_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  // This test documents that an alternate Job should not pool to an already
  // existing HTTP/1.1 connection.  In order to test this, a failed connection
  // to the server is mocked.  This way |request2| relies on the alternate Job.
  StaticSocketDataProvider data_refused;
  data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
  session_deps_.socket_factory->AddSocketDataProvider(&data_refused);

  // Set up alternative service for server.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  AlternativeService alternative_service(NextProto::kProtoHTTP2, alternative);
  base::Time expiration = base::Time::Now() + base::Days(1);
  http_server_properties->SetHttp2AlternativeService(
      server, NetworkAnonymizationKey(), alternative_service, expiration);

  // First transaction to alternative to open an HTTP/1.1 socket.
  HttpRequestInfo request1;
  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
  request1.method = "GET";
  request1.url = GURL(alternative_url);
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  TestCompletionCallback callback1;

  int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(callback1.GetResult(rv), IsOk());
  const HttpResponseInfo* response1 = trans1.GetResponseInfo();
  ASSERT_TRUE(response1);
  ASSERT_TRUE(response1->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
  EXPECT_TRUE(response1->was_alpn_negotiated);
  EXPECT_FALSE(response1->was_fetched_via_spdy);
  std::string response_data1;
  ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
  EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);

  // Request for origin.example.org, which has an alternative service.  This
  // will start two Jobs: the alternative looks for connections to pool to,
  // finds one which is HTTP/1.1, and should ignore it, and should not try to
  // open other connections to alternative server.  The Job to server fails, so
  // this request fails.
  HttpRequestInfo request2;
  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  request2.method = "GET";
  request2.url = GURL(origin_url);
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  TestCompletionCallback callback2;

  rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
  EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));

  // Another transaction to alternative.  This is to test that the HTTP/1.1
  // socket is still open and in the pool.
  HttpRequestInfo request3;
  HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
  request3.method = "GET";
  request3.url = GURL(alternative_url);
  request3.load_flags = 0;
  request3.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  TestCompletionCallback callback3;

  rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
  EXPECT_THAT(callback3.GetResult(rv), IsOk());
  const HttpResponseInfo* response3 = trans3.GetResponseInfo();
  ASSERT_TRUE(response3);
  ASSERT_TRUE(response3->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
  EXPECT_TRUE(response3->was_alpn_negotiated);
  EXPECT_FALSE(response3->was_fetched_via_spdy);
  std::string response_data3;
  ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
  EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
}

TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
  const std::string https_url = "https://www.example.org:8080/";
  const std::string http_url = "http://www.example.org:8080/";

  // Separate SPDY util instance for naked and wrapped requests.
  SpdyTestUtil spdy_util_wrapped(/*use_priority_header=*/true);

  // SPDY GET for HTTPS URL (through CONNECT tunnel)
  const HostPortPair host_port_pair("www.example.org", 8080);
  spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
      base::span<const std::string_view>(), 1,
      HttpProxyConnectJob::kH2QuicTunnelPriority, host_port_pair));
  spdy::SpdySerializedFrame req1(
      spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
  spdy::SpdySerializedFrame wrapped_req1(
      spdy_util_.ConstructWrappedSpdyFrame(req1, 1));

  // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
  quiche::HttpHeaderBlock req2_block;
  req2_block[spdy::kHttp2MethodHeader] = "GET";
  req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
  req2_block[spdy::kHttp2SchemeHeader] = "http";
  req2_block[spdy::kHttp2PathHeader] = "/";
  spdy::SpdySerializedFrame req2(
      spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));

  MockWrite writes1[] = {
      CreateMockWrite(connect, 0),
      CreateMockWrite(wrapped_req1, 2),
      CreateMockWrite(req2, 6),
  };

  spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame resp1(spdy_util_wrapped.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body1(
      spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
  spdy::SpdySerializedFrame wrapped_resp1(
      spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
  spdy::SpdySerializedFrame wrapped_body1(
      spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
  spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 3));
  spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
  MockRead reads1[] = {
      CreateMockRead(conn_resp, 1),
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      CreateMockRead(wrapped_resp1, 4),
      CreateMockRead(wrapped_body1, 5),
      MockRead(ASYNC, ERR_IO_PENDING, 7),
      CreateMockRead(resp2, 8),
      CreateMockRead(body2, 9),
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
  };

  SequencedSocketData data1(reads1, writes1);
  MockConnect connect_data1(ASYNC, OK);
  data1.set_connect_data(connect_data1);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
  ssl1.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);  // to the server
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Start the first transaction to set up the SpdySession
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL(https_url);
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(LOWEST, session.get());
  TestCompletionCallback callback1;
  int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());

  // This pause is a hack to avoid running into https://crbug.com/497228.
  data1.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  data1.Resume();
  EXPECT_THAT(callback1.GetResult(rv), IsOk());
  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);

  LoadTimingInfo load_timing_info1;
  EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
  TestLoadTimingNotReusedWithPac(load_timing_info1,
                                 CONNECT_TIMING_HAS_SSL_TIMES);

  // Now, start the HTTP request.
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL(http_url);
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(MEDIUM, session.get());
  TestCompletionCallback callback2;
  rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());

  // This pause is a hack to avoid running into https://crbug.com/497228.
  data1.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  data1.Resume();
  EXPECT_THAT(callback2.GetResult(rv), IsOk());

  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);

  LoadTimingInfo load_timing_info2;
  EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
  // The established SPDY sessions is considered reused by the HTTP request.
  TestLoadTimingReusedWithPac(load_timing_info2);
  // HTTP requests over a SPDY session should have a different connection
  // socket_log_id than requests over a tunnel.
  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
}

// Test that in the case where we have a SPDY session to a SPDY proxy
// that we do not pool other origins that resolve to the same IP when
// the certificate does not match the new origin.
// http://crbug.com/134690
TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
  const std::string url1 = "http://www.example.org/";
  const std::string url2 = "https://news.example.org/";
  const std::string ip_addr = "1.2.3.4";

  // Second SpdyTestUtil instance for the second socket.
  SpdyTestUtil spdy_util_secure(/*use_priority_header=*/true);

  // SPDY GET for HTTP URL (through SPDY proxy)
  quiche::HttpHeaderBlock headers(
      spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
  spdy::SpdySerializedFrame req1(
      spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));

  MockWrite writes1[] = {
      CreateMockWrite(req1, 0),
  };

  spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead reads1[] = {
      MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
      CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4),  // EOF
  };

  SequencedSocketData data1(reads1, writes1);
  IPAddress ip;
  ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
  IPEndPoint peer_addr = IPEndPoint(ip, 443);
  MockConnect connect_data1(ASYNC, OK, peer_addr);
  data1.set_connect_data(connect_data1);

  // SPDY GET for HTTPS URL (direct)
  spdy::SpdySerializedFrame req2(
      spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));

  MockWrite writes2[] = {
      CreateMockWrite(req2, 0),
  };

  spdy::SpdySerializedFrame resp2(spdy_util_secure.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body2(
      spdy_util_secure.ConstructSpdyDataFrame(1, true));
  MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
                       MockRead(ASYNC, OK, 3)};

  SequencedSocketData data2(reads2, writes2);
  MockConnect connect_data2(ASYNC, OK);
  data2.set_connect_data(connect_data2);

  // Set up a proxy config that sends HTTP requests to a proxy, and
  // all others direct.
  ProxyConfig proxy_config;
  proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          ProxyConfigWithAnnotation(proxy_config,
                                    TRAFFIC_ANNOTATION_FOR_TESTS));

  SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
  ssl1.next_proto = NextProto::kProtoHTTP2;
  // Load a valid cert.  Note, that this does not need to
  // be valid for proxy because the MockSSLClientSocket does
  // not actually verify it.  But SpdySession will use this
  // to see if it is valid for the new origin
  ssl1.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
  ASSERT_TRUE(ssl1.ssl_info.cert);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  SSLSocketDataProvider ssl2(ASYNC, OK);  // to the server
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
  session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Start the first transaction to set up the SpdySession
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL(url1);
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(LOWEST, session.get());
  TestCompletionCallback callback1;
  ASSERT_EQ(ERR_IO_PENDING,
            trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
  // This pause is a hack to avoid running into https://crbug.com/497228.
  data1.RunUntilPaused();
  base::RunLoop().RunUntilIdle();
  data1.Resume();

  EXPECT_THAT(callback1.WaitForResult(), IsOk());
  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);

  // Now, start the HTTP request
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL(url2);
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(MEDIUM, session.get());
  TestCompletionCallback callback2;
  EXPECT_EQ(ERR_IO_PENDING,
            trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
  base::RunLoop().RunUntilIdle();

  ASSERT_TRUE(callback2.have_result());
  EXPECT_THAT(callback2.WaitForResult(), IsOk());
  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
}

// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
// error) in SPDY session, removes the socket from pool and closes the SPDY
// session. Verify that new url's from the same HttpNetworkSession (and a new
// SpdySession) do work. http://crbug.com/224701
TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
  const std::string https_url = "https://www.example.org/";

  MockRead reads1[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)};

  SequencedSocketData data1(reads1, base::span<MockWrite>());

  spdy::SpdySerializedFrame req2(
      spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
  MockWrite writes2[] = {
      CreateMockWrite(req2, 0),
  };

  spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead reads2[] = {
      CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
      MockRead(ASYNC, OK, 3)  // EOF
  };

  SequencedSocketData data2(reads2, writes2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  ssl1.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  std::unique_ptr<HttpNetworkSession> session(
      SpdySessionDependencies::SpdyCreateSession(&session_deps_));

  // Start the first transaction to set up the SpdySession and verify that
  // connection was closed.
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL(https_url);
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans1(MEDIUM, session.get());
  TestCompletionCallback callback1;
  EXPECT_EQ(ERR_IO_PENDING,
            trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
  EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));

  // Now, start the second request and make sure it succeeds.
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL(https_url);
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  HttpNetworkTransaction trans2(MEDIUM, session.get());
  TestCompletionCallback callback2;
  EXPECT_EQ(ERR_IO_PENDING,
            trans2.Start(&request2, callback2.callback(), NetLogWithSource()));

  ASSERT_THAT(callback2.WaitForResult(), IsOk());
  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
}

TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
  ClientSocketPoolManager::set_max_sockets_per_group_for_test(
      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
  ClientSocketPoolManager::set_socket_soft_cap_per_pool_for_test(
      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);

  // Use two different hosts with different IPs so they don't get pooled.
  session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
  session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    session->http_stream_pool()->set_max_stream_sockets_per_group_for_testing(
        1u);
    session->http_stream_pool()->set_max_stream_sockets_per_pool_for_testing(
        1u);
  }

  SSLSocketDataProvider ssl1(ASYNC, OK);
  ssl1.next_proto = NextProto::kProtoHTTP2;
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.next_proto = NextProto::kProtoHTTP2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  spdy::SpdySerializedFrame host1_req(
      spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
  MockWrite spdy1_writes[] = {
      CreateMockWrite(host1_req, 0),
  };
  spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame host1_resp_body(
      spdy_util_.ConstructSpdyDataFrame(1, true));
  MockRead spdy1_reads[] = {
      CreateMockRead(host1_resp, 1),
      CreateMockRead(host1_resp_body, 2),
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
  };

  // Use a separate test instance for the separate SpdySession that will be
  // created.
  SpdyTestUtil spdy_util_2(/*use_priority_header=*/true);
  SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);

  spdy::SpdySerializedFrame host2_req(
      spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
  MockWrite spdy2_writes[] = {
      CreateMockWrite(host2_req, 0),
  };
  spdy::SpdySerializedFrame host2_resp(spdy_util_2.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame host2_resp_body(
      spdy_util_2.ConstructSpdyDataFrame(1, true));
  MockRead spdy2_reads[] = {
      CreateMockRead(host2_resp, 1),
      CreateMockRead(host2_resp_body, 2),
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
  };

  SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);

  MockWrite http_write[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.a.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead http_read[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 6\r\n\r\n"),
      MockRead("hello!"),
  };
  StaticSocketDataProvider http_data(http_read, http_write);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  HostPortPair host_port_pair_a("www.a.com", 443);
  SpdySessionKey spdy_session_key_a(
      host_port_pair_a, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
      SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
      SecureDnsPolicy::kAllow,
      /*disable_cert_verification_network_fetches=*/false);
  EXPECT_FALSE(
      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.a.com/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
  trans.reset();
  EXPECT_TRUE(HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));

  HostPortPair host_port_pair_b("www.b.com", 443);
  SpdySessionKey spdy_session_key_b(
      host_port_pair_b, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
      SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
      SecureDnsPolicy::kAllow,
      /*disable_cert_verification_network_fetches=*/false);
  EXPECT_FALSE(
      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.b.com/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
  EXPECT_FALSE(
      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
  EXPECT_TRUE(HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));

  HostPortPair host_port_pair_a1("www.a.com", 80);
  SpdySessionKey spdy_session_key_a1(
      host_port_pair_a1, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
      SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
      SecureDnsPolicy::kAllow,
      /*disable_cert_verification_network_fetches=*/false);
  EXPECT_FALSE(
      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
  HttpRequestInfo request3;
  request3.method = "GET";
  request3.url = GURL("http://www.a.com/");
  request3.load_flags = 0;
  request3.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
  EXPECT_FALSE(response->was_fetched_via_spdy);
  EXPECT_FALSE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);
  EXPECT_FALSE(
      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
  EXPECT_FALSE(
      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
}

TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
  StaticSocketDataProvider data;
  data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));

  ConnectionAttempts attempts = trans.GetConnectionAttempts();
  ASSERT_EQ(1u, attempts.size());
  EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));

  IPEndPoint endpoint;
  EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
  EXPECT_TRUE(endpoint.address().empty());
}

TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
  StaticSocketDataProvider data;
  data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));

  ConnectionAttempts attempts = trans.GetConnectionAttempts();
  ASSERT_EQ(1u, attempts.size());
  EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));

  IPEndPoint endpoint;
  EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
  EXPECT_TRUE(endpoint.address().empty());
}

TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };
  MockRead data_reads[] = {
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite(ASYNC, ERR_CONNECTION_RESET),
  };
  MockRead data_reads[] = {
      MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead data_reads[] = {
      MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead data_reads[] = {
      MockRead(ASYNC, ERR_CONNECTION_RESET),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

// Tests that when a used socket is returned to the SSL socket pool, it's closed
// if the transport socket pool is stalled on the global socket limit.
TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
  ClientSocketPoolManager::set_max_sockets_per_group_for_test(
      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
  ClientSocketPoolManager::set_socket_soft_cap_per_pool_for_test(
      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);

  // Set up SSL request.

  HttpRequestInfo ssl_request;
  ssl_request.method = "GET";
  ssl_request.url = GURL("https://www.example.org/");
  ssl_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite ssl_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead ssl_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 11\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // Set up HTTP request.

  HttpRequestInfo http_request;
  http_request.method = "GET";
  http_request.url = GURL("http://www.example.org/");
  http_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite http_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead http_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 7\r\n\r\n"),
      MockRead("falafel"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider http_data(http_reads, http_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    session->http_stream_pool()->set_max_stream_sockets_per_group_for_testing(
        1u);
    session->http_stream_pool()->set_max_stream_sockets_per_pool_for_testing(
        1u);
  }

  // Start the SSL request.
  TestCompletionCallback ssl_callback;
  HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
  ASSERT_EQ(ERR_IO_PENDING,
            ssl_trans.Start(&ssl_request, ssl_callback.callback(),
                            NetLogWithSource()));

  // Start the HTTP request.  Pool should stall.
  TestCompletionCallback http_callback;
  HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
  ASSERT_EQ(ERR_IO_PENDING,
            http_trans.Start(&http_request, http_callback.callback(),
                             NetLogWithSource()));
  EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));

  // Wait for response from SSL request.
  ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
  std::string response_data;
  ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  // The SSL socket should automatically be closed, so the HTTP request can
  // start.
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
  ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));

  // The HTTP request can now complete.
  ASSERT_THAT(http_callback.WaitForResult(), IsOk());
  ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
  EXPECT_EQ("falafel", response_data);

  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

// Tests that when a SSL connection is established but there's no corresponding
// request that needs it, the new socket is closed if the transport socket pool
// is stalled on the global socket limit.
TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
  ClientSocketPoolManager::set_max_sockets_per_group_for_test(
      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
  ClientSocketPoolManager::set_socket_soft_cap_per_pool_for_test(
      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);

  // Set up an ssl request.

  HttpRequestInfo ssl_request;
  ssl_request.method = "GET";
  ssl_request.url = GURL("https://www.foopy.com/");
  ssl_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // No data will be sent on the SSL socket.
  StaticSocketDataProvider ssl_data;
  MockConnectCompleter ssl_connect_completer;
  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    // When the HappyEyeballsV3 flag is enabled, the idle socket created by the
    // following preconnect would be reused immedialy after the transaction is
    // started when we don't delay Connect(). Use MockConnectCompleter to block
    // Connect().
    ssl_data.set_connect_data(MockConnect(&ssl_connect_completer));
  }
  session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // Set up HTTP request.

  HttpRequestInfo http_request;
  http_request.method = "GET";
  http_request.url = GURL("http://www.example.org/");
  http_request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite http_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead http_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 7\r\n\r\n"),
      MockRead("falafel"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider http_data(http_reads, http_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&http_data);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    session->http_stream_pool()->set_max_stream_sockets_per_group_for_testing(
        1u);
    session->http_stream_pool()->set_max_stream_sockets_per_pool_for_testing(
        1u);
  }

  // Preconnect an SSL socket.  A preconnect is needed because connect jobs are
  // cancelled when a normal transaction is cancelled.
  HttpStreamFactory* http_stream_factory = session->http_stream_factory();
  http_stream_factory->PreconnectStreams(1, ssl_request, base::OnceClosure());
  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));

  // Start the HTTP request.  Pool should stall.
  TestCompletionCallback http_callback;
  HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
  ASSERT_EQ(ERR_IO_PENDING,
            http_trans.Start(&http_request, http_callback.callback(),
                             NetLogWithSource()));
  EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));

  if (base::FeatureList::IsEnabled(features::kHappyEyeballsV3)) {
    ssl_connect_completer.Complete(OK);
  }

  // The SSL connection will automatically be closed once the connection is
  // established, to let the HTTP request start.
  ASSERT_THAT(http_callback.WaitForResult(), IsOk());
  std::string response_data;
  ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
  EXPECT_EQ("falafel", response_data);

  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
}

TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

// This test makes sure the retry logic doesn't trigger when reading an error
// response from a server that rejected a POST with a CONNECTION_RESET.
TEST_P(HttpNetworkTransactionTest,
       PostReadsErrorResponseAfterResetOnReusedSocket) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n\r\n"),
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 Peachy\r\n"
               "Content-Length: 14\r\n\r\n"),
      MockRead("first response"),
      MockRead("HTTP/1.1 400 Not OK\r\n"
               "Content-Length: 15\r\n\r\n"),
      MockRead("second response"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("http://www.foo.com/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
  ASSERT_TRUE(response1);

  EXPECT_TRUE(response1->headers);
  EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());

  std::string response_data1;
  rv = ReadTransaction(trans1.get(), &response_data1);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("first response", response_data1);
  // Delete the transaction to release the socket back into the socket pool.
  trans1.reset();

  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request2;
  request2.method = "POST";
  request2.url = GURL("http://www.foo.com/");
  request2.upload_data_stream = &upload_data_stream;
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
  rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
  ASSERT_TRUE(response2);

  EXPECT_TRUE(response2->headers);
  EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());

  std::string response_data2;
  rv = ReadTransaction(&trans2, &response_data2);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("second response", response_data2);
}

TEST_P(HttpNetworkTransactionTest,
       PostReadsErrorResponseAfterResetPartialBodySent) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"
                "fo"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

// This tests the more common case than the previous test, where headers and
// body are not merged into a single request.
TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
  ChunkedUploadDataStream upload_data_stream(0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Transfer-Encoding: chunked\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  // Make sure the headers are sent before adding a chunk.  This ensures that
  // they can't be merged with the body in a single send.  Not currently
  // necessary since a chunked body is never merged with headers, but this makes
  // the test more future proof.
  base::RunLoop().RunUntilIdle();

  upload_data_stream.AppendData(base::byte_span_from_cstring("last chunk"),
                                true);

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
      MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(&trans, &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("hello world", response_data);
}

TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

TEST_P(HttpNetworkTransactionTest,
       PostIgnoresNonErrorResponseAfterResetAnd100) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
      MockRead("HTTP/1.0 302 Redirect\r\n"),
      MockRead("Location: http://somewhere-else.com/\r\n"),
      MockRead("Content-Length: 0\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP 0.9 rocks!"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
}

#if BUILDFLAG(ENABLE_WEBSOCKETS)

namespace {

void AddWebSocketHeaders(HttpRequestHeaders* headers) {
  headers->SetHeader("Connection", "Upgrade");
  headers->SetHeader("Upgrade", "websocket");
  headers->SetHeader("Origin", "http://www.example.org");
  headers->SetHeader("Sec-WebSocket-Version", "13");
}

}  // namespace

TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
  for (bool secure : {true, false}) {
    MockWrite data_writes[] = {
        MockWrite("GET / HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: Upgrade\r\n"
                  "Upgrade: websocket\r\n"
                  "Origin: http://www.example.org\r\n"
                  "Sec-WebSocket-Version: 13\r\n"
                  "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
                  "Sec-WebSocket-Extensions: permessage-deflate; "
                  "client_max_window_bits\r\n\r\n")};

    MockRead data_reads[] = {
        MockRead("HTTP/1.1 101 Switching Protocols\r\n"
                 "Upgrade: websocket\r\n"
                 "Connection: Upgrade\r\n"
                 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};

    StaticSocketDataProvider data(data_reads, data_writes);
    session_deps_.socket_factory->AddSocketDataProvider(&data);
    SSLSocketDataProvider ssl(ASYNC, OK);
    if (secure) {
      session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
    }

    HttpRequestInfo request;
    request.method = "GET";
    request.url =
        GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
    AddWebSocketHeaders(&request.extra_headers);
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    TestWebSocketHandshakeStreamCreateHelper
        websocket_handshake_stream_create_helper;

    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
    HttpNetworkTransaction trans(LOW, session.get());
    trans.SetWebSocketHandshakeStreamCreateHelper(
        &websocket_handshake_stream_create_helper);

    TestCompletionCallback callback;
    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    const HttpStreamRequest* stream_request = trans.stream_request_.get();
    ASSERT_TRUE(stream_request);
    EXPECT_EQ(&websocket_handshake_stream_create_helper,
              stream_request->websocket_handshake_stream_create_helper());

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    EXPECT_TRUE(data.AllReadDataConsumed());
    EXPECT_TRUE(data.AllWriteDataConsumed());
  }
}

// Verify that proxy headers are not sent to the destination server when
// establishing a tunnel for a secure WebSocket connection.
TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("wss://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  AddWebSocketHeaders(&request.extra_headers);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since a proxy is configured, try to establish a tunnel.
  MockWrite data_writes[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      // After calling trans->RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: Upgrade\r\n"
                "Upgrade: websocket\r\n"
                "Origin: http://www.example.org\r\n"
                "Sec-WebSocket-Version: 13\r\n"
                "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
                "Sec-WebSocket-Extensions: permessage-deflate; "
                "client_max_window_bits\r\n\r\n")};

  // The proxy responds to the connect with a 407, using a persistent
  // connection.
  MockRead data_reads[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
               "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
               "Content-Length: 0\r\n"
               "Proxy-Connection: keep-alive\r\n"
               "User-Agent: test-ua\r\n\r\n"),

      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 101 Switching Protocols\r\n"
               "Upgrade: websocket\r\n"
               "Connection: Upgrade\r\n"
               "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  trans->SetWebSocketHandshakeStreamCreateHelper(
      &websocket_stream_create_helper);

  {
    TestCompletionCallback callback;

    int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());
  }

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(407, response->headers->response_code());

  {
    TestCompletionCallback callback;

    int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
                                    callback.callback());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());
  }

  response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);

  EXPECT_EQ(101, response->headers->response_code());

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Verify that proxy headers are not sent to the destination server when
// establishing a tunnel for an insecure WebSocket connection.
// This requires the authentication info to be injected into the auth cache
// due to crbug.com/395064
// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("ws://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  AddWebSocketHeaders(&request.extra_headers);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes[] = {
      // Try to establish a tunnel for the WebSocket connection, with
      // credentials. Because WebSockets have a separate set of socket pools,
      // they cannot and will not use the same TCP/IP connection as the
      // preflight HTTP request.
      MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
                "Host: www.example.org:80\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: Upgrade\r\n"
                "Upgrade: websocket\r\n"
                "Origin: http://www.example.org\r\n"
                "Sec-WebSocket-Version: 13\r\n"
                "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
                "Sec-WebSocket-Extensions: permessage-deflate; "
                "client_max_window_bits\r\n\r\n")};

  MockRead data_reads[] = {
      // HTTP CONNECT with credentials.
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      // WebSocket connection established inside tunnel.
      MockRead("HTTP/1.1 101 Switching Protocols\r\n"
               "Upgrade: websocket\r\n"
               "Connection: Upgrade\r\n"
               "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  session->http_auth_cache()->Add(
      url::SchemeHostPort(GURL("http://myproxy:70/")), HttpAuth::AUTH_PROXY,
      "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
      "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");

  TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  trans->SetWebSocketHandshakeStreamCreateHelper(
      &websocket_stream_create_helper);

  TestCompletionCallback callback;

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);

  EXPECT_EQ(101, response->headers->response_code());

  trans.reset();
  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// WebSockets over QUIC is not supported, including over QUIC proxies.
TEST_P(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
  for (bool secure : {true, false}) {
    SCOPED_TRACE(secure);
    session_deps_.proxy_resolution_service =
        ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
            {ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_QUIC,
                                               "myproxy.org", 443)},
            TRAFFIC_ANNOTATION_FOR_TESTS);
    session_deps_.enable_quic = true;

    HttpRequestInfo request;
    request.url =
        GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
    AddWebSocketHeaders(&request.extra_headers);
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    TestWebSocketHandshakeStreamCreateHelper
        websocket_handshake_stream_create_helper;

    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
    HttpNetworkTransaction trans(LOW, session.get());
    trans.SetWebSocketHandshakeStreamCreateHelper(
        &websocket_handshake_stream_create_helper);

    TestCompletionCallback callback;
    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
  }
}

#endif  // BUILDFLAG(ENABLE_WEBSOCKETS)

TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite("foo"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  EXPECT_EQ(ERR_IO_PENDING,
            trans.Start(&request, callback.callback(), NetLogWithSource()));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  std::string response_data;
  EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());

  EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
  EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
}

TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
  std::vector<std::unique_ptr<UploadElementReader>> element_readers;
  element_readers.push_back(std::make_unique<UploadBytesElementReader>(
      base::byte_span_from_cstring("foo")));
  ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 3\r\n\r\n"),
      MockWrite("foo"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  EXPECT_EQ(ERR_IO_PENDING,
            trans.Start(&request, callback.callback(), NetLogWithSource()));
  EXPECT_THAT(callback.WaitForResult(), IsOk());

  std::string response_data;
  EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());

  EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
  EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
}

TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
  ChunkedUploadDataStream upload_data_stream(0);

  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("http://www.foo.com/");
  request.upload_data_stream = &upload_data_stream;
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Transfer-Encoding: chunked\r\n\r\n"),
      MockWrite("1\r\nf\r\n"),
      MockWrite("2\r\noo\r\n"),
      MockWrite("0\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  EXPECT_EQ(ERR_IO_PENDING,
            trans.Start(&request, callback.callback(), NetLogWithSource()));

  base::RunLoop().RunUntilIdle();
  upload_data_stream.AppendData(base::byte_span_from_cstring("f"), false);

  base::RunLoop().RunUntilIdle();
  upload_data_stream.AppendData(base::byte_span_from_cstring("oo"), true);

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  std::string response_data;
  EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());

  EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
  EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
}

void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
                                  const std::string& accept_encoding,
                                  const std::string& content_encoding,
                                  const std::string& location,
                                  bool should_match) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.foo.com/");
  request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
                                  accept_encoding);
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  // Send headers successfully, but get an error while sending the body.
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.foo.com\r\n"
                "Connection: keep-alive\r\n"
                "Accept-Encoding: "),
      MockWrite(accept_encoding),
      MockWrite("\r\n\r\n"),
  };

  std::string response_code = "200 OK";
  std::string extra;
  if (!location.empty()) {
    response_code = "301 Redirect\r\nLocation: ";
    response_code.append(location);
  }

  MockRead data_reads[] = {
      MockRead("HTTP/1.0 "),
      MockRead(response_code),
      MockRead("\r\nContent-Encoding: "),
      MockRead(content_encoding),
      MockRead("\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };
  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps->socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  if (should_match) {
    EXPECT_THAT(rv, IsOk());
  } else {
    EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
  }
}

TEST_P(HttpNetworkTransactionTest, MatchContentEncoding1) {
  CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
}

TEST_P(HttpNetworkTransactionTest, MatchContentEncoding2) {
  CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
                               true);
}

TEST_P(HttpNetworkTransactionTest, MatchContentEncoding3) {
  CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
                               "", false);
}

TEST_P(HttpNetworkTransactionTest, MatchContentEncoding4) {
  CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
                               "www.foo.com/other", true);
}

TEST_P(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
  ProxyConfig proxy_config;
  proxy_config.set_pac_url(GURL("http://fooproxyurl"));
  proxy_config.set_pac_mandatory(true);
  MockAsyncProxyResolver resolver;
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::make_unique<FailingProxyResolverFactory>(),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;

  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  EXPECT_THAT(callback.WaitForResult(),
              IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
}

TEST_P(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
  ProxyConfig proxy_config;
  proxy_config.set_pac_url(GURL("http://fooproxyurl"));
  proxy_config.set_pac_mandatory(true);
  auto proxy_resolver_factory =
      std::make_unique<MockAsyncProxyResolverFactory>(false);
  auto* proxy_resolver_factory_ptr = proxy_resolver_factory.get();
  MockAsyncProxyResolver resolver;
  session_deps_.proxy_resolution_service =
      std::make_unique<ConfiguredProxyResolutionService>(
          std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
              proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
          std::move(proxy_resolver_factory),
          /*host_resolver_for_override_rules=*/nullptr, nullptr,
          /*quick_check_enabled=*/true);
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  proxy_resolver_factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(
      ERR_FAILED, &resolver);
  EXPECT_THAT(callback.WaitForResult(),
              IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
}

TEST_P(HttpNetworkTransactionTest, NoSupportedProxies) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
          {ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_QUIC,
                                             "myproxy.org", 443)},
          TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.enable_quic = false;
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  TestCompletionCallback callback;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
}

//-----------------------------------------------------------------------------
// Reporting tests

#if BUILDFLAG(ENABLE_REPORTING)
class HttpNetworkTransactionReportingTest
    : public HttpNetworkTransactionTestBase,
      public ::testing::WithParamInterface<bool> {
 protected:
  HttpNetworkTransactionReportingTest() {
    std::vector<base::test::FeatureRef> required_features = {
        features::kPartitionConnectionsByNetworkIsolationKey};
    feature_list_.InitWithFeatures(required_features, {});
  }

  void SetUp() override {
    HttpNetworkTransactionTestBase::SetUp();
    auto test_reporting_context = std::make_unique<TestReportingContext>(
        &clock_, &tick_clock_, ReportingPolicy());
    test_reporting_context_ = test_reporting_context.get();
    session_deps_.reporting_service =
        ReportingService::CreateForTesting(std::move(test_reporting_context));
  }

  TestReportingContext* reporting_context() const {
    return test_reporting_context_;
  }

  void TearDown() override {
    clear_reporting_service();
    HttpNetworkTransactionTestBase::TearDown();
  }
  void clear_reporting_service() {
    test_reporting_context_ = nullptr;
    session_deps_.reporting_service.reset();
  }

  // Makes an HTTPS request that should install a valid Reporting policy
  // using Report-To header.
  void RequestPolicy(CertStatus cert_status = 0) {
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL(url_);
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
    request.network_isolation_key = kNetworkIsolationKey;
    request.network_anonymization_key = kNetworkAnonymizationKey;
    MockWrite data_writes[] = {
        MockWrite("GET / HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    MockRead reporting_header;
    reporting_header = MockRead(
        "Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
        "\"endpoints\": [{\"url\": "
        "\"https://www.example.org/upload/\"}]}\r\n");
    MockRead data_reads[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        std::move(reporting_header),
        MockRead("\r\n"),
        MockRead("hello world"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider reads(data_reads, data_writes);
    session_deps_.socket_factory->AddSocketDataProvider(&reads);

    SSLSocketDataProvider ssl(ASYNC, OK);
    if (request.url.SchemeIsCryptographic()) {
      ssl.ssl_info.cert =
          ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
      ASSERT_TRUE(ssl.ssl_info.cert);
      ssl.ssl_info.cert_status = cert_status;
      session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
    }

    TestCompletionCallback callback;
    auto session = CreateSession(&session_deps_);
    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(callback.GetResult(rv), IsOk());
  }

 protected:
  bool UseDocumentReporting() const { return GetParam(); }
  std::string url_ = "https://www.example.org/";

 private:
  base::test::ScopedFeatureList feature_list_;
  raw_ptr<TestReportingContext> test_reporting_context_ = nullptr;
};

TEST_P(HttpNetworkTransactionReportingTest,
       DontProcessReportToHeaderNoService) {
  clear_reporting_service();
  RequestPolicy();
  // No crash.
}

TEST_P(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
  url_ = "http://www.example.org/";
  RequestPolicy();
  EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
}

TEST_P(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
  RequestPolicy();
  ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
  const ReportingEndpoint endpoint =
      reporting_context()->cache()->GetEndpointForTesting(
          ReportingEndpointGroupKey(
              kNetworkAnonymizationKey,
              url::Origin::Create(GURL("https://www.example.org/")), "nel",
              ReportingTargetType::kDeveloper),
          GURL("https://www.example.org/upload/"));
  EXPECT_TRUE(endpoint);
}

TEST_P(HttpNetworkTransactionReportingTest,
       DontProcessReportToHeaderInvalidHttps) {
  CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
  RequestPolicy(cert_status);
  EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
}

INSTANTIATE_TEST_SUITE_P(All,
                         HttpNetworkTransactionReportingTest,
                         ::testing::Bool());

#endif  // BUILDFLAG(ENABLE_REPORTING)

//-----------------------------------------------------------------------------
// Network Error Logging tests

#if BUILDFLAG(ENABLE_REPORTING)
namespace {

const char kUserAgent[] = "Mozilla/1.0";
const char kReferrer[] = "https://www.referrer.org/";

}  // namespace

class HttpNetworkTransactionNetworkErrorLoggingTest
    : public HttpNetworkTransactionTest {
 protected:
  void SetUp() override {
    HttpNetworkTransactionTestBase::SetUp();
    auto network_error_logging_service =
        std::make_unique<TestNetworkErrorLoggingService>();
    test_network_error_logging_service_ = network_error_logging_service.get();
    session_deps_.network_error_logging_service =
        std::move(network_error_logging_service);

    extra_headers_.SetHeader(HttpRequestHeaders::kUserAgent, kUserAgent);
    extra_headers_.SetHeader(HttpRequestHeaders::kReferer, kReferrer);

    request_.method = HttpRequestHeaders::kGetMethod;
    request_.url = GURL(url_);
    request_.network_isolation_key = kNetworkIsolationKey;
    request_.network_anonymization_key = kNetworkAnonymizationKey;
    request_.extra_headers = extra_headers_;
    request_.reporting_upload_depth = reporting_upload_depth_;
    request_.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  }

  void TearDown() override {
    clear_network_error_logging_service();
    HttpNetworkTransactionTestBase::TearDown();
  }

  TestNetworkErrorLoggingService* network_error_logging_service() const {
    return test_network_error_logging_service_;
  }

  void clear_network_error_logging_service() {
    test_network_error_logging_service_ = nullptr;
    session_deps_.network_error_logging_service.reset();
  }

  // Makes an HTTPS request that should install a valid NEL policy.
  void RequestPolicy(CertStatus cert_status = 0) {
    std::string extra_header_string = extra_headers_.ToString();
    MockWrite data_writes[] = {
        MockWrite("GET / HTTP/1.1\r\n"
                  "Host: www.example.org\r\n"
                  "Connection: keep-alive\r\n"),
        MockWrite(ASYNC, extra_header_string),
    };
    MockRead data_reads[] = {
        MockRead("HTTP/1.0 200 OK\r\n"),
        MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
        MockRead("\r\n"),
        MockRead("hello world"),
        MockRead(SYNCHRONOUS, OK),
    };

    StaticSocketDataProvider reads(data_reads, data_writes);
    session_deps_.socket_factory->AddSocketDataProvider(&reads);

    SSLSocketDataProvider ssl(ASYNC, OK);
    if (request_.url.SchemeIsCryptographic()) {
      ssl.ssl_info.cert =
          ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
      ASSERT_TRUE(ssl.ssl_info.cert);
      ssl.ssl_info.cert_status = cert_status;
      session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
    }

    TestCompletionCallback callback;
    auto session = CreateSession(&session_deps_);
    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
    int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
    EXPECT_THAT(callback.GetResult(rv), IsOk());

    std::string response_data;
    ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
    EXPECT_EQ("hello world", response_data);
  }

  void CheckReport(size_t index,
                   int status_code,
                   int error_type,
                   IPAddress server_ip = IPAddress::IPv4Localhost()) {
    ASSERT_LT(index, network_error_logging_service()->errors().size());

    const NetworkErrorLoggingService::RequestDetails& error =
        network_error_logging_service()->errors()[index];
    EXPECT_EQ(url_, error.uri);
    EXPECT_EQ(kNetworkAnonymizationKey, error.network_anonymization_key);
    EXPECT_EQ(kReferrer, error.referrer);
    EXPECT_EQ(kUserAgent, error.user_agent);
    EXPECT_EQ(server_ip, error.server_ip);
    EXPECT_EQ("http/1.1", error.protocol);
    EXPECT_EQ("GET", error.method);
    EXPECT_EQ(status_code, error.status_code);
    EXPECT_EQ(error_type, error.type);
    EXPECT_EQ(0, error.reporting_upload_depth);
  }

 protected:
  std::string url_ = "https://www.example.org/";
  CertStatus cert_status_ = 0;
  HttpRequestInfo request_;
  HttpRequestHeaders extra_headers_;
  int reporting_upload_depth_ = 0;

 private:
  raw_ptr<TestNetworkErrorLoggingService> test_network_error_logging_service_ =
      nullptr;
};

INSTANTIATE_TEST_SUITE_P(All,
                         HttpNetworkTransactionNetworkErrorLoggingTest,
                         testing::ValuesIn(GetTestParams()));

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       DontProcessNelHeaderNoService) {
  clear_network_error_logging_service();
  RequestPolicy();
  // No crash.
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       DontProcessNelHeaderHttp) {
  url_ = "http://www.example.org/";
  request_.url = GURL(url_);
  RequestPolicy();
  EXPECT_EQ(0u, network_error_logging_service()->headers().size());
}

// Don't set NEL policies received on a proxied connection.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       DontProcessNelHeaderProxy) {
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl(ASYNC, OK);
  ssl.ssl_info.cert =
      ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
  ASSERT_TRUE(ssl.ssl_info.cert);
  ssl.ssl_info.cert_status = 0;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback1.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback1.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_TRUE(response->WasFetchedViaProxy());

  // No NEL header was set.
  EXPECT_EQ(0u, network_error_logging_service()->headers().size());
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
  RequestPolicy();
  ASSERT_EQ(1u, network_error_logging_service()->headers().size());
  const auto& header = network_error_logging_service()->headers()[0];
  EXPECT_EQ(kNetworkAnonymizationKey, header.network_anonymization_key);
  EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
            header.origin);
  EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
  EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       DontProcessNelHeaderInvalidHttps) {
  CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
  RequestPolicy(cert_status);
  EXPECT_EQ(0u, network_error_logging_service()->headers().size());
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
  RequestPolicy();
  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  CheckReport(0 /* index */, 200 /* status_code */, OK);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportDNSErrorAfterStartSync) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  session_deps_.host_resolver->set_synchronous_mode(true);
  session_deps_.host_resolver->rules()->AddRule(GURL(url_).GetHost(),
                                                ERR_NAME_NOT_RESOLVED);
  TestCompletionCallback callback;

  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));

  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
              IPAddress() /* server_ip */);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportDNSErrorAfterStartAsync) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  session_deps_.host_resolver->set_synchronous_mode(false);
  session_deps_.host_resolver->rules()->AddRule(GURL(url_).GetHost(),
                                                ERR_NAME_NOT_RESOLVED);
  TestCompletionCallback callback;

  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));

  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
              IPAddress() /* server_ip */);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportErrorAfterStart) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider data;
  data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));

  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  CheckReport(0 /* index */, 0 /* status_code */, ERR_CONNECTION_REFUSED,
              IPAddress::IPv4Localhost() /* server_ip */);
}

// Same as above except the error is ASYNC
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportErrorAfterStartAsync) {
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
  StaticSocketDataProvider data;
  data.set_connect_data(mock_connect);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;

  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));

  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  CheckReport(0 /* index */, 0 /* status_code */, ERR_CONNECTION_REFUSED,
              IPAddress::IPv4Localhost() /* server_ip */);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportReadBodyError) {
  std::string extra_header_string = extra_headers_.ToString();
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),  // wrong content length
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider reads(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&reads);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // Log start time
  base::TimeTicks start_time = base::TimeTicks::Now();

  TestCompletionCallback callback;
  auto session = CreateSession(&session_deps_);
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(trans.get(), &response_data);
  EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));

  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  CheckReport(0 /* index */, 200 /* status_code */,
              ERR_CONTENT_LENGTH_MISMATCH);
  const NetworkErrorLoggingService::RequestDetails& error =
      network_error_logging_service()->errors()[0];
  EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
}

// Same as above except the final read is ASYNC.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportReadBodyErrorAsync) {
  std::string extra_header_string = extra_headers_.ToString();
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),  // wrong content length
      MockRead("hello world"),
      MockRead(ASYNC, OK),
  };

  StaticSocketDataProvider reads(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&reads);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  // Log start time
  base::TimeTicks start_time = base::TimeTicks::Now();

  TestCompletionCallback callback;
  auto session = CreateSession(&session_deps_);
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());

  std::string response_data;
  rv = ReadTransaction(trans.get(), &response_data);
  EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));

  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  CheckReport(0 /* index */, 200 /* status_code */,
              ERR_CONTENT_LENGTH_MISMATCH);
  const NetworkErrorLoggingService::RequestDetails& error =
      network_error_logging_service()->errors()[0];
  EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportRestartWithAuth) {
  std::string extra_header_string = extra_headers_.ToString();
  static const base::TimeDelta kSleepDuration = base::Milliseconds(10);

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      // Give a couple authenticate options (only the middle one is actually
      // supported).
      MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(SYNCHRONOUS, ERR_FAILED),
  };

  // After calling trans->RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  base::TimeTicks start_time = base::TimeTicks::Now();
  base::TimeTicks restart_time;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback1;

  int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(callback1.GetResult(rv), IsOk());

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  TestCompletionCallback callback2;

  // Wait 10 ms then restart with auth
  FastForwardBy(kSleepDuration);
  restart_time = base::TimeTicks::Now();
  rv =
      trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(callback2.GetResult(rv), IsOk());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  trans.reset();

  // One 401 report for the auth challenge, then a 200 report for the successful
  // retry. Note that we don't report the error draining the body, as the first
  // request already generated a report for the auth challenge.
  ASSERT_EQ(2u, network_error_logging_service()->errors().size());

  // Check error report contents
  CheckReport(0 /* index */, 401 /* status_code */, OK);
  CheckReport(1 /* index */, 200 /* status_code */, OK);

  const NetworkErrorLoggingService::RequestDetails& error1 =
      network_error_logging_service()->errors()[0];
  const NetworkErrorLoggingService::RequestDetails& error2 =
      network_error_logging_service()->errors()[1];

  // Sanity-check elapsed time values
  EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
  // Check that the start time is refreshed when restarting with auth.
  EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
}

// Same as above, except draining the body before restarting fails
// asynchronously.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportRestartWithAuthAsync) {
  std::string extra_header_string = extra_headers_.ToString();
  static const base::TimeDelta kSleepDuration = base::Milliseconds(10);

  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
      // Give a couple authenticate options (only the middle one is actually
      // supported).
      MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      // Large content-length -- won't matter, as connection will be reset.
      MockRead("Content-Length: 10000\r\n\r\n"),
      MockRead(ASYNC, ERR_FAILED),
  };

  // After calling trans->RestartWithAuth(), this is the request we should
  // be issuing -- the final header line contains the credentials.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Authorization: Basic Zm9vOmJhcg==\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };

  // Lastly, the server responds with the actual content.
  MockRead data_reads2[] = {
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  base::TimeTicks start_time = base::TimeTicks::Now();
  base::TimeTicks restart_time;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback1;

  int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(callback1.GetResult(rv), IsOk());

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  TestCompletionCallback callback2;

  // Wait 10 ms then restart with auth
  FastForwardBy(kSleepDuration);
  restart_time = base::TimeTicks::Now();
  rv =
      trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(callback2.GetResult(rv), IsOk());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  trans.reset();

  // One 401 report for the auth challenge, then a 200 report for the successful
  // retry. Note that we don't report the error draining the body, as the first
  // request already generated a report for the auth challenge.
  ASSERT_EQ(2u, network_error_logging_service()->errors().size());

  // Check error report contents
  CheckReport(0 /* index */, 401 /* status_code */, OK);
  CheckReport(1 /* index */, 200 /* status_code */, OK);

  const NetworkErrorLoggingService::RequestDetails& error1 =
      network_error_logging_service()->errors()[0];
  const NetworkErrorLoggingService::RequestDetails& error2 =
      network_error_logging_service()->errors()[1];

  // Sanity-check elapsed time values
  EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
  // Check that the start time is refreshed when restarting with auth.
  EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportRetryKeepAliveConnectionReset) {
  std::string extra_header_string = extra_headers_.ToString();
  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("hello"),
      // Connection is reset
      MockRead(ASYNC, ERR_CONNECTION_RESET),
  };

  // Successful retry
  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("world"),
      MockRead(ASYNC, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback1;

  int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(callback1.GetResult(rv), IsOk());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
  EXPECT_EQ("hello", response_data);

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback2;

  rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
  EXPECT_THAT(callback2.GetResult(rv), IsOk());

  ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
  EXPECT_EQ("world", response_data);

  trans1.reset();
  trans2.reset();

  // One OK report from first request, then a ERR_CONNECTION_RESET report from
  // the second request, then an OK report from the successful retry.
  ASSERT_EQ(3u, network_error_logging_service()->errors().size());

  // Check error report contents
  CheckReport(0 /* index */, 200 /* status_code */, OK);
  CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
  CheckReport(2 /* index */, 200 /* status_code */, OK);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportRetryKeepAlive408) {
  std::string extra_header_string = extra_headers_.ToString();
  MockWrite data_writes1[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("hello"),
      // 408 Request Timeout
      MockRead(SYNCHRONOUS,
               "HTTP/1.1 408 Request Timeout\r\n"
               "Connection: Keep-Alive\r\n"
               "Content-Length: 6\r\n\r\n"
               "Pickle"),
  };

  // Successful retry
  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
      MockRead("world"),
      MockRead(ASYNC, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback1;

  int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(callback1.GetResult(rv), IsOk());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
  EXPECT_EQ("hello", response_data);

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback2;

  rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
  EXPECT_THAT(callback2.GetResult(rv), IsOk());

  ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
  EXPECT_EQ("world", response_data);

  trans1.reset();
  trans2.reset();

  // One 200 report from first request, then a 408 report from
  // the second request, then a 200 report from the successful retry.
  ASSERT_EQ(3u, network_error_logging_service()->errors().size());

  // Check error report contents
  CheckReport(0 /* index */, 200 /* status_code */, OK);
  CheckReport(1 /* index */, 408 /* status_code */, OK);
  CheckReport(2 /* index */, 200 /* status_code */, OK);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportRetry421WithoutConnectionPooling) {
  // Two hosts resolve to the same IP address.
  const std::string ip_addr = "1.2.3.4";
  IPAddress ip;
  ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
  IPEndPoint peer_addr = IPEndPoint(ip, 443);

  session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
  session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
  session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Two requests on the first connection.
  spdy::SpdySerializedFrame req1(
      spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
  spdy_util_.UpdateWithStreamDestruction(1);
  spdy::SpdySerializedFrame req2(
      spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
  spdy::SpdySerializedFrame rst(
      spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
  MockWrite writes1[] = {
      CreateMockWrite(req1, 0),
      CreateMockWrite(req2, 3),
      CreateMockWrite(rst, 6),
  };

  // The first one succeeds, the second gets error 421 Misdirected Request.
  spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
  quiche::HttpHeaderBlock response_headers;
  response_headers[spdy::kHttp2StatusHeader] = "421";
  spdy::SpdySerializedFrame resp2(
      spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
  MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
                       CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};

  MockConnect connect1(ASYNC, OK, peer_addr);
  SequencedSocketData data1(connect1, reads1, writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  AddSSLSocketData();

  // Retry the second request on a second connection.
  SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
  spdy::SpdySerializedFrame req3(
      spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
  MockWrite writes2[] = {
      CreateMockWrite(req3, 0),
  };

  spdy::SpdySerializedFrame resp3(spdy_util2.ConstructSpdyGetReply(
      base::span<const std::string_view>(), 1));
  spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
  MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
                       MockRead(ASYNC, 0, 3)};

  MockConnect connect2(ASYNC, OK, peer_addr);
  SequencedSocketData data2(connect2, reads2, writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  AddSSLSocketData();

  // Preload mail.example.org into HostCache.
  int rv = session_deps_.host_resolver->LoadIntoCache(
      HostPortPair("mail.example.org", 443), NetworkAnonymizationKey(),
      std::nullopt);
  EXPECT_THAT(rv, IsOk());

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/");
  request1.load_flags = 0;
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;
  rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans1->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  trans1.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://mail.example.org/");
  request2.load_flags = 0;
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  rv = trans2->Start(&request2, callback.callback(),
                     NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  response = trans2->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
  EXPECT_TRUE(response->was_fetched_via_spdy);
  EXPECT_TRUE(response->was_alpn_negotiated);
  ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
  EXPECT_EQ("hello!", response_data);

  trans2.reset();

  // One 200 report from the first request, then a 421 report from the
  // second request, then a 200 report from the successful retry.
  ASSERT_EQ(3u, network_error_logging_service()->errors().size());

  // Check error report contents
  const NetworkErrorLoggingService::RequestDetails& error1 =
      network_error_logging_service()->errors()[0];
  EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
  EXPECT_TRUE(error1.referrer.is_empty());
  EXPECT_EQ("", error1.user_agent);
  EXPECT_EQ(ip, error1.server_ip);
  EXPECT_EQ("h2", error1.protocol);
  EXPECT_EQ("GET", error1.method);
  EXPECT_EQ(200, error1.status_code);
  EXPECT_EQ(OK, error1.type);
  EXPECT_EQ(0, error1.reporting_upload_depth);

  const NetworkErrorLoggingService::RequestDetails& error2 =
      network_error_logging_service()->errors()[1];
  EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
  EXPECT_TRUE(error2.referrer.is_empty());
  EXPECT_EQ("", error2.user_agent);
  EXPECT_EQ(ip, error2.server_ip);
  EXPECT_EQ("h2", error2.protocol);
  EXPECT_EQ("GET", error2.method);
  EXPECT_EQ(421, error2.status_code);
  EXPECT_EQ(OK, error2.type);
  EXPECT_EQ(0, error2.reporting_upload_depth);

  const NetworkErrorLoggingService::RequestDetails& error3 =
      network_error_logging_service()->errors()[2];
  EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
  EXPECT_TRUE(error3.referrer.is_empty());
  EXPECT_EQ("", error3.user_agent);
  EXPECT_EQ(ip, error3.server_ip);
  EXPECT_EQ("h2", error3.protocol);
  EXPECT_EQ("GET", error3.method);
  EXPECT_EQ(200, error3.status_code);
  EXPECT_EQ(OK, error3.type);
  EXPECT_EQ(0, error3.reporting_upload_depth);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportCancelAfterStart) {
  StaticSocketDataProvider data;
  data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  TestCompletionCallback callback;
  auto session = CreateSession(&session_deps_);
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_EQ(rv, ERR_IO_PENDING);

  // Cancel after start.
  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
              IPAddress() /* server_ip */);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       CreateReportCancelBeforeReadingBody) {
  std::string extra_header_string = extra_headers_.ToString();
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),  // Body is never read.
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;
  auto session = CreateSession(&session_deps_);
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);

  EXPECT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());

  // Cancel before reading the body.
  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
  RequestPolicy();
  EXPECT_EQ(1u, network_error_logging_service()->headers().size());
  EXPECT_EQ(1u, network_error_logging_service()->errors().size());

  // Make HTTP request
  std::string extra_header_string = extra_headers_.ToString();
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n\r\n"),
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, extra_header_string),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  // Insecure url
  url_ = "http://www.example.org/";
  request_.url = GURL(url_);

  TestCompletionCallback callback;
  auto session = CreateSession(&session_deps_);
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  // Insecure request does not generate a report
  EXPECT_EQ(1u, network_error_logging_service()->errors().size());
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       DontCreateReportHttpError) {
  RequestPolicy();
  EXPECT_EQ(1u, network_error_logging_service()->headers().size());
  EXPECT_EQ(1u, network_error_logging_service()->errors().size());

  // Make HTTP request that fails
  MockRead data_reads[] = {
      MockRead("hello world"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  url_ = "http://www.originwithoutpolicy.com:2000/";
  request_.url = GURL(url_);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback;
  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));

  // Insecure request does not generate a report, regardless of existence of a
  // policy for the origin.
  EXPECT_EQ(1u, network_error_logging_service()->errors().size());
}

// Don't report on proxy auth challenges, don't report if connecting through a
// proxy.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Configure against proxy server "myproxy:70".
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
          "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Since we have proxy, should try to establish tunnel.
  MockWrite data_writes1[] = {
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n\r\n"),
  };

  // The proxy responds to the connect with a 407, using a non-persistent
  // connection.
  MockRead data_reads1[] = {
      // No credentials.
      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
      MockRead("Proxy-Connection: close\r\n\r\n"),
  };

  MockWrite data_writes2[] = {
      // After calling trans->RestartWithAuth(), this is the request we should
      // be issuing -- the final header line contains the credentials.
      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
                "Host: www.example.org:443\r\n"
                "Proxy-Connection: keep-alive\r\n"
                "User-Agent: test-ua\r\n"
                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),

      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),

      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 5\r\n\r\n"),
      MockRead(SYNCHRONOUS, "hello"),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback1;

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(callback1.GetResult(rv), IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  EXPECT_EQ(407, response->headers->response_code());

  std::string response_data;
  rv = ReadTransaction(trans.get(), &response_data);
  EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));

  // No NEL report is generated for the 407.
  EXPECT_EQ(0u, network_error_logging_service()->errors().size());

  TestCompletionCallback callback2;

  rv =
      trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
  EXPECT_THAT(callback2.GetResult(rv), IsOk());

  response = trans->GetResponseInfo();
  EXPECT_EQ(200, response->headers->response_code());

  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello", response_data);

  trans.reset();

  // No NEL report is generated because we are behind a proxy.
  EXPECT_EQ(0u, network_error_logging_service()->errors().size());
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
       ReportContainsUploadDepth) {
  reporting_upload_depth_ = 7;
  request_.reporting_upload_depth = reporting_upload_depth_;
  RequestPolicy();
  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
  const NetworkErrorLoggingService::RequestDetails& error =
      network_error_logging_service()->errors()[0];
  EXPECT_EQ(7, error.reporting_upload_depth);
}

TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
  std::string extra_header_string = extra_headers_.ToString();
  static const base::TimeDelta kSleepDuration = base::Milliseconds(10);

  std::vector<MockWrite> data_writes = {
      MockWrite(ASYNC, 0,
                "GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"),
      MockWrite(ASYNC, 1, extra_header_string),
  };

  std::vector<MockRead> data_reads = {
      // Write one byte of the status line, followed by a pause.
      MockRead(ASYNC, 2, "H"),
      MockRead(ASYNC, ERR_IO_PENDING, 3),
      MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
      MockRead(ASYNC, 5, "hello world"),
      MockRead(SYNCHRONOUS, OK, 6),
  };

  SequencedSocketData data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  TestCompletionCallback callback;

  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  data.RunUntilPaused();
  ASSERT_TRUE(data.IsPaused());
  FastForwardBy(kSleepDuration);
  data.Resume();

  EXPECT_THAT(callback.GetResult(rv), IsOk());

  std::string response_data;
  ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("hello world", response_data);

  trans.reset();

  ASSERT_EQ(1u, network_error_logging_service()->errors().size());

  CheckReport(0 /* index */, 200 /* status_code */, OK);

  const NetworkErrorLoggingService::RequestDetails& error =
      network_error_logging_service()->errors()[0];

  // Sanity-check elapsed time in error report
  EXPECT_EQ(kSleepDuration, error.elapsed_time);
}

#endif  // BUILDFLAG(ENABLE_REPORTING)

TEST_P(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://example.org/");

  request.load_flags = LOAD_ONLY_FROM_CACHE;

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
  TestCompletionCallback callback1;
  int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());

  EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
}

TEST_P(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
  static const base::TimeDelta kDelay = base::Milliseconds(10);
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  ssl.connect_callback = FastForwardByCallback(kDelay);
  ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
  ssl.confirm_callback = FastForwardByCallback(kDelay);
  session_deps_.enable_early_data = true;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  base::TimeTicks start_time = base::TimeTicks::Now();
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(1, response->headers->GetContentLength()->InBytes());

  // Check that ConfirmHandshake wasn't called.
  ASSERT_FALSE(ssl.ConfirmDataConsumed());
  ASSERT_TRUE(ssl.WriteBeforeConfirm());

  // The handshake time should include the time it took to run Connect(), but
  // not ConfirmHandshake().
  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
  EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
  EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
  EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);

  trans.reset();

  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

TEST_P(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
  static const base::TimeDelta kDelay = base::Milliseconds(10);
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite(SYNCHRONOUS,
                "POST / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  ssl.connect_callback = FastForwardByCallback(kDelay);
  ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
  ssl.confirm_callback = FastForwardByCallback(kDelay);
  session_deps_.enable_early_data = true;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  base::TimeTicks start_time = base::TimeTicks::Now();
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(1, response->headers->GetContentLength()->InBytes());

  // Check that the Write didn't get called before ConfirmHandshake completed.
  ASSERT_FALSE(ssl.WriteBeforeConfirm());

  // The handshake time should include the time it took to run Connect(), but
  // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
  // assume the connection did not negotiate 0-RTT or the handshake was already
  // confirmed.
  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
  EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
  EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
  EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);

  trans.reset();

  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

TEST_P(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite(ASYNC,
                "POST / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
  session_deps_.enable_early_data = true;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(1, response->headers->GetContentLength()->InBytes());

  // Check that the Write didn't get called before ConfirmHandshake completed.
  ASSERT_FALSE(ssl.WriteBeforeConfirm());

  trans.reset();

  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

TEST_P(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
  static const base::TimeDelta kDelay = base::Milliseconds(10);
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite(SYNCHRONOUS,
                "POST / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  ssl.connect_callback = FastForwardByCallback(kDelay);
  ssl.confirm = MockConfirm(ASYNC, OK);
  ssl.confirm_callback = FastForwardByCallback(kDelay);
  session_deps_.enable_early_data = true;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  base::TimeTicks start_time = base::TimeTicks::Now();
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(1, response->headers->GetContentLength()->InBytes());

  // Check that the Write didn't get called before ConfirmHandshake completed.
  ASSERT_FALSE(ssl.WriteBeforeConfirm());

  // The handshake time should include the time it took to run Connect() and
  // ConfirmHandshake().
  LoadTimingInfo load_timing_info;
  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
  EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
  EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
  EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
  EXPECT_EQ(load_timing_info.connect_timing.connect_end,
            start_time + 2 * kDelay);

  trans.reset();

  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

TEST_P(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite(ASYNC,
                "POST / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  ssl.confirm = MockConfirm(ASYNC, OK);
  session_deps_.enable_early_data = true;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ(200, response->headers->response_code());
  EXPECT_EQ(1, response->headers->GetContentLength()->InBytes());

  // Check that the Write didn't get called before ConfirmHandshake completed.
  ASSERT_FALSE(ssl.WriteBeforeConfirm());

  trans.reset();

  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// 0-RTT rejects are handled at HttpNetworkTransaction.
TEST_P(HttpNetworkTransactionTest, ZeroRTTReject) {
  enum class RejectType {
    kRead,
    kWrite,
    kConfirm,
  };

  for (RejectType type :
       {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
    SCOPED_TRACE(static_cast<int>(type));
    for (Error reject_error :
         {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
      SCOPED_TRACE(reject_error);
      session_deps_.socket_factory =
          std::make_unique<MockClientSocketFactory>();

      HttpRequestInfo request;
      request.method = type == RejectType::kConfirm ? "POST" : "GET";
      request.url = GURL("https://www.example.org/");
      request.traffic_annotation =
          MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

      // The first request fails.
      std::vector<MockWrite> data1_writes;
      std::vector<MockRead> data1_reads;
      SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
      switch (type) {
        case RejectType::kRead:
          data1_writes.emplace_back(
              "GET / HTTP/1.1\r\n"
              "Host: www.example.org\r\n"
              "Connection: keep-alive\r\n\r\n");
          data1_reads.emplace_back(ASYNC, reject_error);
          // Cause ConfirmHandshake to hang (it should not be called).
          ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
          break;
        case RejectType::kWrite:
          data1_writes.emplace_back(ASYNC, reject_error);
          // Cause ConfirmHandshake to hang (it should not be called).
          ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
          break;
        case RejectType::kConfirm:
          // The request never gets far enough to read or write.
          ssl1.confirm = MockConfirm(ASYNC, reject_error);
          break;
      }

      StaticSocketDataProvider data1(data1_reads, data1_writes);
      session_deps_.socket_factory->AddSocketDataProvider(&data1);
      session_deps_.enable_early_data = true;
      session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);

      // The retry succeeds.
      //
      // TODO(crbug.com/41451775): If |reject_error| is
      // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
      MockWrite data2_writes[] = {
          request.method == "POST"
              ? MockWrite("POST / HTTP/1.1\r\n"
                          "Host: www.example.org\r\n"
                          "Connection: keep-alive\r\n"
                          "Content-Length: 0\r\n\r\n")
              : MockWrite("GET / HTTP/1.1\r\n"
                          "Host: www.example.org\r\n"
                          "Connection: keep-alive\r\n\r\n"),
      };

      MockRead data2_reads[] = {
          MockRead("HTTP/1.1 200 OK\r\n"),
          MockRead("Content-Length: 1\r\n\r\n"),
          MockRead(SYNCHRONOUS, "1"),
      };

      StaticSocketDataProvider data2(data2_reads, data2_writes);
      session_deps_.socket_factory->AddSocketDataProvider(&data2);
      SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
      ssl2.confirm = MockConfirm(ASYNC, OK);
      session_deps_.enable_early_data = true;
      session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

      std::unique_ptr<HttpNetworkSession> session(
          CreateSession(&session_deps_));

      TestCompletionCallback callback;
      auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
                                                            session.get());

      EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
                                                  NetLogWithSource())),
                  IsOk());

      const HttpResponseInfo* response = trans->GetResponseInfo();
      ASSERT_TRUE(response);
      ASSERT_TRUE(response->headers);
      EXPECT_EQ(200, response->headers->response_code());
      EXPECT_EQ(1, response->headers->GetContentLength()->InBytes());
    }
  }
}

TEST_P(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
  session_deps_.enable_early_data = true;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));

  // Check that the Write didn't get called before ConfirmHandshake completed.
  ASSERT_FALSE(ssl.WriteBeforeConfirm());

  trans.reset();

  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

TEST_P(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
  HttpRequestInfo request;
  request.method = "POST";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  MockWrite data_writes[] = {
      MockWrite("POST / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "Content-Length: 0\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"),
      MockRead("Content-Length: 1\r\n\r\n"),
      MockRead(SYNCHRONOUS, "1"),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
  ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
  session_deps_.enable_early_data = true;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());

  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));

  // Check that the Write didn't get called before ConfirmHandshake completed.
  ASSERT_FALSE(ssl.WriteBeforeConfirm());

  trans.reset();

  session->CloseAllConnections(ERR_FAILED, "Very good reason");
}

// Test the proxy and origin server each requesting both TLS client certificates
// and HTTP auth. This is a regression test for https://crbug.com/946406.
TEST_P(HttpNetworkTransactionTest, AuthEverything) {
  // Note these hosts must match the CheckBasic*Auth() functions.
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);

  std::unique_ptr<FakeClientCertIdentity> identity_proxy =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
  ASSERT_TRUE(identity_proxy);

  auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_origin->host_and_port =
      HostPortPair("www.example.org", 443);

  std::unique_ptr<FakeClientCertIdentity> identity_origin =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
  ASSERT_TRUE(identity_origin);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // First, the client connects to the proxy, which requests a client
  // certificate.
  SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl_proxy1.cert_request_info = cert_request_info_proxy;
  ssl_proxy1.expected_send_client_cert = false;
  StaticSocketDataProvider data1;
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);

  // The client responds with a certificate on a new connection. The handshake
  // succeeds.
  SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
  ssl_proxy2.expected_send_client_cert = true;
  ssl_proxy2.expected_client_cert = identity_proxy->certificate();
  // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
  std::vector<MockWrite> mock_writes2;
  std::vector<MockRead> mock_reads2;
  mock_writes2.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n\r\n");
  mock_reads2.emplace_back(
      "HTTP/1.1 407 Proxy Authentication Required\r\n"
      "Content-Length: 0\r\n"
      "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
  // The client retries with credentials.
  mock_writes2.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  // The origin requests client certificates.
  SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl_origin2.cert_request_info = cert_request_info_origin;
  StaticSocketDataProvider data2(mock_reads2, mock_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);

  // The client responds to the origin client certificate request on a new
  // connection.
  SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
  ssl_proxy3.expected_send_client_cert = true;
  ssl_proxy3.expected_client_cert = identity_proxy->certificate();
  std::vector<MockWrite> mock_writes3;
  std::vector<MockRead> mock_reads3;
  mock_writes3.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  SSLSocketDataProvider ssl_origin3(ASYNC, OK);
  ssl_origin3.expected_send_client_cert = true;
  ssl_origin3.expected_client_cert = identity_origin->certificate();
  // The client sends the origin HTTP request, which results in another HTTP
  // auth request.
  mock_writes3.emplace_back(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n");
  mock_reads3.emplace_back(
      "HTTP/1.1 401 Unauthorized\r\n"
      "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
      "Content-Length: 0\r\n\r\n");
  // The client retries with credentials, and the request finally succeeds.
  mock_writes3.emplace_back(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n"
      // Authenticate as user:pass.
      "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
  mock_reads3.emplace_back(
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 0\r\n\r\n");
  // The client makes another request. This should reuse the socket with all
  // credentials cached.
  mock_writes3.emplace_back(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n"
      // Authenticate as user:pass.
      "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
  mock_reads3.emplace_back(
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 0\r\n\r\n");
  StaticSocketDataProvider data3(mock_reads3, mock_writes3);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Start the request.
  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = callback.GetResult(
      trans->Start(&request, callback.callback(), NetLogWithSource()));

  // Handle the proxy client certificate challenge.
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans->GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_TRUE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port,
            cert_request_info_proxy->host_and_port);
  rv = callback.GetResult(trans->RestartWithCertificate(
      identity_proxy->certificate(), identity_proxy->ssl_private_key(),
      callback.callback()));

  // Handle the proxy HTTP auth challenge.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
  EXPECT_TRUE(
      CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
  rv = callback.GetResult(trans->RestartWithAuth(
      AuthCredentials(u"proxyuser", u"proxypass"), callback.callback()));

  // Handle the origin client certificate challenge.
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_FALSE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port,
            cert_request_info_origin->host_and_port);
  rv = callback.GetResult(trans->RestartWithCertificate(
      identity_origin->certificate(), identity_origin->ssl_private_key(),
      callback.callback()));

  // Handle the origin HTTP auth challenge.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
  EXPECT_TRUE(
      CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
  rv = callback.GetResult(trans->RestartWithAuth(
      AuthCredentials(u"user", u"pass"), callback.callback()));

  // The request completes.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());

  // Make a second request. This time all credentials are cached.
  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
                                              NetLogWithSource())),
              IsOk());
  EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
}

// Test the proxy and origin server each requesting both TLS client certificates
// and HTTP auth and each HTTP auth closing the connection. This is a regression
// test for https://crbug.com/946406.
TEST_P(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
  // Note these hosts must match the CheckBasic*Auth() functions.
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);

  std::unique_ptr<FakeClientCertIdentity> identity_proxy =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
  ASSERT_TRUE(identity_proxy);

  auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_origin->host_and_port =
      HostPortPair("www.example.org", 443);

  std::unique_ptr<FakeClientCertIdentity> identity_origin =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
  ASSERT_TRUE(identity_origin);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // First, the client connects to the proxy, which requests a client
  // certificate.
  SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl_proxy1.cert_request_info = cert_request_info_proxy;
  ssl_proxy1.expected_send_client_cert = false;
  StaticSocketDataProvider data1;
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);

  // The client responds with a certificate on a new connection. The handshake
  // succeeds.
  SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
  ssl_proxy2.expected_send_client_cert = true;
  ssl_proxy2.expected_client_cert = identity_proxy->certificate();
  // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
  std::vector<MockWrite> mock_writes2;
  std::vector<MockRead> mock_reads2;
  mock_writes2.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n\r\n");
  mock_reads2.emplace_back(
      "HTTP/1.1 407 Proxy Authentication Required\r\n"
      "Content-Length: 0\r\n"
      "Proxy-Connection: close\r\n"
      "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
  StaticSocketDataProvider data2(mock_reads2, mock_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);

  // The client retries with credentials on a new connection.
  SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
  ssl_proxy3.expected_send_client_cert = true;
  ssl_proxy3.expected_client_cert = identity_proxy->certificate();
  std::vector<MockWrite> mock_writes3;
  std::vector<MockRead> mock_reads3;
  mock_writes3.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  // The origin requests client certificates.
  SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl_origin3.cert_request_info = cert_request_info_origin;
  StaticSocketDataProvider data3(mock_reads3, mock_writes3);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);

  // The client responds to the origin client certificate request on a new
  // connection.
  SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
  ssl_proxy4.expected_send_client_cert = true;
  ssl_proxy4.expected_client_cert = identity_proxy->certificate();
  std::vector<MockWrite> mock_writes4;
  std::vector<MockRead> mock_reads4;
  mock_writes4.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  SSLSocketDataProvider ssl_origin4(ASYNC, OK);
  ssl_origin4.expected_send_client_cert = true;
  ssl_origin4.expected_client_cert = identity_origin->certificate();
  // The client sends the origin HTTP request, which results in another HTTP
  // auth request and closed connection.
  mock_writes4.emplace_back(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n");
  mock_reads4.emplace_back(
      "HTTP/1.1 401 Unauthorized\r\n"
      "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
      "Connection: close\r\n"
      "Content-Length: 0\r\n\r\n");
  StaticSocketDataProvider data4(mock_reads4, mock_writes4);
  session_deps_.socket_factory->AddSocketDataProvider(&data4);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);

  // The client retries with credentials on a new connection, and the request
  // finally succeeds.
  SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
  ssl_proxy5.expected_send_client_cert = true;
  ssl_proxy5.expected_client_cert = identity_proxy->certificate();
  std::vector<MockWrite> mock_writes5;
  std::vector<MockRead> mock_reads5;
  mock_writes5.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  SSLSocketDataProvider ssl_origin5(ASYNC, OK);
  ssl_origin5.expected_send_client_cert = true;
  ssl_origin5.expected_client_cert = identity_origin->certificate();
  mock_writes5.emplace_back(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n"
      // Authenticate as user:pass.
      "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
  mock_reads5.emplace_back(
      "HTTP/1.1 200 OK\r\n"
      "Connection: close\r\n"
      "Content-Length: 0\r\n\r\n");
  StaticSocketDataProvider data5(mock_reads5, mock_writes5);
  session_deps_.socket_factory->AddSocketDataProvider(&data5);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);

  // The client makes a second request. This needs yet another connection, but
  // all credentials are cached.
  SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
  ssl_proxy6.expected_send_client_cert = true;
  ssl_proxy6.expected_client_cert = identity_proxy->certificate();
  std::vector<MockWrite> mock_writes6;
  std::vector<MockRead> mock_reads6;
  mock_writes6.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  SSLSocketDataProvider ssl_origin6(ASYNC, OK);
  ssl_origin6.expected_send_client_cert = true;
  ssl_origin6.expected_client_cert = identity_origin->certificate();
  mock_writes6.emplace_back(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n"
      // Authenticate as user:pass.
      "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
  mock_reads6.emplace_back(
      "HTTP/1.1 200 OK\r\n"
      "Connection: close\r\n"
      "Content-Length: 0\r\n\r\n");
  StaticSocketDataProvider data6(mock_reads6, mock_writes6);
  session_deps_.socket_factory->AddSocketDataProvider(&data6);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Start the request.
  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = callback.GetResult(
      trans->Start(&request, callback.callback(), NetLogWithSource()));

  // Handle the proxy client certificate challenge.
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans->GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_TRUE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port,
            cert_request_info_proxy->host_and_port);
  rv = callback.GetResult(trans->RestartWithCertificate(
      identity_proxy->certificate(), identity_proxy->ssl_private_key(),
      callback.callback()));

  // Handle the proxy HTTP auth challenge.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
  EXPECT_TRUE(
      CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
  rv = callback.GetResult(trans->RestartWithAuth(
      AuthCredentials(u"proxyuser", u"proxypass"), callback.callback()));

  // Handle the origin client certificate challenge.
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_FALSE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port,
            cert_request_info_origin->host_and_port);
  rv = callback.GetResult(trans->RestartWithCertificate(
      identity_origin->certificate(), identity_origin->ssl_private_key(),
      callback.callback()));

  // Handle the origin HTTP auth challenge.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
  EXPECT_TRUE(
      CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
  rv = callback.GetResult(trans->RestartWithAuth(
      AuthCredentials(u"user", u"pass"), callback.callback()));

  // The request completes.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());

  // Make a second request. This time all credentials are cached.
  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
                                              NetLogWithSource())),
              IsOk());
  EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
}

// Test the proxy requesting HTTP auth and the server requesting TLS client
// certificates. This is a regression test for https://crbug.com/946406.
TEST_P(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
  // Note these hosts must match the CheckBasic*Auth() functions.
  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info_origin->host_and_port =
      HostPortPair("www.example.org", 443);

  std::unique_ptr<FakeClientCertIdentity> identity_origin =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
  ASSERT_TRUE(identity_origin);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // The client connects to the proxy. The handshake succeeds.
  SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
  // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
  std::vector<MockWrite> mock_writes1;
  std::vector<MockRead> mock_reads1;
  mock_writes1.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n\r\n");
  mock_reads1.emplace_back(
      "HTTP/1.1 407 Proxy Authentication Required\r\n"
      "Content-Length: 0\r\n"
      "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
  // The client retries with credentials, and the request finally succeeds.
  mock_writes1.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  // The origin requests client certificates.
  SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl_origin1.cert_request_info = cert_request_info_origin;
  StaticSocketDataProvider data1(mock_reads1, mock_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);

  // The client responds to the origin client certificate request on a new
  // connection.
  SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
  std::vector<MockWrite> mock_writes2;
  std::vector<MockRead> mock_reads2;
  mock_writes2.emplace_back(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      // Authenticate as proxyuser:proxypass.
      "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
  mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
  SSLSocketDataProvider ssl_origin2(ASYNC, OK);
  ssl_origin2.expected_send_client_cert = true;
  ssl_origin2.expected_client_cert = identity_origin->certificate();
  // The client sends the origin HTTP request, which succeeds.
  mock_writes2.emplace_back(
      "GET / HTTP/1.1\r\n"
      "Host: www.example.org\r\n"
      "Connection: keep-alive\r\n\r\n");
  mock_reads2.emplace_back(
      "HTTP/1.1 200 OK\r\n"
      "Content-Length: 0\r\n\r\n");
  StaticSocketDataProvider data2(mock_reads2, mock_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Start the request.
  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = callback.GetResult(
      trans->Start(&request, callback.callback(), NetLogWithSource()));

  // Handle the proxy HTTP auth challenge.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
  EXPECT_TRUE(
      CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
  rv = callback.GetResult(trans->RestartWithAuth(
      AuthCredentials(u"proxyuser", u"proxypass"), callback.callback()));

  // Handle the origin client certificate challenge.
  ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
  SSLCertRequestInfo* cert_request_info =
      trans->GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(cert_request_info);
  EXPECT_FALSE(cert_request_info->is_proxy);
  EXPECT_EQ(cert_request_info->host_and_port,
            cert_request_info_origin->host_and_port);
  rv = callback.GetResult(trans->RestartWithCertificate(
      identity_origin->certificate(), identity_origin->ssl_private_key(),
      callback.callback()));

  // The request completes.
  ASSERT_THAT(rv, IsOk());
  EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
}

// Test that socket reuse works with client certificates.
TEST_P(HttpNetworkTransactionTest, ClientCertSocketReuse) {
  auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info->host_and_port = HostPortPair("www.example.org", 443);

  std::unique_ptr<FakeClientCertIdentity> identity =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
  ASSERT_TRUE(identity);

  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://www.example.org/a");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://www.example.org/b");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // The first connection results in a client certificate request.
  StaticSocketDataProvider data1;
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
  ssl1.cert_request_info = cert_request_info;
  ssl1.expected_send_client_cert = false;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);

  // The second connection succeeds and is usable for both requests.
  MockWrite mock_writes[] = {
      MockWrite("GET /a HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
      MockWrite("GET /b HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  MockRead mock_reads[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Length: 0\r\n\r\n"),
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Length: 0\r\n\r\n"),
  };
  StaticSocketDataProvider data2(mock_reads, mock_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.expected_send_client_cert = true;
  ssl2.expected_client_cert = identity->certificate();
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Start the first request. It succeeds after providing client certificates.
  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
                                              NetLogWithSource())),
              IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));

  SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
  ASSERT_TRUE(info);
  EXPECT_FALSE(info->is_proxy);
  EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);

  ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
                  identity->certificate(), identity->ssl_private_key(),
                  callback.callback())),
              IsOk());
  EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());

  // Make the second request. It completes without requesting client
  // certificates.
  trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
                                              NetLogWithSource())),
              IsOk());
  EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
}

// Test for partitioning connections by NetworkAnonymizationKey. Runs 3 requests
// in sequence with two different NetworkAnonymizationKeys, the first and last
// have the same key, the second a different one. Checks that the requests are
// partitioned across sockets as expected.
TEST_P(HttpNetworkTransactionTest, NetworkIsolation) {
  const SchemefulSite kSite1(GURL("http://origin1/"));
  const SchemefulSite kSite2(GURL("http://origin2/"));
  const auto network_anonymization_key1 =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  const auto network_anonymization_key2 =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
  NetworkIsolationKey network_isolation_key2(kSite2, kSite2);

  for (bool partition_connections : {false, true}) {
    SCOPED_TRACE(partition_connections);

    base::test::ScopedFeatureList feature_list;
    if (partition_connections) {
      feature_list.InitAndEnableFeature(
          features::kPartitionConnectionsByNetworkIsolationKey);
    } else {
      feature_list.InitAndDisableFeature(
          features::kPartitionConnectionsByNetworkIsolationKey);
    }

    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

    // Reads and writes for the unpartitioned case, where only one socket is
    // used.

    const MockWrite kUnpartitionedWrites[] = {
        MockWrite("GET /1 HTTP/1.1\r\n"
                  "Host: foo.test\r\n"
                  "Connection: keep-alive\r\n\r\n"),
        MockWrite("GET /2 HTTP/1.1\r\n"
                  "Host: foo.test\r\n"
                  "Connection: keep-alive\r\n\r\n"),
        MockWrite("GET /3 HTTP/1.1\r\n"
                  "Host: foo.test\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    const MockRead kUnpartitionedReads[] = {
        MockRead("HTTP/1.1 200 OK\r\n"
                 "Connection: keep-alive\r\n"
                 "Content-Length: 1\r\n\r\n"
                 "1"),
        MockRead("HTTP/1.1 200 OK\r\n"
                 "Connection: keep-alive\r\n"
                 "Content-Length: 1\r\n\r\n"
                 "2"),
        MockRead("HTTP/1.1 200 OK\r\n"
                 "Connection: keep-alive\r\n"
                 "Content-Length: 1\r\n\r\n"
                 "3"),
    };

    StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
                                                kUnpartitionedWrites);

    // Reads and writes for the partitioned case, where two sockets are used.

    const MockWrite kPartitionedWrites1[] = {
        MockWrite("GET /1 HTTP/1.1\r\n"
                  "Host: foo.test\r\n"
                  "Connection: keep-alive\r\n\r\n"),
        MockWrite("GET /3 HTTP/1.1\r\n"
                  "Host: foo.test\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    const MockRead kPartitionedReads1[] = {
        MockRead("HTTP/1.1 200 OK\r\n"
                 "Connection: keep-alive\r\n"
                 "Content-Length: 1\r\n\r\n"
                 "1"),
        MockRead("HTTP/1.1 200 OK\r\n"
                 "Connection: keep-alive\r\n"
                 "Content-Length: 1\r\n\r\n"
                 "3"),
    };

    const MockWrite kPartitionedWrites2[] = {
        MockWrite("GET /2 HTTP/1.1\r\n"
                  "Host: foo.test\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    const MockRead kPartitionedReads2[] = {
        MockRead("HTTP/1.1 200 OK\r\n"
                 "Connection: keep-alive\r\n"
                 "Content-Length: 1\r\n\r\n"
                 "2"),
    };

    StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
                                               kPartitionedWrites1);
    StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
                                               kPartitionedWrites2);

    if (partition_connections) {
      session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
      session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
    } else {
      session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
    }

    TestCompletionCallback callback;
    HttpRequestInfo request1;
    request1.method = "GET";
    request1.url = GURL("http://foo.test/1");
    request1.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
    request1.network_isolation_key = network_isolation_key1;
    request1.network_anonymization_key = network_anonymization_key1;
    auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
                                                           session.get());
    int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
    EXPECT_THAT(callback.GetResult(rv), IsOk());
    std::string response_data1;
    EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
    EXPECT_EQ("1", response_data1);
    trans1.reset();

    HttpRequestInfo request2;
    request2.method = "GET";
    request2.url = GURL("http://foo.test/2");
    request2.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
    request2.network_isolation_key = network_isolation_key2;
    request2.network_anonymization_key = network_anonymization_key2;
    auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
                                                           session.get());
    rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
    EXPECT_THAT(callback.GetResult(rv), IsOk());
    std::string response_data2;
    EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
    EXPECT_EQ("2", response_data2);
    trans2.reset();

    HttpRequestInfo request3;
    request3.method = "GET";
    request3.url = GURL("http://foo.test/3");
    request3.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
    request3.network_isolation_key = network_isolation_key1;
    request3.network_anonymization_key = network_anonymization_key1;
    auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
                                                           session.get());
    rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
    EXPECT_THAT(callback.GetResult(rv), IsOk());
    std::string response_data3;
    EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
    EXPECT_EQ("3", response_data3);
    trans3.reset();
  }
}

TEST_P(HttpNetworkTransactionTest, NetworkIsolationH2) {
  const SchemefulSite kSite1(GURL("http://origin1/"));
  const SchemefulSite kSite2(GURL("http://origin2/"));
  const auto network_anonymization_key1 =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  const auto network_anonymization_key2 =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
  NetworkIsolationKey network_isolation_key2(kSite2, kSite2);

  // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
  // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
  // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
  // the same way as the HTTP over H2 proxy case.
  for (bool use_proxy : {false, true}) {
    SCOPED_TRACE(use_proxy);
    if (use_proxy) {
      session_deps_.proxy_resolution_service =
          ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
              "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
    } else {
      session_deps_.proxy_resolution_service =
          ConfiguredProxyResolutionService::CreateDirect();
    }
    const char* url1 = nullptr;
    const char* url2 = nullptr;
    const char* url3 = nullptr;
    if (use_proxy) {
      url1 = "http://foo.test/1";
      url2 = "http://foo.test/2";
      url3 = "http://foo.test/3";
    } else {
      url1 = "https://foo.test/1";
      url2 = "https://foo.test/2";
      url3 = "https://foo.test/3";
    }

    for (bool partition_connections : {false, true}) {
      SCOPED_TRACE(partition_connections);

      base::test::ScopedFeatureList feature_list;
      if (partition_connections) {
        feature_list.InitAndEnableFeature(
            features::kPartitionConnectionsByNetworkIsolationKey);
      } else {
        feature_list.InitAndDisableFeature(
            features::kPartitionConnectionsByNetworkIsolationKey);
      }

      std::unique_ptr<HttpNetworkSession> session(
          CreateSession(&session_deps_));

      // Reads and writes for the unpartitioned case, where only one socket is
      // used.

      SpdyTestUtil spdy_util(/*use_priority_header=*/true);
      spdy::SpdySerializedFrame unpartitioned_req1(
          spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
      spdy::SpdySerializedFrame unpartitioned_response1(
          spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          1));
      spdy::SpdySerializedFrame unpartitioned_body1(
          spdy_util.ConstructSpdyDataFrame(1, "1", true));
      spdy_util.UpdateWithStreamDestruction(1);

      spdy::SpdySerializedFrame unpartitioned_req2(
          spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
      spdy::SpdySerializedFrame unpartitioned_response2(
          spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          3));
      spdy::SpdySerializedFrame unpartitioned_body2(
          spdy_util.ConstructSpdyDataFrame(3, "2", true));
      spdy_util.UpdateWithStreamDestruction(3);

      spdy::SpdySerializedFrame unpartitioned_req3(
          spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
      spdy::SpdySerializedFrame unpartitioned_response3(
          spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                          5));
      spdy::SpdySerializedFrame unpartitioned_body3(
          spdy_util.ConstructSpdyDataFrame(5, "3", true));

      const MockWrite kUnpartitionedWrites[] = {
          CreateMockWrite(unpartitioned_req1, 0),
          CreateMockWrite(unpartitioned_req2, 3),
          CreateMockWrite(unpartitioned_req3, 6),
      };

      const MockRead kUnpartitionedReads[] = {
          CreateMockRead(unpartitioned_response1, 1),
          CreateMockRead(unpartitioned_body1, 2),
          CreateMockRead(unpartitioned_response2, 4),
          CreateMockRead(unpartitioned_body2, 5),
          CreateMockRead(unpartitioned_response3, 7),
          CreateMockRead(unpartitioned_body3, 8),
          MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
      };

      SequencedSocketData unpartitioned_data(kUnpartitionedReads,
                                             kUnpartitionedWrites);

      // Reads and writes for the partitioned case, where two sockets are used.

      SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
      spdy::SpdySerializedFrame partitioned_req1(
          spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
      spdy::SpdySerializedFrame partitioned_response1(
          spdy_util2.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                           1));
      spdy::SpdySerializedFrame partitioned_body1(
          spdy_util2.ConstructSpdyDataFrame(1, "1", true));
      spdy_util2.UpdateWithStreamDestruction(1);

      spdy::SpdySerializedFrame partitioned_req3(
          spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
      spdy::SpdySerializedFrame partitioned_response3(
          spdy_util2.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                           3));
      spdy::SpdySerializedFrame partitioned_body3(
          spdy_util2.ConstructSpdyDataFrame(3, "3", true));

      const MockWrite kPartitionedWrites1[] = {
          CreateMockWrite(partitioned_req1, 0),
          CreateMockWrite(partitioned_req3, 3),
      };

      const MockRead kPartitionedReads1[] = {
          CreateMockRead(partitioned_response1, 1),
          CreateMockRead(partitioned_body1, 2),
          CreateMockRead(partitioned_response3, 4),
          CreateMockRead(partitioned_body3, 5),
          MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
      };

      SpdyTestUtil spdy_util3(/*use_priority_header=*/true);
      spdy::SpdySerializedFrame partitioned_req2(
          spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
      spdy::SpdySerializedFrame partitioned_response2(
          spdy_util3.ConstructSpdyGetReply(base::span<const std::string_view>(),
                                           1));
      spdy::SpdySerializedFrame partitioned_body2(
          spdy_util3.ConstructSpdyDataFrame(1, "2", true));

      const MockWrite kPartitionedWrites2[] = {
          CreateMockWrite(partitioned_req2, 0),
      };

      const MockRead kPartitionedReads2[] = {
          CreateMockRead(partitioned_response2, 1),
          CreateMockRead(partitioned_body2, 2),
          MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
      };

      SequencedSocketData partitioned_data1(kPartitionedReads1,
                                            kPartitionedWrites1);
      SequencedSocketData partitioned_data2(kPartitionedReads2,
                                            kPartitionedWrites2);

      // No need to segment SSLDataProviders by whether or not partitioning is
      // enabled.
      SSLSocketDataProvider ssl_data1(ASYNC, OK);
      ssl_data1.next_proto = NextProto::kProtoHTTP2;
      SSLSocketDataProvider ssl_data2(ASYNC, OK);
      ssl_data2.next_proto = NextProto::kProtoHTTP2;

      if (partition_connections) {
        session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
        session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
        session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
        session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
      } else {
        session_deps_.socket_factory->AddSocketDataProvider(
            &unpartitioned_data);
        session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
      }

      TestCompletionCallback callback;
      HttpRequestInfo request1;
      request1.method = "GET";
      request1.url = GURL(url1);
      request1.traffic_annotation =
          MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
      request1.network_isolation_key = network_isolation_key1;
      request1.network_anonymization_key = network_anonymization_key1;

      auto trans1 =
          std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
      int rv =
          trans1->Start(&request1, callback.callback(), NetLogWithSource());
      EXPECT_THAT(callback.GetResult(rv), IsOk());
      std::string response_data1;
      EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
      EXPECT_EQ("1", response_data1);
      trans1.reset();

      HttpRequestInfo request2;
      request2.method = "GET";
      request2.url = GURL(url2);
      request2.traffic_annotation =
          MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
      request2.network_isolation_key = network_isolation_key2;
      request2.network_anonymization_key = network_anonymization_key2;
      auto trans2 =
          std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
      rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
      EXPECT_THAT(callback.GetResult(rv), IsOk());
      std::string response_data2;
      EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
      EXPECT_EQ("2", response_data2);
      trans2.reset();

      HttpRequestInfo request3;
      request3.method = "GET";
      request3.url = GURL(url3);
      request3.traffic_annotation =
          MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
      request3.network_isolation_key = network_isolation_key1;
      request3.network_anonymization_key = network_anonymization_key1;

      auto trans3 =
          std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
      rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
      EXPECT_THAT(callback.GetResult(rv), IsOk());
      std::string response_data3;
      EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
      EXPECT_EQ("3", response_data3);
      trans3.reset();
    }
  }
}

// Preconnect two sockets with different NetworkAnonymizationKeys when
// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then
// issue a request and make sure the correct socket is used. Loops three times,
// expecting to use the first preconnect, second preconnect, and neither.
TEST_P(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionConnectionsByNetworkIsolationKey);

  enum class TestCase {
    kUseFirstPreconnect,
    kUseSecondPreconnect,
    kDontUsePreconnect,
  };

  const SchemefulSite kSite1(GURL("http://origin1/"));
  const SchemefulSite kSite2(GURL("http://origin2/"));
  const SchemefulSite kSite3(GURL("http://origin3/"));
  auto preconnect1_anonymization_key =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  auto preconnect2_anonymization_key =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  auto not_preconnected_anonymization_key =
      NetworkAnonymizationKey::CreateSameSite(kSite3);
  NetworkIsolationKey preconnect1_isolation_key(kSite1, kSite1);
  NetworkIsolationKey preconnect2_isolation_key(kSite2, kSite2);
  NetworkIsolationKey not_preconnected_isolation_key(kSite3, kSite3);
  // Test that only preconnects with
  for (TestCase test_case :
       {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
        TestCase::kDontUsePreconnect}) {
    SpdySessionDependencies session_deps;
    // Make DNS lookups completely synchronously, so preconnects complete
    // immediately.
    session_deps.host_resolver->set_synchronous_mode(true);

    const MockWrite kMockWrites[] = {
        MockWrite(ASYNC, 0,
                  "GET / HTTP/1.1\r\n"
                  "Host: www.foo.com\r\n"
                  "Connection: keep-alive\r\n\r\n"),
    };

    const MockRead kMockReads[] = {
        MockRead(ASYNC, 1,
                 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
                 "hello"),
    };

    // Used for the socket that will actually be used, which may or may not be
    // one of the preconnects
    SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
                                         kMockReads, kMockWrites);

    // Used for the preconnects that won't actually be used.
    SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
                                         base::span<const MockRead>(),
                                         base::span<const MockWrite>());
    SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
                                         base::span<const MockRead>(),
                                         base::span<const MockWrite>());

    NetworkAnonymizationKey network_anonymization_key_for_request;
    NetworkIsolationKey network_isolation_key_for_request;

    switch (test_case) {
      case TestCase::kUseFirstPreconnect:
        session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
        session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
        network_isolation_key_for_request = preconnect1_isolation_key;
        network_anonymization_key_for_request = preconnect1_anonymization_key;
        break;
      case TestCase::kUseSecondPreconnect:
        session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
        session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
        network_isolation_key_for_request = preconnect2_isolation_key;
        network_anonymization_key_for_request = preconnect2_anonymization_key;
        break;
      case TestCase::kDontUsePreconnect:
        session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
        session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
        session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
        network_isolation_key_for_request = not_preconnected_isolation_key;
        network_anonymization_key_for_request =
            not_preconnected_anonymization_key;
        break;
    }

    std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));

    // Preconnect sockets.
    HttpRequestInfo request;
    request.method = "GET";
    request.url = GURL("http://www.foo.com/");
    request.traffic_annotation =
        MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

    request.network_isolation_key = preconnect1_isolation_key;
    request.network_anonymization_key = preconnect1_anonymization_key;
    session->http_stream_factory()->PreconnectStreams(1, request,
                                                      base::OnceClosure());

    request.network_isolation_key = preconnect2_isolation_key;
    request.network_anonymization_key = preconnect2_anonymization_key;
    session->http_stream_factory()->PreconnectStreams(1, request,
                                                      base::OnceClosure());

    request.network_isolation_key = network_isolation_key_for_request;
    request.network_anonymization_key = network_anonymization_key_for_request;

    // Run until idle to ensure that preconnects complete.
    RunUntilIdle();
    EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));

    // Make the request.
    TestCompletionCallback callback;

    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

    int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
    EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

    rv = callback.WaitForResult();
    EXPECT_THAT(rv, IsOk());

    const HttpResponseInfo* response = trans.GetResponseInfo();
    ASSERT_TRUE(response);
    ASSERT_TRUE(response->headers);
    EXPECT_EQ(200, response->headers->response_code());

    std::string response_data;
    rv = ReadTransaction(&trans, &response_data);
    EXPECT_THAT(rv, IsOk());
    EXPECT_EQ("hello", response_data);

    if (test_case != TestCase::kDontUsePreconnect) {
      EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
    } else {
      EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
    }
  }
}

// Test that the NetworkAnonymizationKey is passed down to SSLConfig so the
// session cache is isolated.
TEST_P(HttpNetworkTransactionTest, NetworkIsolationSSL) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionConnectionsByNetworkIsolationKey);

  const SchemefulSite kSite1(GURL("http://origin1/"));
  const SchemefulSite kSite2(GURL("http://origin2/"));
  const auto kNetworkAnonymizationKey1 =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
  const auto kNetworkAnonymizationKey2 =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // The server always sends Connection: close, so each request goes over a
  // distinct socket.

  const MockWrite kWrites1[] = {
      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n")};

  const MockRead kReads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: close\r\n"
               "Content-Length: 1\r\n\r\n"
               "1")};

  const MockWrite kWrites2[] = {
      MockWrite("GET /2 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n")};

  const MockRead kReads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: close\r\n"
               "Content-Length: 1\r\n\r\n"
               "2")};

  const MockWrite kWrites3[] = {
      MockWrite("GET /3 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n")};

  const MockRead kReads3[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: close\r\n"
               "Content-Length: 1\r\n\r\n"
               "3")};

  StaticSocketDataProvider data1(kReads1, kWrites1);
  StaticSocketDataProvider data2(kReads2, kWrites2);
  StaticSocketDataProvider data3(kReads3, kWrites3);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSocketDataProvider(&data3);

  SSLSocketDataProvider ssl_data1(ASYNC, OK);
  ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
  ssl_data1.expected_network_anonymization_key = kNetworkAnonymizationKey1;
  SSLSocketDataProvider ssl_data2(ASYNC, OK);
  ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
  ssl_data2.expected_network_anonymization_key = kNetworkAnonymizationKey2;
  SSLSocketDataProvider ssl_data3(ASYNC, OK);
  ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
  ssl_data3.expected_network_anonymization_key = kNetworkAnonymizationKey1;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);

  TestCompletionCallback callback;
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://foo.test/1");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request1.network_isolation_key = kNetworkIsolationKey1;
  request1.network_anonymization_key = kNetworkAnonymizationKey1;

  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data1;
  EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
  EXPECT_EQ("1", response_data1);
  trans1.reset();

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://foo.test/2");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request2.network_isolation_key = kNetworkIsolationKey2;
  request2.network_anonymization_key = kNetworkAnonymizationKey2;
  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data2;
  EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
  EXPECT_EQ("2", response_data2);
  trans2.reset();

  HttpRequestInfo request3;
  request3.method = "GET";
  request3.url = GURL("https://foo.test/3");
  request3.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request3.network_isolation_key = kNetworkIsolationKey1;
  request3.network_anonymization_key = kNetworkAnonymizationKey1;
  auto trans3 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data3;
  EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
  EXPECT_EQ("3", response_data3);
  trans3.reset();
}

// Test that the NetworkAnonymizationKey is passed down to SSLConfig so the
// session cache is isolated, for both origins and proxies.
TEST_P(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      features::kPartitionConnectionsByNetworkIsolationKey);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);

  const SchemefulSite kSite1(GURL("http://origin1/"));
  const SchemefulSite kSite2(GURL("http://origin2/"));
  const auto kNetworkAnonymizationKey1 =
      NetworkAnonymizationKey::CreateSameSite(kSite1);
  const auto kNetworkAnonymizationKey2 =
      NetworkAnonymizationKey::CreateSameSite(kSite2);
  const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
  const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Make both a tunneled and non-tunneled request.
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://foo.test/1");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request1.network_isolation_key = kNetworkIsolationKey1;
  request1.network_anonymization_key = kNetworkAnonymizationKey1;

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("http://foo.test/2");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
  request2.network_isolation_key = kNetworkIsolationKey2;
  request2.network_anonymization_key = kNetworkAnonymizationKey2;

  const MockWrite kWrites1[] = {MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
                                          "Host: foo.test:443\r\n"
                                          "Proxy-Connection: keep-alive\r\n"
                                          "User-Agent: test-ua\r\n\r\n"),
                                MockWrite("GET /1 HTTP/1.1\r\n"
                                          "Host: foo.test\r\n"
                                          "Connection: keep-alive\r\n\r\n")};

  const MockRead kReads1[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: close\r\n"
               "Content-Length: 1\r\n\r\n"
               "1")};

  const MockWrite kWrites2[] = {
      MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Proxy-Connection: keep-alive\r\n\r\n")};

  const MockRead kReads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: close\r\n"
               "Content-Length: 1\r\n\r\n"
               "2")};

  StaticSocketDataProvider data1(kReads1, kWrites1);
  StaticSocketDataProvider data2(kReads2, kWrites2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
  ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
  ssl_proxy1.expected_network_anonymization_key = kNetworkAnonymizationKey1;
  SSLSocketDataProvider ssl_origin1(ASYNC, OK);
  ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
  ssl_origin1.expected_network_anonymization_key = kNetworkAnonymizationKey1;
  SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
  ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
  ssl_proxy2.expected_network_anonymization_key = kNetworkAnonymizationKey2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);

  TestCompletionCallback callback;
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data1;
  EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
  EXPECT_EQ("1", response_data1);
  trans1.reset();

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data2;
  EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
  EXPECT_EQ("2", response_data2);
  trans2.reset();
}

// Test that SSLConfig changes from SSLConfigService are picked up even when
// there are live sockets.
TEST_P(HttpNetworkTransactionTest, SSLConfigChanged) {
  SSLContextConfig ssl_context_config;
  ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
  auto ssl_config_service =
      std::make_unique<TestSSLConfigService>(ssl_context_config);
  TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();

  session_deps_.ssl_config_service = std::move(ssl_config_service);

  // Make three requests. Between the second and third, the SSL config will
  // change.
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://foo.test/1");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://foo.test/2");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  HttpRequestInfo request3;
  request3.method = "GET";
  request3.url = GURL("https://foo.test/3");
  request3.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  const MockWrite kWrites1[] = {
      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
      MockWrite("GET /2 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  const MockRead kReads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 1\r\n\r\n"
               "1"),
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 1\r\n\r\n"
               "2"),
  };

  // The third request goes on a different socket because the SSL config has
  // changed.
  const MockWrite kWrites2[] = {
      MockWrite("GET /3 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n")};

  const MockRead kReads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 1\r\n\r\n"
               "3")};

  StaticSocketDataProvider data1(kReads1, kWrites1);
  StaticSocketDataProvider data2(kReads2, kWrites2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
  SSLSocketDataProvider ssl2(ASYNC, OK);
  ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  TestCompletionCallback callback;
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data1;
  EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
  EXPECT_EQ("1", response_data1);
  trans1.reset();

  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data2;
  EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
  EXPECT_EQ("2", response_data2);
  trans2.reset();

  ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
  ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);

  auto trans3 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data3;
  EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
  EXPECT_EQ("3", response_data3);
  trans3.reset();
}

TEST_P(HttpNetworkTransactionTest, SSLConfigChangedDuringTransaction) {
  SSLContextConfig ssl_context_config;
  ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
  auto ssl_config_service =
      std::make_unique<TestSSLConfigService>(ssl_context_config);
  TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
  session_deps_.ssl_config_service = std::move(ssl_config_service);

  // First request will start connecting before SSLConfig change.
  HttpRequestInfo request1;
  request1.method = "GET";
  request1.url = GURL("https://foo.test/1");
  request1.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  const MockWrite kWrites1[] = {
      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kReads1[] = {
      MockRead(ASYNC, ERR_IO_PENDING, 1),
      MockRead(ASYNC, 2,
               "HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 1\r\n\r\n"
               "1"),
  };

  // Second request will be after SSLConfig changes so it should be on a new
  // socket.
  HttpRequestInfo request2;
  request2.method = "GET";
  request2.url = GURL("https://foo.test/2");
  request2.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  const MockWrite kWrites2[] = {
      MockWrite("GET /2 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n")};

  const MockRead kReads2[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 1\r\n\r\n"
               "2")};

  SequencedSocketData data1(kReads1, kWrites1);
  StaticSocketDataProvider data2(kReads2, kWrites2);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  // 1st request starts before config change, so should see the initial
  // SSLConfig.
  ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;

  SSLSocketDataProvider ssl2(ASYNC, OK);
  // 2nd request should be made on a new socket after config change, so should
  // see the new SSLConfig.
  ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;

  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  TestCompletionCallback callback1;
  auto trans1 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans1->Start(&request1, callback1.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Wait for the first transaction to connect and start reading data.
  data1.RunUntilPaused();

  // Change network config.
  ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
  ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);

  // Resume the first transaction reads.
  data1.Resume();
  EXPECT_THAT(callback1.GetResult(rv), IsOk());
  std::string response_data1;
  EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
  EXPECT_EQ("1", response_data1);
  trans1.reset();

  // Start 2nd transaction. Since the config was changed, it should use a new
  // socket.
  TestCompletionCallback callback2;
  auto trans2 =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans2->Start(&request2, callback2.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback2.GetResult(rv), IsOk());
  std::string response_data2;
  EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
  EXPECT_EQ("2", response_data2);
  trans2.reset();
}

TEST_P(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
  SSLContextConfig ssl_context_config;
  ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
  auto ssl_config_service =
      std::make_unique<TestSSLConfigService>(ssl_context_config);
  TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();

  session_deps_.ssl_config_service = std::move(ssl_config_service);

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://foo.test/1");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  const MockWrite kWrites1[] = {
      MockWrite("GET /1 HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kReads1[] = {
      MockRead("HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 1\r\n\r\n"
               "1"),
  };

  StaticSocketDataProvider data1(kReads1, kWrites1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  // Even though the transaction was created before the change, the connection
  // shouldn't happen until after the SSLConfig change, so expect that the
  // socket will be created with the new SSLConfig.
  SSLSocketDataProvider ssl_data(ASYNC, OK);
  ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  TestCompletionCallback callback;
  auto trans =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
  ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);

  EXPECT_THAT(callback.GetResult(rv), IsOk());
  std::string response_data;
  EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
  EXPECT_EQ("1", response_data);
  trans.reset();
}

// Test that HttpNetworkTransaction correctly handles existing sockets when the
// server requests a client certificate post-handshake (via a TLS
// renegotiation). This is a regression test for https://crbug.com/829184.
TEST_P(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
  const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
      TRAFFIC_ANNOTATION_FOR_TESTS);

  auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
  cert_request_info->host_and_port = HostPortPair("foo.test", 443);

  std::unique_ptr<FakeClientCertIdentity> identity =
      FakeClientCertIdentity::CreateFromCertAndKeyFiles(
          GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
  ASSERT_TRUE(identity);

  // This test will make several requests so that, when the client certificate
  // request comes in, we have a socket in use, an idle socket, and a socket for
  // an unrelated host.
  //
  // First, two long-lived requests which do not complete until after the client
  // certificate request. This arranges for sockets to be in use during the
  // request. They should not be interrupted.
  HttpRequestInfo request_long_lived;
  request_long_lived.method = "GET";
  request_long_lived.url = GURL("https://foo.test/long-lived");
  request_long_lived.traffic_annotation = kTrafficAnnotation;

  HttpRequestInfo request_long_lived_bar;
  request_long_lived_bar.method = "GET";
  request_long_lived_bar.url = GURL("https://bar.test/long-lived");
  request_long_lived_bar.traffic_annotation = kTrafficAnnotation;

  // Next, make a request that needs client certificates.
  HttpRequestInfo request_auth;
  request_auth.method = "GET";
  request_auth.url = GURL("https://foo.test/auth");
  request_auth.traffic_annotation = kTrafficAnnotation;

  // Before responding to the challenge, make a request to an unauthenticated
  // endpoint. This will result in an idle socket when the client certificate
  // challenge is resolved.
  HttpRequestInfo request_unauth;
  request_unauth.method = "GET";
  request_unauth.url = GURL("https://foo.test/unauth");
  request_unauth.traffic_annotation = kTrafficAnnotation;

  // After all the preceding requests complete, end with two additional requests
  // to ensure pre-authentication foo.test sockets are not used and bar.test
  // sockets are unaffected.
  HttpRequestInfo request_post_auth;
  request_post_auth.method = "GET";
  request_post_auth.url = GURL("https://foo.test/post-auth");
  request_post_auth.traffic_annotation = kTrafficAnnotation;

  HttpRequestInfo request_post_auth_bar;
  request_post_auth_bar.method = "GET";
  request_post_auth_bar.url = GURL("https://bar.test/post-auth");
  request_post_auth_bar.traffic_annotation = kTrafficAnnotation;

  // The sockets for /long-lived and /unauth complete their request but are
  // not allocated for /post-auth or /retry because SSL state has since changed.
  const MockWrite kLongLivedWrites[] = {
      MockWrite(ASYNC, 0,
                "GET /long-lived HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kLongLivedReads[] = {
      // Pause so /long-lived completes after the client presents client
      // certificates.
      MockRead(ASYNC, ERR_IO_PENDING, 1),
      MockRead(ASYNC, 2,
               "HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 10\r\n\r\n"
               "long-lived"),
  };
  SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
  SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
  session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);

  // Requests for bar.test should be unaffected by foo.test and get allocated
  // a single socket.
  const MockWrite kBarWrites[] = {
      MockWrite(ASYNC, 0,
                "GET /long-lived HTTP/1.1\r\n"
                "Host: bar.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
      MockWrite(ASYNC, 3,
                "GET /post-auth HTTP/1.1\r\n"
                "Host: bar.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kBarReads[] = {
      // Pause on /long-lived so it completes after foo.test's authentication.
      MockRead(ASYNC, ERR_IO_PENDING, 1),
      MockRead(ASYNC, 2,
               "HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 10\r\n\r\n"
               "long-lived"),
      MockRead(ASYNC, 4,
               "HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 9\r\n\r\n"
               "post-auth"),
  };
  SequencedSocketData data_bar(kBarReads, kBarWrites);
  SSLSocketDataProvider ssl_bar(ASYNC, OK);
  session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);

  // Requesting /auth results in a post-handshake client certificate challenge.
  const MockWrite kAuthWrites[] = {
      MockWrite(ASYNC, 0,
                "GET /auth HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kAuthReads[] = {
      MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
  };
  SequencedSocketData data_auth(kAuthReads, kAuthWrites);
  SSLSocketDataProvider ssl_auth(ASYNC, OK);
  ssl_auth.cert_request_info = cert_request_info;
  session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);

  // Requesting /unauth completes.
  const MockWrite kUnauthWrites[] = {
      MockWrite(ASYNC, 0,
                "GET /unauth HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kUnauthReads[] = {
      MockRead(ASYNC, 1,
               "HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 6\r\n\r\n"
               "unauth"),
  };
  SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
  SSLSocketDataProvider ssl_unauth(ASYNC, OK);
  session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);

  // When the client certificate is selected, /auth is retried on a new
  // connection. In particular, it should not be retried on |data_unauth|,
  // which would not honor the new client certificate configuration.
  const MockWrite kRetryWrites[] = {
      MockWrite(ASYNC, 0,
                "GET /auth HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kRetryReads[] = {
      MockRead(ASYNC, 1,
               "HTTP/1.1 200 OK\r\n"
               // Close the connection so we test that /post-auth is not
               // allocated to |data_unauth| or |data_long_lived|.
               "Connection: close\r\n"
               "Content-Length: 4\r\n\r\n"
               "auth"),
  };
  SequencedSocketData data_retry(kRetryReads, kRetryWrites);
  SSLSocketDataProvider ssl_retry(ASYNC, OK);
  ssl_retry.expected_send_client_cert = true;
  ssl_retry.expected_client_cert = identity->certificate();
  session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);

  // /post-auth gets its own socket.
  const MockWrite kPostAuthWrites[] = {
      MockWrite(ASYNC, 0,
                "GET /post-auth HTTP/1.1\r\n"
                "Host: foo.test\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };
  const MockRead kPostAuthReads[] = {
      MockRead(ASYNC, 1,
               "HTTP/1.1 200 OK\r\n"
               "Connection: keep-alive\r\n"
               "Content-Length: 9\r\n\r\n"
               "post-auth"),
  };
  SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
  SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
  ssl_post_auth.expected_send_client_cert = true;
  ssl_post_auth.expected_client_cert = identity->certificate();
  session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);

  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);

  // Start the two long-lived requests.
  TestCompletionCallback callback_long_lived;
  auto trans_long_lived =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  int rv = trans_long_lived->Start(
      &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
  ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
  data_long_lived.RunUntilPaused();

  TestCompletionCallback callback_long_lived_bar;
  auto trans_long_lived_bar =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans_long_lived_bar->Start(&request_long_lived_bar,
                                   callback_long_lived_bar.callback(),
                                   NetLogWithSource());
  ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
  data_bar.RunUntilPaused();

  // Request /auth. This gives a client certificate challenge.
  TestCompletionCallback callback_auth;
  auto trans_auth =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans_auth->Start(&request_auth, callback_auth.callback(),
                         NetLogWithSource());
  EXPECT_THAT(callback_auth.GetResult(rv),
              IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));

  // Make an unauthenticated request. This completes.
  TestCompletionCallback callback_unauth;
  auto trans_unauth =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
                           NetLogWithSource());
  EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
  std::string response_unauth;
  EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
  EXPECT_EQ("unauth", response_unauth);
  trans_unauth.reset();

  // Complete the authenticated request.
  rv = trans_auth->RestartWithCertificate(identity->certificate(),
                                          identity->ssl_private_key(),
                                          callback_auth.callback());
  EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
  std::string response_auth;
  EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
  EXPECT_EQ("auth", response_auth);
  trans_auth.reset();

  // Complete the long-lived requests.
  data_long_lived.Resume();
  EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
  std::string response_long_lived;
  EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
              IsOk());
  EXPECT_EQ("long-lived", response_long_lived);
  trans_long_lived.reset();

  data_bar.Resume();
  EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
  std::string response_long_lived_bar;
  EXPECT_THAT(
      ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
      IsOk());
  EXPECT_EQ("long-lived", response_long_lived_bar);
  trans_long_lived_bar.reset();

  // Run the post-authentication requests.
  TestCompletionCallback callback_post_auth;
  auto trans_post_auth =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
                              NetLogWithSource());
  EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
  std::string response_post_auth;
  EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
              IsOk());
  EXPECT_EQ("post-auth", response_post_auth);
  trans_post_auth.reset();

  TestCompletionCallback callback_post_auth_bar;
  auto trans_post_auth_bar =
      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
  rv = trans_post_auth_bar->Start(&request_post_auth_bar,
                                  callback_post_auth_bar.callback(),
                                  NetLogWithSource());
  EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
  std::string response_post_auth_bar;
  EXPECT_THAT(
      ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
      IsOk());
  EXPECT_EQ("post-auth", response_post_auth_bar);
  trans_post_auth_bar.reset();
}

TEST_P(HttpNetworkTransactionTest, RequestWithDnsAliases) {
  // Create a request.
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Add a rule with DNS aliases to the host resolver.
  std::vector<std::string> aliases({"alias1", "alias2", "www.example.org"});
  session_deps_.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
      "www.example.org", "127.0.0.1", std::move(aliases));

  // Create a HttpNetworkSession.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Create a transaction.
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Prepare the expected data to be written and read. The client should send
  // the request below.
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  // The server should respond with the following.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  TestCompletionCallback callback;

  // Start the transaction.
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Wait for completion.
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  // Get the response info.
  const HttpResponseInfo* response = trans.GetResponseInfo();

  // Verify that the alias list was stored in the response info as expected.
  ASSERT_TRUE(response);
  EXPECT_THAT(response->dns_aliases,
              testing::ElementsAre("alias1", "alias2", "www.example.org"));
}

TEST_P(HttpNetworkTransactionTest, RequestWithNoAdditionalDnsAliases) {
  // Create a request.
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("http://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  // Add a rule without DNS aliases to the host resolver.
  session_deps_.host_resolver->rules()->AddRule("www.example.org", "127.0.0.1");

  // Create a HttpNetworkSession.
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  // Create a transaction.
  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  // Prepare the expected data to be written and read. The client should send
  // the request below.
  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  // The server should respond with the following.
  MockRead data_reads[] = {
      MockRead("HTTP/1.0 200 OK\r\n"),
      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
      MockRead("Content-Length: 100\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);
  TestCompletionCallback callback;

  // Start the transaction.
  int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  // Wait for completion.
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  // Get the response info.
  const HttpResponseInfo* response = trans.GetResponseInfo();

  // Verify that the alias list was stored in the response info as expected.
  ASSERT_TRUE(response);
  EXPECT_THAT(response->dns_aliases, testing::ElementsAre("www.example.org"));
}

// Test behavior of SetProxyInfoInResponse with a direct connection.
TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_Direct) {
  ProxyInfo proxy_info;
  proxy_info.UseDirect();
  HttpResponseInfo response_info;
  HttpNetworkTransaction::SetProxyInfoInResponse(proxy_info, &response_info);
  EXPECT_EQ(response_info.WasFetchedViaProxy(), false);
  EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), false);
  EXPECT_EQ(response_info.proxy_chain, ProxyChain::Direct());
}

// Test behavior of SetProxyInfoInResponse with a proxied connection.
TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_Proxied) {
  ProxyInfo proxy_info;
  ProxyChain proxy_chain =
      ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTPS, "prx", 443);
  proxy_info.UseProxyChain(proxy_chain);
  HttpResponseInfo response_info;
  HttpNetworkTransaction::SetProxyInfoInResponse(proxy_info, &response_info);
  EXPECT_EQ(response_info.WasFetchedViaProxy(), true);
  EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), false);
  EXPECT_EQ(response_info.proxy_chain, proxy_chain);
}

// Test behavior of SetProxyInfoInResponse with an empty ProxyInfo.
TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_Empty) {
  ProxyInfo empty_proxy_info;
  HttpResponseInfo response_info;
  HttpNetworkTransaction::SetProxyInfoInResponse(empty_proxy_info,
                                                 &response_info);
  EXPECT_EQ(response_info.WasFetchedViaProxy(), false);
  EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), false);
  EXPECT_FALSE(response_info.proxy_chain.IsValid());
}

// Test behavior of SetProxyInfoInResponse with a proxied connection for IP
// protection.
TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_IpProtectionProxied) {
  ProxyInfo proxy_info;
  ProxyChain ip_protection_proxy_chain =
      ProxyChain::ForIpProtection({ProxyServer::FromSchemeHostAndPort(
          ProxyServer::SCHEME_HTTPS, "prx", 443)});
  proxy_info.UseProxyChain(ip_protection_proxy_chain);
  HttpResponseInfo response_info;
  HttpNetworkTransaction::SetProxyInfoInResponse(proxy_info, &response_info);
  EXPECT_EQ(response_info.WasFetchedViaProxy(), true);
  EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), true);
  EXPECT_EQ(response_info.proxy_chain, ip_protection_proxy_chain);
}

// Test behavior of SetProxyInfoInResponse with a direct connection for IP
// protection.
TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_IpProtectionDirect) {
  ProxyInfo proxy_info;
  const ProxyChain kIpProtectionDirectChain = ProxyChain::ForIpProtection({});
  proxy_info.UseProxyChain(kIpProtectionDirectChain);
  HttpResponseInfo response_info;
  HttpNetworkTransaction::SetProxyInfoInResponse(proxy_info, &response_info);
  EXPECT_EQ(response_info.WasFetchedViaProxy(), false);
  EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), true);
  EXPECT_EQ(response_info.proxy_chain, kIpProtectionDirectChain);
}

class IpProtectionProxyDelegate : public TestProxyDelegate {
 public:
  IpProtectionProxyDelegate() {
    set_extra_header_name(HttpRequestHeaders::kAuthorization);
  }

  // ProxyDelegate implementation:
  void OnResolveProxy(const GURL& url,
                      const NetworkAnonymizationKey& network_anonymization_key,
                      const std::string& method,
                      const ProxyRetryInfoMap& proxy_retry_info,
                      ProxyInfo* result) override {
    ProxyList proxy_list;
    proxy_list.AddProxyChain(proxy_chain());

    // For IP Protection we always want to fallback to direct, so emulate the
    // behavior of NetworkServiceProxyDelegate where a direct chain will always
    // be added as the last ProxyList entry.
    if (!proxy_chain().is_direct()) {
      proxy_list.AddProxyChain(ProxyChain::Direct());
    }

    result->UseProxyList(proxy_list);
  }

  static std::string GetAuthorizationHeaderValue(
      const ProxyServer& proxy_server) {
    return GetExtraHeaderValue(proxy_server);
  }
};

// Test that for requests sent through an IP Protection proxy, the
// 'IP-Protection' header is sent as expected when the feature is enabled.
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyIpProtectionRequestHeaderAddedWhenEnabled) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      features::kEnableIpProtectionProxy,
      {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"}});

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
  auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
      session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(nested_proxy_chain_);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  const std::string kProxyServer1AuthHeaderValue =
      IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_1_);
  const std::string kProxyServer2AuthHeaderValue =
      IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_2_);

  const std::string kProxyServer2Connect = base::StringPrintf(
      "CONNECT proxy2.test:71 HTTP/1.1\r\n"
      "Host: proxy2.test:71\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      "Authorization: %s\r\n\r\n",
      kProxyServer1AuthHeaderValue.c_str());
  const std::string kEndpointConnect = base::StringPrintf(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      "Authorization: %s\r\n\r\n",
      kProxyServer2AuthHeaderValue.c_str());

  MockWrite data_writes[] = {
      MockWrite(kProxyServer2Connect),
      MockWrite(kEndpointConnect),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n"
                "IP-Protection: 1\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead("HTTP/1.1 200\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

// Test that for direct requests that are marked as being for IP Protection, the
// 'IP-Protection' header is not sent even when the feature is enabled. This
// test should be removed once `kIpPrivacyDirectOnly` is.
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyIpProtectionRequestHeaderNotAddedForIpProtectionDirect) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      features::kEnableIpProtectionProxy,
      {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"},
       {features::kIpPrivacyDirectOnly.name, "true"}});

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  const auto kIpProtectionDirectChain =
      ProxyChain::ForIpProtection(std::vector<ProxyServer>());

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
  auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
      session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(kIpProtectionDirectChain);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

// Test that for requests sent through an IP Protection proxy, the
// 'IP-Protection' header is not sent if the feature is disabled.
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyIpProtectionRequestHeaderNotAddedIfFeatureDisabled) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      features::kEnableIpProtectionProxy,
      {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "false"}});

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
  auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
      session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(nested_proxy_chain_);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  const std::string kProxyServer1AuthHeaderValue =
      IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_1_);
  const std::string kProxyServer2AuthHeaderValue =
      IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_2_);

  const std::string kProxyServer2Connect = base::StringPrintf(
      "CONNECT proxy2.test:71 HTTP/1.1\r\n"
      "Host: proxy2.test:71\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      "Authorization: %s\r\n\r\n",
      kProxyServer1AuthHeaderValue.c_str());
  const std::string kEndpointConnect = base::StringPrintf(
      "CONNECT www.example.org:443 HTTP/1.1\r\n"
      "Host: www.example.org:443\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      "Authorization: %s\r\n\r\n",
      kProxyServer2AuthHeaderValue.c_str());

  MockWrite data_writes[] = {
      MockWrite(kProxyServer2Connect),
      MockWrite(kEndpointConnect),
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
      MockRead("HTTP/1.1 200\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&data);

  SSLSocketDataProvider ssl(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  SSLSocketDataProvider ssl3(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

// Test that for a request that fails to be sent through an IP Protection proxy,
// after we fallback to direct the 'IP-Protection' header is not added to the
// request headers.
TEST_P(HttpNetworkTransactionTest,
       HttpsNestedProxyIpProtectionRequestHeaderNotAddedAfterFallback) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      features::kEnableIpProtectionProxy,
      {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"}});
  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  session_deps_.proxy_resolution_service =
      ConfiguredProxyResolutionService::CreateFixedForTest(
          "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
  session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
  auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
      session_deps_.proxy_delegate.get());
  proxy_delegate->set_proxy_chain(nested_proxy_chain_);
  session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
  session_deps_.net_log = NetLog::Get();
  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  const std::string kProxyServer1AuthHeaderValue =
      IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_1_);

  const std::string kProxyServer2Connect = base::StringPrintf(
      "CONNECT proxy2.test:71 HTTP/1.1\r\n"
      "Host: proxy2.test:71\r\n"
      "Proxy-Connection: keep-alive\r\n"
      "User-Agent: test-ua\r\n"
      "Authorization: %s\r\n\r\n",
      kProxyServer1AuthHeaderValue.c_str());

  MockWrite data_writes1[] = {
      MockWrite(kProxyServer2Connect),
  };

  MockRead data_reads1[] = {
      MockRead("HTTP/1.1 401 Not Authorized\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data1(data_reads1, data_writes1);
  session_deps_.socket_factory->AddSocketDataProvider(&data1);

  SSLSocketDataProvider ssl1(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);

  // The proxy delegate should implement falling back to direct after an error,
  // and we don't expect any proxying or an IP Protection request header on the
  // GET.
  MockWrite data_writes2[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads2[] = {
      MockRead("HTTP/1.1 200\r\n\r\n"),
      MockRead(SYNCHRONOUS, OK),
  };

  StaticSocketDataProvider data2(data_reads2, data_writes2);
  session_deps_.socket_factory->AddSocketDataProvider(&data2);

  SSLSocketDataProvider ssl2(ASYNC, OK);
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);

  TestCompletionCallback callback;

  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());

  int rv = trans.Start(&request, callback.callback(),
                       NetLogWithSource::Make(NetLogSourceType::NONE));
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));

  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  const HttpResponseInfo* response = trans.GetResponseInfo();
  ASSERT_TRUE(response);
  ASSERT_TRUE(response->headers);
  EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
}

TEST_P(HttpNetworkTransactionTest, EarlyHintsWithAltSvcHeader) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitWithFeatures(
      // enabled features
      {features::kEnableEarlyHintsOnHttp11},  // Enable Early Hints on HTTP/1.1
      // disabled features
      {});

  // Enable QUIC
  session_deps_.enable_quic = true;
  session_deps_.enable_http2_alternative_service = true;

  MockWrite data_writes[] = {
      MockWrite("GET / HTTP/1.1\r\n"
                "Host: www.example.org\r\n"
                "Connection: keep-alive\r\n\r\n"),
  };

  MockRead data_reads[] = {
      MockRead("HTTP/1.1 103 Early Hints\r\n"
               "alt-svc: h3=\":443\"; ma=86400\r\n"
               "\r\n"),
      MockRead("HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html\r\n"
               "Content-Length: 5\r\n"
               "\r\n"
               "Hello"),
  };

  StaticSocketDataProvider reads(data_reads, data_writes);
  session_deps_.socket_factory->AddSocketDataProvider(&reads);

  SSLSocketDataProvider ssl(ASYNC, OK);
  // Add certificate to make SSL info valid
  scoped_refptr<X509Certificate> cert(
      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
  ASSERT_TRUE(cert);
  ssl.ssl_info.cert = cert;
  ssl.ssl_info.cert_status = 0;
  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);

  std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));

  HttpRequestInfo request;
  request.method = "GET";
  request.url = GURL("https://www.example.org/");
  request.traffic_annotation =
      net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);

  std::unique_ptr<HttpNetworkTransaction> trans(
      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));

  // Add early response headers callback to ensure 103 response is processed
  bool early_hints_received = false;
  trans->SetEarlyResponseHeadersCallback(base::BindLambdaForTesting(
      [&early_hints_received](
          scoped_refptr<const HttpResponseHeaders> headers) {
        EXPECT_EQ(103, headers->response_code());
        early_hints_received = true;
      }));

  TestCompletionCallback callback;
  int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
  rv = callback.WaitForResult();
  EXPECT_THAT(rv, IsOk());

  // Verify early hints were received
  EXPECT_TRUE(early_hints_received);

  // Verify final response
  const HttpResponseInfo* response = trans->GetResponseInfo();
  ASSERT_TRUE(response);
  EXPECT_EQ(200, response->headers->response_code());
  ASSERT_TRUE(response->ssl_info.is_valid());  // Verify SSL info is valid

  std::string response_data;
  rv = ReadTransaction(trans.get(), &response_data);
  EXPECT_THAT(rv, IsOk());
  EXPECT_EQ("Hello", response_data);

  // Verify Alt-Svc was processed
  HttpServerProperties* http_server_properties =
      session->http_server_properties();
  url::SchemeHostPort server(request.url);
  const AlternativeServiceInfoVector alternative_service_info_vector =
      http_server_properties->GetAlternativeServiceInfos(
          server, NetworkAnonymizationKey());

  ASSERT_EQ(1u, alternative_service_info_vector.size());
  EXPECT_EQ(NextProto::kProtoQUIC,
            alternative_service_info_vector[0].protocol());
  EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service().port);
  EXPECT_EQ("www.example.org",
            alternative_service_info_vector[0].alternative_service().host);
}

// If the proxy is not direct, we should see no additional capacity offered.
TEST_P(HttpNetworkTransactionTest, ProxyAdditionalCapacity) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      features::kTcpSocketPoolLimitRandomization,
      {
          {
              "TcpSocketPoolLimitRandomizationBase",
              "0.1",
          },
          {
              "TcpSocketPoolLimitRandomizationCapacity",
              "2",
          },
          {
              "TcpSocketPoolLimitRandomizationMinimum",
              "0.3",
          },
          {
              "TcpSocketPoolLimitRandomizationNoise",
              "0.4",
          },
      });
  std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
  EXPECT_EQ(session
                ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
                                ProxyChain::Direct())
                ->AdditionalCapacityForTest(),
            SocketPoolAdditionalCapacity::CreateForTest(0.1, 2, 0.3, 0.4));
  EXPECT_EQ(session
                ->GetSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
                                ProxyChain::Direct())
                ->AdditionalCapacityForTest(),
            SocketPoolAdditionalCapacity::CreateForTest(0.1, 2, 0.3, 0.4));
  EXPECT_EQ(session
                ->GetSocketPool(
                    HttpNetworkSession::NORMAL_SOCKET_POOL,
                    ProxyChain(ProxyServer::SCHEME_HTTPS,
                               SameProxyWithDifferentSchemesProxyResolver::
                                   ProxyHostPortPair()))
                ->AdditionalCapacityForTest(),
            SocketPoolAdditionalCapacity::CreateEmpty());
  EXPECT_EQ(session
                ->GetSocketPool(
                    HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
                    ProxyChain(ProxyServer::SCHEME_HTTPS,
                               SameProxyWithDifferentSchemesProxyResolver::
                                   ProxyHostPortPair()))
                ->AdditionalCapacityForTest(),
            SocketPoolAdditionalCapacity::CreateEmpty());
}

}  // namespace net
