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

#include "services/network/network_context.h"

#include <algorithm>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#include "base/barrier_closure.h"
#include "base/build_time.h"
#include "base/byte_size.h"
#include "base/callback_list.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/containers/extend.h"
#include "base/containers/flat_set.h"
#include "base/containers/to_vector.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/current_thread.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/types/optional_util.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "components/cookie_config/cookie_store_util.h"
#include "components/domain_reliability/monitor.h"
#include "components/enterprise/buildflags/buildflags.h"
#include "components/network_session_configurator/browser/network_session_configurator.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/os_crypt/async/common/encryptor.h"
#include "components/prefs/json_pref_store.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
#include "components/unexportable_keys/mojom/unexportable_key_service_proxied.h"
#include "components/url_matcher/url_matcher.h"
#include "components/url_matcher/url_util.h"
#include "components/url_pattern/simple_url_pattern_matcher.h"
#include "components/variations/net/variations_http_headers.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/features.h"
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/network_delegate.h"
#include "net/base/network_isolation_key.h"
#include "net/base/port_util.h"
#include "net/base/reconnect_notifier.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "net/cert/caching_cert_verifier.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/coalescing_cert_verifier.h"
#include "net/cert/x509_util.h"
#include "net/cookies/cookie_access_delegate.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/site_for_cookies.h"
#include "net/device_bound_sessions/session_service.h"
#include "net/disk_cache/buildflags.h"
#include "net/disk_cache/disk_cache.h"
#include "net/dns/context_host_resolver.h"
#include "net/dns/host_cache.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/extras/sqlite/cookie_crypto_delegate.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_auth_preferences.h"
#include "net/http/http_auth_scheme.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_transaction_factory.h"
#include "net/log/net_log_source_type.h"
#include "net/net_buildflags.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/proxy_resolution/proxy_config.h"
#include "net/shared_dictionary/shared_dictionary_isolation_key.h"
#include "net/ssl/ech_mode_getter.h"
#include "net/ssl/ssl_config_service.h"
#include "net/storage_access_api/status.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "services/network/brokered_client_socket_factory.h"
#include "services/network/connection_change_observer.h"
#include "services/network/cookie_manager.h"
#include "services/network/data_remover_util.h"
#include "services/network/device_bound_session_manager.h"
#include "services/network/disk_cache/mojo_backend_file_operations_factory.h"
#include "services/network/enterprise/encryption/encrypted_backend_file_operations_factory.h"
#include "services/network/enterprise/encryption/os_crypt_cache_encryption_delegate.h"
#include "services/network/host_resolver.h"
#include "services/network/http_auth_cache_proxy_copier.h"
#include "services/network/http_server_properties_pref_delegate.h"
#include "services/network/ignore_errors_cert_verifier.h"
#include "services/network/is_browser_initiated.h"
#include "services/network/known_legacy_scope_domains_delegate.h"
#include "services/network/logical_invalidation_store.h"
#include "services/network/net_log_exporter.h"
#include "services/network/network_service.h"
#include "services/network/network_service_network_delegate.h"
#include "services/network/network_service_proxy_delegate.h"
#include "services/network/oblivious_http_request_handler.h"
#include "services/network/pervasive_resources/shared_resource_checker.h"
#include "services/network/prefetch_cache.h"
#include "services/network/prefetch_matching_url_loader_factory.h"
#include "services/network/prefetch_url_loader_client.h"
#include "services/network/proxy_checking_host_resolver_request.h"
#include "services/network/proxy_config_service_mojo.h"
#include "services/network/proxy_lookup_request.h"
#include "services/network/proxy_resolving_socket_factory_mojo.h"
#include "services/network/public/cpp/cert_verifier/mojo_cert_verifier.h"
#include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/parsed_headers.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_host_resolver.h"
#include "services/network/public/mojom/clear_data_filter.mojom.h"
#include "services/network/public/mojom/connection_change_observer_client.mojom-forward.h"
#include "services/network/public/mojom/cookie_encryption_provider.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/reporting_service.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom-forward.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/web_transport.mojom.h"
#include "services/network/resolve_host_request.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
#include "services/network/restricted_cookie_manager.h"
#include "services/network/session_cleanup_cookie_store.h"
#include "services/network/shared_dictionary/shared_dictionary_constants.h"
#include "services/network/shared_dictionary/shared_dictionary_manager.h"
#include "services/network/shared_dictionary/shared_dictionary_storage.h"
#include "services/network/ssl_config_service_mojo.h"
#include "services/network/throttling/network_conditions.h"
#include "services/network/throttling/throttling_controller.h"
#include "services/network/throttling/throttling_network_transaction_factory.h"
#include "services/network/trust_tokens/expiry_inspecting_record_expiry_delegate.h"
#include "services/network/trust_tokens/in_memory_trust_token_persister.h"
#include "services/network/trust_tokens/pending_trust_token_store.h"
#include "services/network/trust_tokens/sqlite_trust_token_persister.h"
#include "services/network/trust_tokens/suitable_trust_token_origin.h"
#include "services/network/trust_tokens/trust_token_parameterization.h"
#include "services/network/trust_tokens/trust_token_query_answerer.h"
#include "services/network/trust_tokens/trust_token_store.h"
#include "services/network/url_loader.h"
#include "services/network/url_request_context_builder_mojo.h"
#include "services/network/web_transport.h"
#include "url/gurl.h"
#include "url/url_canon.h"
#include "url/url_constants.h"

#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
#include "services/network/device_bound_session_service_delegate.h"
#include "services/network/ssl_private_key_proxy.h"
#endif

#if BUILDFLAG(IS_CT_SUPPORTED)
// gn check does not account for BUILDFLAG(). So, for iOS builds, it will
// complain about a missing dependency on the target exposing this header. Add a
// nogncheck to stop it from yelling.
#include "components/certificate_transparency/chrome_require_ct_delegate.h"  // nogncheck
#include "services/network/sct_auditing/sct_auditing_cache.h"
#include "services/network/sct_auditing/sct_auditing_handler.h"
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

#if BUILDFLAG(ENABLE_WEBSOCKETS)
#include "services/network/websocket.h"
#include "services/network/websocket_factory.h"
#endif  // BUILDFLAG(ENABLE_WEBSOCKETS)

#if BUILDFLAG(ENABLE_REPORTING)
#include "net/base/http_user_agent_settings.h"
#include "net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.h"
#include "net/network_error_logging/network_error_logging_service.h"
#include "net/reporting/reporting_browsing_data_remover.h"
#include "net/reporting/reporting_policy.h"
#include "net/reporting/reporting_service.h"
#endif  // BUILDFLAG(ENABLE_REPORTING)

#if BUILDFLAG(ENABLE_MDNS)
#include "services/network/mdns_responder.h"
#endif  // BUILDFLAG(ENABLE_MDNS)

#if BUILDFLAG(IS_P2P_ENABLED)
#include "services/network/p2p/socket_manager.h"
#endif  // BUILDFLAG(IS_P2P_ENABLED)

#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)
#include "services/network/disk_cache/mojo_shared_http_cache_client_remote.h"
#endif  // BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)

#if BUILDFLAG(IS_ANDROID)
#include "base/android/application_status_listener.h"
#include "net/ssl/ech_mode_getter_android.h"
#endif  // BUILDFLAG(IS_ANDROID)

namespace network {

namespace {

net::CertVerifier* g_cert_verifier_for_testing = nullptr;

// A CertVerifier that forwards all requests to |g_cert_verifier_for_testing|.
// This is used to allow NetworkContexts to have their own
// std::unique_ptr<net::CertVerifier> while forwarding calls to the shared
// verifier.
class WrappedTestingCertVerifier : public net::CertVerifier {
 public:
  ~WrappedTestingCertVerifier() override = default;

  // CertVerifier implementation
  int Verify(const RequestParams& params,
             net::CertVerifyResult* verify_result,
             net::CompletionOnceCallback callback,
             std::unique_ptr<Request>* out_req,
             const net::NetLogWithSource& net_log) override {
    verify_result->Reset();
    if (!g_cert_verifier_for_testing) {
      return net::ERR_FAILED;
    }
    return g_cert_verifier_for_testing->Verify(
        params, verify_result, std::move(callback), out_req, net_log);
  }
  void Verify2QwacBinding(
      const std::string& binding,
      const std::string& hostname,
      const scoped_refptr<net::X509Certificate>& tls_cert,
      base::OnceCallback<void(const scoped_refptr<net::X509Certificate>&)>
          callback,
      const net::NetLogWithSource& net_log) override {
    if (!g_cert_verifier_for_testing) {
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback), nullptr));
      return;
    }
    g_cert_verifier_for_testing->Verify2QwacBinding(
        binding, hostname, tls_cert, std::move(callback), net_log);
  }
  void SetConfig(const Config& config) override {
    if (!g_cert_verifier_for_testing) {
      return;
    }
    g_cert_verifier_for_testing->SetConfig(config);
  }
  void AddObserver(Observer* observer) override {
    if (!g_cert_verifier_for_testing) {
      return;
    }
    g_cert_verifier_for_testing->AddObserver(observer);
  }
  void RemoveObserver(Observer* observer) override {
    if (!g_cert_verifier_for_testing) {
      return;
    }
    g_cert_verifier_for_testing->RemoveObserver(observer);
  }
};

// This implementation initializes an OSCryptAsync Encryptor instance and uses
// that.
class CookieOSCryptAsyncDelegate : public net::CookieCryptoDelegate {
 public:
  explicit CookieOSCryptAsyncDelegate(
      mojo::PendingRemote<network::mojom::CookieEncryptionProvider> provider);

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

  void Init(base::OnceClosure callback) override;
  bool EncryptString(const std::string& plaintext,
                     std::string* ciphertext) override;
  bool DecryptString(const std::string& ciphertext,
                     std::string* plaintext) override;

 private:
  void InitCallback(
      mojo::Remote<network::mojom::CookieEncryptionProvider> lifetime,
      scoped_refptr<os_crypt_async::Encryptor> encryptor);

  scoped_refptr<os_crypt_async::Encryptor> instance_;
  mojo::PendingRemote<network::mojom::CookieEncryptionProvider> provider_
      GUARDED_BY_CONTEXT(sequence_checker_);
  base::OnceClosureList callbacks_ GUARDED_BY_CONTEXT(sequence_checker_);
  bool is_initializing_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
  bool is_initialized_ GUARDED_BY_CONTEXT(sequence_checker_) = false;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<CookieOSCryptAsyncDelegate> weak_ptr_factory_{this};
};

CookieOSCryptAsyncDelegate::CookieOSCryptAsyncDelegate(
    mojo::PendingRemote<network::mojom::CookieEncryptionProvider> provider)
    : provider_(std::move(provider)) {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

bool CookieOSCryptAsyncDelegate::EncryptString(const std::string& plaintext,
                                               std::string* ciphertext) {
  return instance_->EncryptString(plaintext, ciphertext);
}

bool CookieOSCryptAsyncDelegate::DecryptString(const std::string& ciphertext,
                                               std::string* plaintext) {
  return instance_->DecryptString(ciphertext, plaintext);
}

void CookieOSCryptAsyncDelegate::InitCallback(
    mojo::Remote<network::mojom::CookieEncryptionProvider> lifetime,
    scoped_refptr<os_crypt_async::Encryptor> encryptor) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // The Encryptor is moved between sequences here. Verify that it's only moved
  // once.
  CHECK(!instance_);
  instance_ = std::move(encryptor);
  is_initialized_ = true;
  callbacks_.Notify();
}

void CookieOSCryptAsyncDelegate::Init(base::OnceClosure callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (is_initialized_) {
    std::move(callback).Run();
    return;
  }

  // AddUnsafe is safe here because it's always called with a callback that is
  // owned by a refcounted object. See SQLitePersistentCookieStore::Backend.
  callbacks_.AddUnsafe(std::move(callback));

  if (is_initializing_) {
    return;
  }

  is_initializing_ = true;
  mojo::Remote<network::mojom::CookieEncryptionProvider> remote(
      std::move(provider_));
  auto* raw_remote = remote.get();
  raw_remote->GetEncryptor(
      base::BindOnce(&CookieOSCryptAsyncDelegate::InitCallback,
                     weak_ptr_factory_.GetWeakPtr(), std::move(remote)));
}

// Predicate function to determine if the given |domain| matches the
// |filter_type| and |filter_domains| from a |mojom::ClearDataFilter|.
bool MatchesDomainFilter(mojom::ClearDataFilter_Type filter_type,
                         std::set<std::string> filter_domains,
                         const std::string& domain) {
  bool found_domain = filter_domains.find(domain) != filter_domains.end();
  return (filter_type == mojom::ClearDataFilter_Type::DELETE_MATCHES) ==
         found_domain;
}

// Returns a callback that checks if a domain matches the |filter|. |filter|
// must contain no origins. A null filter matches everything.
base::RepeatingCallback<bool(const std::string& host_name)> MakeDomainFilter(
    mojom::ClearDataFilter* filter) {
  if (!filter) {
    return base::BindRepeating([](const std::string&) { return true; });
  }

  DCHECK(filter->origins.empty())
      << "Origin filtering not allowed in a domain-only filter";

  std::set<std::string> filter_domains;
  filter_domains.insert(filter->domains.begin(), filter->domains.end());
  return base::BindRepeating(&MatchesDomainFilter, filter->type,
                             std::move(filter_domains));
}

// Predicate function to determine if the given |origin| matches the
// |filter_type|, |filter_domains| and |filter_origins| from a
// |mojom::ClearDataFilter|.
bool MatchesOriginFilter(mojom::ClearDataFilter_Type filter_type,
                         std::set<std::string> filter_domains,
                         std::set<url::Origin> filter_origins,
                         const url::Origin& origin) {
  std::string url_registrable_domain =
      net::registry_controlled_domains::GetDomainAndRegistry(
          origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
  bool found_domain =
      (filter_domains.find(url_registrable_domain != ""
                               ? url_registrable_domain
                               : origin.host()) != filter_domains.end());

  bool found_origin = (filter_origins.find(origin) != filter_origins.end());

  return (filter_type == mojom::ClearDataFilter_Type::DELETE_MATCHES) ==
         (found_domain || found_origin);
}

// Builds a generic Origin-matching predicate function based on |filter|. If
// |filter| is null, creates an always-true predicate.
base::RepeatingCallback<bool(const url::Origin&)> BuildOriginFilter(
    mojom::ClearDataFilterPtr filter) {
  if (!filter) {
    return base::BindRepeating([](const url::Origin&) { return true; });
  }

  std::set<std::string> filter_domains;
  filter_domains.insert(filter->domains.begin(), filter->domains.end());

  std::set<url::Origin> filter_origins;
  filter_origins.insert(filter->origins.begin(), filter->origins.end());

  return base::BindRepeating(&MatchesOriginFilter, filter->type,
                             std::move(filter_domains),
                             std::move(filter_origins));
}

// Builds a generic URL-matching predicate function based on |filter|.
// If |filter| is null, creates an always-true predicate.
base::RepeatingCallback<bool(const GURL&)> BuildUrlFilter(
    mojom::ClearDataFilterPtr filter) {
  return filter ? BindDoesUrlMatchFilter(filter->type, filter->origins,
                                         filter->domains)
                : base::NullCallback();
}

#if BUILDFLAG(IS_ANDROID)
class NetworkContextApplicationStatusListener
    : public base::android::ApplicationStatusListener {
 public:
  // Sets `get_callback` to be a callback that returns nullptr if the created
  // NetworkContextApplicationStatusListener has been destroyed, and the
  // listener itself, otherwise. It's a constructor argument to avoid needing
  // a cast, moving this into the header, or other complexities around
  // `app_status_listeners_` being a vector of the parent class.
  explicit NetworkContextApplicationStatusListener(
      disk_cache::ApplicationStatusListenerGetter& get_callback) {
    get_callback =
        base::BindRepeating(&NetworkContextApplicationStatusListener::
                                ReturnAppStatusListenerIfAlive,
                            weak_ptr_factory_.GetWeakPtr());
  }

  // base::android::ApplicationStatusListener implementation:
  void SetCallback(const ApplicationStateChangeCallback& callback) override {
    DCHECK(!callback_);
    DCHECK(callback);
    callback_ = callback;
  }

  void Notify(base::android::ApplicationState state) override {
    if (callback_) {
      callback_.Run(state);
    }
  }

 private:
  static base::android::ApplicationStatusListener*
  ReturnAppStatusListenerIfAlive(
      base::WeakPtr<base::android::ApplicationStatusListener> listener) {
    return listener.get();
  }

  ApplicationStateChangeCallback callback_;
  base::WeakPtrFactory<base::android::ApplicationStatusListener>
      weak_ptr_factory_{this};
};

#endif  // BUILDFLAG(IS_ANDROID)

struct TestVerifyCertState {
  net::CertVerifyResult result;
  std::unique_ptr<net::CertVerifier::Request> request;
};

void TestVerifyCertCallback(
    std::unique_ptr<TestVerifyCertState> request,
    NetworkContext::VerifyCertificateForTestingCallback callback,
    int result) {
  std::move(callback).Run(result);
}

#if BUILDFLAG(IS_CT_SUPPORTED)
// SCTAuditingDelegate is an implementation of the delegate interface that is
// aware of per-NetworkContext details (to allow the cache to notify the
// associated NetworkContextClient of new reports, and to apply
// per-NetworkContext enabled/disabled status for the auditing feature).
class SCTAuditingDelegate : public net::SCTAuditingDelegate {
 public:
  explicit SCTAuditingDelegate(const base::WeakPtr<NetworkContext>& context);
  ~SCTAuditingDelegate() override;

  // net::SCTAuditingDelegate:
  void MaybeEnqueueReport(
      const net::HostPortPair& host_port_pair,
      const net::X509Certificate* validated_certificate_chain,
      const net::SignedCertificateTimestampAndStatusList&
          signed_certificate_timestamps) override;

 private:
  base::WeakPtr<NetworkContext> context_;
};

SCTAuditingDelegate::SCTAuditingDelegate(
    const base::WeakPtr<NetworkContext>& context)
    : context_(context) {}

SCTAuditingDelegate::~SCTAuditingDelegate() = default;

void SCTAuditingDelegate::MaybeEnqueueReport(
    const net::HostPortPair& host_port_pair,
    const net::X509Certificate* validated_certificate_chain,
    const net::SignedCertificateTimestampAndStatusList&
        signed_certificate_timestamps) {
  if (!context_) {
    return;
  }
  context_->MaybeEnqueueSCTReport(host_port_pair, validated_certificate_chain,
                                  signed_certificate_timestamps);
}
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

// Obtains a full data file path from a NetworkContextFilePaths, a class member
// pointer to the data file. If valid, then returns true and places the full
// path into `full_path` otherwise returns false.
bool GetFullDataFilePath(
    const mojom::NetworkContextFilePathsPtr& file_paths,
    std::optional<base::FilePath> network::mojom::NetworkContextFilePaths::*
        field_name,
    base::FilePath& full_path) {
  if (!file_paths) {
    return false;
  }

  std::optional<base::FilePath> relative_file_path =
      file_paths.get()->*field_name;
  if (!relative_file_path.has_value()) {
    return false;
  }

  // Path to a data file should always be a plain filename.
  DCHECK_EQ(relative_file_path->BaseName(), *relative_file_path);

  full_path =
      file_paths->data_directory.path().Append(relative_file_path->value());
  return true;
}

// Produces URLLoaderFactoryParams suitable for a prefetch. Generally this
// should match the params that are used for subresource fetches to render
// processes.
mojom::URLLoaderFactoryParamsPtr CreateURLLoaderFactoryParamsForPrefetch() {
  auto params = mojom::URLLoaderFactoryParams::New();
  params->process_id = OriginatingProcessId::browser();
  // We want to be able to use TrustedParams to set the IsolationInfo for each
  // prefetch separately, so make it trusted.
  // TODO(crbug.com/342445996): Maybe stop using TrustedParams and lock this
  // down?
  params->is_trusted = true;

  // This can be set to true by the content::switches::kDisableWebSecurity
  // switch, but that's not available in the network service. The consequences
  // of this being disabled should just be that prefetches fail where this flag
  // would have taken effect.
  // TODO(crbug.com/342445996): Pass this through from the caller.
  //
  // Android WebView also disables web security when the
  // `allow_universal_access_from_file_urls` flag is set, however, WebView
  // doesn't currently support prefetch anyway.
  params->disable_web_security = false;

  // TODO(crbug.com/342445996): Find out if we need to set anything here.
  params->client_security_state = mojom::ClientSecurityState::New();

  // TODO(crbug.com/342445996): params->coep_reporter

  // --disable-web-security also disables Opaque Response Blocking (ORB).
  params->is_orb_enabled = !params->disable_web_security;

  // TODO(crbug.com/342445996): trust_token_issuance_policy,
  // trust_token_redemption_policy

  // TODO(crbug.com/342445996): Add observers as needed for DevTools support,
  // etc.

  // TODO(crbug.com/342445996): params->cookie_setting_overrides

  params->debug_tag = "CreateURLLoaderFactoryParamsForPrefetch";

  // TODO(crbug.com/342445996): params->require_cross_site_requests_for_cookies

  return params;
}

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
//
// LINT.IfChange(HSTSRedirectUpgradeReason)
enum class HSTSRedirectUpgradeReason {
  kNotUpgradedNotHTTP = 0,
  kNotUpgradedHSTSUnavailable = 1,
  kNotUpgradedNoHSTSPin = 2,
  kUpgraded = 3,
  kMaxValue = kUpgraded,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:HSTSRedirectUpgradeReason)

void RecordHSTSPreconnectUpgradeReason(HSTSRedirectUpgradeReason reason) {
  if (!base::FeatureList::IsEnabled(
          net::features::kHstsTopLevelNavigationsOnly)) {
    base::UmaHistogramEnumeration("Net.PreconnectHSTSUpgradesUrl", reason);
  }
}

bool IsIncognitoFromParams(const mojom::NetworkContextParams& params) {
  // Checking both to see if there are any file paths at all, and if there is
  // specifically an http_cache_directory filepath in order to avoid a
  // potential nullptr dereference if we just checked that
  // `params_->file_paths->http_cache_directory' existed.
  return !params.file_paths || !params.file_paths->http_cache_directory;
}

void RemoveInvalidationFilterCallback(
    base::WeakPtr<NetworkContext> context,
    net::HttpCache::InvalidationFilter filter) {
  if (!context) {
    return;
  }
  net::HttpCache* cache =
      context->url_request_context()->http_transaction_factory()->GetCache();
  if (cache) {
    cache->RemoveInvalidationFilter(filter);
  }
  context->OnLogicalFilterRemoved(filter);
}

}  // namespace

constexpr uint32_t NetworkContext::kMaxOutstandingRequestsPerProcess;

NetworkContext::NetworkContextHttpAuthPreferences::
    NetworkContextHttpAuthPreferences(NetworkService* network_service)
    : network_service_(network_service) {}

NetworkContext::NetworkContextHttpAuthPreferences::
    ~NetworkContextHttpAuthPreferences() = default;

#if BUILDFLAG(IS_LINUX)
bool NetworkContext::NetworkContextHttpAuthPreferences::AllowGssapiLibraryLoad()
    const {
  if (network_service_) {
    network_service_->OnBeforeGssapiLibraryLoad();
  }
  return net::HttpAuthPreferences::AllowGssapiLibraryLoad();
}
#endif  // BUILDFLAG(IS_LINUX)

NetworkContext::NetworkRestriction::NetworkRestriction() = default;
NetworkContext::NetworkRestriction::NetworkRestriction(
    NetworkRestriction&& other) = default;
NetworkContext::NetworkRestriction&
NetworkContext::NetworkRestriction::operator=(NetworkRestriction&& other) =
    default;
NetworkContext::NetworkRestriction::~NetworkRestriction() = default;

NetworkContext::PendingCertVerify::PendingCertVerify() = default;
NetworkContext::PendingCertVerify::~PendingCertVerify() = default;

NetworkContext::NetworkContext(
    NetworkService* network_service,
    mojo::PendingReceiver<mojom::NetworkContext> receiver,
    mojom::NetworkContextParamsPtr params,
    OnConnectionCloseCallback on_connection_close_callback)
    : NetworkContext(base::PassKey<NetworkContext>(),
                     network_service,
                     std::move(receiver),
                     std::move(params),
                     std::move(on_connection_close_callback),
                     OnURLRequestContextBuilderConfiguredCallback()) {}

// net::NetworkDelegate that wraps
NetworkContext::NetworkContext(
    base::PassKey<NetworkContext> pass_key,
    NetworkService* network_service,
    mojo::PendingReceiver<mojom::NetworkContext> receiver,
    mojom::NetworkContextParamsPtr params,
    OnConnectionCloseCallback on_connection_close_callback,
    OnURLRequestContextBuilderConfiguredCallback
        on_url_request_context_builder_configured)
    : network_service_(network_service),
      url_request_context_(nullptr),
#if BUILDFLAG(ENABLE_REPORTING)
      is_observing_reporting_service_(false),
#endif  // BUILDFLAG(ENABLE_REPORTING)
      params_(std::move(params)),
      on_connection_close_callback_(std::move(on_connection_close_callback)),
      receiver_(std::in_place_type<Receiver>, this),
      cors_preflight_controller_(network_service),
      http_auth_merged_preferences_(network_service),
      ohttp_handler_(this),
      prefetch_enabled_(
          base::FeatureList::IsEnabled(features::kNetworkContextPrefetch) &&
          (params_->bound_network == net::handles::kInvalidNetworkHandle)),
      cors_non_wildcard_request_headers_support_(base::FeatureList::IsEnabled(
          features::kCorsNonWildcardRequestHeadersSupport)),
      prefetch_cache_(prefetch_enabled_ ? std::make_unique<PrefetchCache>()
                                        : nullptr),
      variations_headers_(std::move(params_->initial_variations_headers)) {
  TRACE_EVENT0("loading", "NetworkContext::NetworkContext");

  if (features::ShouldBindNetworkContextDirectReceiver()) {
    receiver_.emplace<DirectReceiver>(mojo::DirectReceiverKey{}, this);
  }
  std::visit(
      [&](auto& receiver_to_bind) {
        receiver_to_bind.Bind(std::move(receiver));
      },
      receiver_);
#if BUILDFLAG(IS_WIN) && DCHECK_IS_ON()
  if (params_->file_paths) {
    DCHECK(params_->win_permissions_set)
        << "Permissions not set on files. Network context should be created "
           "using CreateNetworkContextInNetworkService rather than directly on "
           "the network service.";
  }
#endif  // BUILDFLAG(IS_WIN) && DCHECK_IS_ON()

#if BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)
  if (params_->file_paths) {
    if (params_->file_paths->http_cache_directory) {
      EnsureMounted(&*params_->file_paths->http_cache_directory);
    }
    if (params_->file_paths->shared_dictionary_directory) {
      EnsureMounted(&*params_->file_paths->shared_dictionary_directory);
    }
    EnsureMounted(&params_->file_paths->data_directory);
  }
#endif  // BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)

  if (params_->shared_dictionary_enabled) {
    if (params_->file_paths &&
        params_->file_paths->shared_dictionary_directory &&
        !params_->file_paths->shared_dictionary_directory->path().empty()) {
#if BUILDFLAG(IS_ANDROID)
      disk_cache::ApplicationStatusListenerGetter get_callback;
      app_status_listeners_.push_back(
          std::make_unique<NetworkContextApplicationStatusListener>(
              get_callback));
#endif  // BUILDFLAG(IS_ANDROID)
      // TODO(crbug.com/40255884): Set `file_operations_factory` to support
      // sandboxed network service on Android.
      shared_dictionary_manager_ = SharedDictionaryManager::CreateOnDisk(
          params_->file_paths->shared_dictionary_directory->path().Append(
              FILE_PATH_LITERAL("db")),
          params_->file_paths->shared_dictionary_directory->path().Append(
              FILE_PATH_LITERAL("cache")),
          params_->shared_dictionary_cache_max_size,
          shared_dictionary::kDictionaryMaxCountPerNetworkContext,
#if BUILDFLAG(IS_ANDROID)
          std::move(get_callback),
#endif  // BUILDFLAG(IS_ANDROID)
          /*file_operations_factory=*/nullptr);
    } else {
      shared_dictionary_manager_ = SharedDictionaryManager::CreateInMemory(
          params_->shared_dictionary_cache_max_size,
          shared_dictionary::kDictionaryMaxCountPerNetworkContext);
    }
  }

  mojo::PendingRemote<mojom::URLLoaderFactory>
      url_loader_factory_for_cert_net_fetcher;
  mojo::PendingReceiver<mojom::URLLoaderFactory>
      url_loader_factory_for_cert_net_fetcher_receiver =
          url_loader_factory_for_cert_net_fetcher
              .InitWithNewPipeAndPassReceiver();

  scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store =
      MakeSessionCleanupCookieStore();

  url_request_context_owner_ = MakeURLRequestContext(
      std::move(url_loader_factory_for_cert_net_fetcher),
      session_cleanup_cookie_store,
      std::move(on_url_request_context_builder_configured),
      params_->bound_network);
  url_request_context_ = url_request_context_owner_.url_request_context.get();

  cookie_manager_ = std::make_unique<CookieManager>(
      url_request_context_, std::move(session_cleanup_cookie_store),
      std::move(params_->cookie_manager_params));

  cookie_manager_->AddSettingsWillChangeCallback(
      base::BindRepeating(&NetworkContext::OnCookieManagerSettingsChanged,
                          weak_factory_.GetWeakPtr()));

  shared_resource_checker_ = std::make_unique<SharedResourceChecker>(
      cookie_manager_->cookie_settings());

  network_service_->RegisterNetworkContext(this);

  // Only register for destruction if |this| will be wholly lifetime-managed
  // by the NetworkService. In the other constructors, lifetime is shared with
  // other consumers, and thus self-deletion is not safe and can result in
  // double-frees.
  std::visit(
      [&](auto& receiver) {
        receiver.set_disconnect_handler(base::BindOnce(
            &NetworkContext::OnConnectionError, base::Unretained(this)));
      },
      receiver_);

  socket_factory_ = std::make_unique<SocketFactory>(
      url_request_context_->net_log(), url_request_context_);
#if BUILDFLAG(IS_WIN)
  if (params_->socket_brokers) {
    socket_factory_->BindSocketBroker(
        std::move(params_->socket_brokers->server));
  }
#endif
  resource_scheduler_ = std::make_unique<ResourceScheduler>();

  if (params_->http_auth_static_network_context_params) {
    http_auth_merged_preferences_.SetAllowDefaultCredentials(
        params_->http_auth_static_network_context_params
            ->allow_default_credentials);
  }

  InitializeCorsParams();

#if BUILDFLAG(IS_CT_SUPPORTED)
  if (params_->ct_policy) {
    SetCTPolicy(std::move(params_->ct_policy));
  }

  base::FilePath sct_auditing_path;
  GetFullDataFilePath(params_->file_paths,
                      &network::mojom::NetworkContextFilePaths::
                          sct_auditing_pending_reports_file_name,
                      sct_auditing_path);
  sct_auditing_handler_ =
      std::make_unique<SCTAuditingHandler>(this, sct_auditing_path);
  sct_auditing_handler()->SetMode(params_->sct_auditing_mode);
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

#if BUILDFLAG(IS_ANDROID)
  if (params_->cookie_manager) {
    GetCookieManager(std::move(params_->cookie_manager));
  }
#endif  // BUILDFLAG(IS_ANDROID)

  CreateURLLoaderFactoryForCertNetFetcher(
      std::move(url_loader_factory_for_cert_net_fetcher_receiver));

  SetBlockTrustTokens(params_->block_trust_tokens);

  if (params_ && params_->http_cache_file_operations_factory) {
    http_cache_file_operations_factory_ =
        base::MakeRefCounted<MojoBackendFileOperationsFactory>(
            std::move(params_->http_cache_file_operations_factory));
  }

  if (prefetch_enabled_) {
    InitializePrefetchURLLoaderFactory();
  }

  device_bound_session_manager_ = DeviceBoundSessionManager::Create(
      url_request_context_->device_bound_session_service(),
      cookie_manager_.get());

  if (params_->file_paths &&
      params_->file_paths->logical_invalidation_directory) {
    base::TaskPriority priority =
        base::FeatureList::IsEnabled(net::features::kLogicalClearHttpCache) &&
                net::features::kLogicalClearHttpCacheUserVisiblePriority.Get()
            ? base::TaskPriority::USER_VISIBLE
            : base::TaskPriority::BEST_EFFORT;
    scoped_refptr<base::SequencedTaskRunner> file_task_runner =
        base::ThreadPool::CreateSequencedTaskRunner(
            {base::MayBlock(), priority,
             base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
    logical_invalidation_store_ = std::make_unique<LogicalInvalidationStore>(
        params_->file_paths->logical_invalidation_directory->path(),
        file_task_runner);
    // Start loading persisted invalidation filters asynchronously on startup.
    logical_invalidation_store_->Load(
        base::BindOnce(&NetworkContext::OnInvalidationFiltersLoaded,
                       weak_factory_.GetWeakPtr()));
  } else {
    initial_filters_loaded_ = true;
  }
}

NetworkContext::NetworkContext(
    NetworkService* network_service,
    mojo::PendingReceiver<mojom::NetworkContext> receiver,
    net::URLRequestContext* url_request_context,
    const std::vector<std::string>& cors_exempt_header_list)
    : network_service_(network_service),
      url_request_context_(url_request_context),
#if BUILDFLAG(ENABLE_REPORTING)
      is_observing_reporting_service_(false),
#endif  // BUILDFLAG(ENABLE_REPORTING)
      receiver_(std::in_place_type<Receiver>, this),
      cookie_manager_(std::make_unique<CookieManager>(
          url_request_context,
          nullptr,
          /*params=*/nullptr)),
      socket_factory_(
          std::make_unique<SocketFactory>(url_request_context_->net_log(),
                                          url_request_context)),
      cors_preflight_controller_(network_service),
      http_auth_merged_preferences_(network_service),
      ohttp_handler_(this),
      prefetch_enabled_(
          base::FeatureList::IsEnabled(features::kNetworkContextPrefetch) &&
          (url_request_context_->bound_network() ==
           net::handles::kInvalidNetworkHandle)),
      prefetch_cache_(prefetch_enabled_ ? std::make_unique<PrefetchCache>()
                                        : nullptr) {
  TRACE_EVENT0("loading", "NetworkContext::NetworkContext");

  if (features::ShouldBindNetworkContextDirectReceiver()) {
    receiver_.emplace<DirectReceiver>(mojo::DirectReceiverKey{}, this);
  }
  std::visit(
      [&](auto& receiver_to_bind) {
        receiver_to_bind.Bind(std::move(receiver));
      },
      receiver_);

  shared_resource_checker_ = std::make_unique<SharedResourceChecker>(
      cookie_manager_->cookie_settings());

  // May be nullptr in tests.
  if (network_service_) {
    network_service_->RegisterNetworkContext(this);
  }
  resource_scheduler_ = std::make_unique<ResourceScheduler>();

  for (const auto& key : cors_exempt_header_list) {
    cors_exempt_header_list_.insert(key);
  }

  if (prefetch_enabled_) {
    InitializePrefetchURLLoaderFactory();
  }
}

#if BUILDFLAG(ENABLE_WEBSOCKETS)
void NetworkContext::CreateNetLogEntriesForActiveWebSockets(
    net::NetLog::ThreadSafeObserver* observer) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (websocket_factory_) {
    websocket_factory_->CreateNetLogEntriesForActiveConnections(observer);
  }
}
#endif  // BUILDFLAG(ENABLE_WEBSOCKETS)

NetworkContext::~NetworkContext() {
  is_destructing_ = true;

  // Clear pending HttpCacheDataRemovers and counters explicitly to cancel
  // any in-flight background operations and avoid callback races.
  http_cache_data_removers_.clear();
  http_cache_data_counters_.clear();

  // May be nullptr in tests.
  if (network_service_) {
    network_service_->DeregisterNetworkContext(this);
  }

  if (domain_reliability_monitor_) {
    domain_reliability_monitor_->Shutdown();
  }
  // Because of the order of declaration in the class,
  // domain_reliability_monitor_ will be destroyed before
  // |url_loader_factories_| which could own URLLoader's whose destructor call
  // back into this class and might use domain_reliability_monitor_. So we reset
  // |domain_reliability_monitor_| here explicitly, instead of changing the
  // order, because any work calling into |domain_reliability_monitor_| at
  // shutdown would be unnecessary as the reports would be thrown out.
  domain_reliability_monitor_.reset();

  if (url_request_context_ &&
      url_request_context_->transport_security_state()) {
#if BUILDFLAG(IS_CT_SUPPORTED)
    if (require_ct_delegate_) {
      url_request_context_->transport_security_state()->SetRequireCTDelegate(
          nullptr);
    }
#endif  // BUILDFLAG(IS_CT_SUPPORTED)
  }

#if BUILDFLAG(ENABLE_REPORTING)
  if (is_observing_reporting_service_) {
    DCHECK(url_request_context());
    // May be nullptr in tests.
    if (url_request_context()->reporting_service()) {
      url_request_context()->reporting_service()->RemoveReportingCacheObserver(
          this);
    }
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)

#if BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)
  if (!dismount_closures_.empty()) {
    // Dismount all mounted directories after a generous delay, so that
    // pending asynchronous IO tasks have a chance to complete before the
    // directory is unmounted.
    constexpr base::TimeDelta kDismountDelay = base::Minutes(5);

    for (auto& dismount_closure : dismount_closures_) {
      std::ignore = base::ThreadPool::PostDelayedTask(
          FROM_HERE, std::move(dismount_closure), kDismountDelay);
    }
  }
#endif  // BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)

  // Clear `url_loader_factories_` before deleting the contents, as it can
  // result in re-entrant calls to DestroyURLLoaderFactory().
  std::set<std::unique_ptr<PrefetchMatchingURLLoaderFactory>,
           base::UniquePtrComparator>
      url_loader_factories = std::move(url_loader_factories_);
}

void NetworkContext::OnCookieManagerSettingsChanged() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  for (const std::unique_ptr<network::RestrictedCookieManager>& rcm :
       restricted_cookie_managers_) {
    rcm->OnCookieSettingsChanged();
  }
}

// static
std::unique_ptr<NetworkContext> NetworkContext::CreateForTesting(
    NetworkService* network_service,
    mojo::PendingReceiver<mojom::NetworkContext> receiver,
    mojom::NetworkContextParamsPtr params,
    OnURLRequestContextBuilderConfiguredCallback
        on_url_request_context_builder_configured) {
  return std::make_unique<NetworkContext>(
      base::PassKey<NetworkContext>(), network_service, std::move(receiver),
      std::move(params), OnConnectionCloseCallback(),
      std::move(on_url_request_context_builder_configured));
}

// static
void NetworkContext::SetCertVerifierForTesting(
    net::CertVerifier* cert_verifier) {
  g_cert_verifier_for_testing = cert_verifier;
}

void NetworkContext::CreateURLLoaderFactory(
    mojo::PendingReceiver<mojom::URLLoaderFactory> receiver,
    mojom::URLLoaderFactoryParamsPtr params,
    scoped_refptr<ResourceSchedulerClient> resource_scheduler_client) {
  url_loader_factories_.emplace(
      std::make_unique<PrefetchMatchingURLLoaderFactory>(
          this, std::move(params), std::move(resource_scheduler_client),
          std::move(receiver), &cors_origin_access_list_,
          prefetch_cache_.get()));
}

void NetworkContext::CreateURLLoaderFactoryForCertNetFetcher(
    mojo::PendingReceiver<mojom::URLLoaderFactory> factory_receiver) {
  // TODO(crbug.com/40695068): investigate changing these params.
  auto url_loader_factory_params = mojom::URLLoaderFactoryParams::New();
  url_loader_factory_params->is_trusted = true;
  url_loader_factory_params->process_id = OriginatingProcessId::browser();
  url_loader_factory_params->automatically_assign_isolation_info = true;
  url_loader_factory_params->is_orb_enabled = false;
  if (url_request_context()->bound_network() !=
      net::handles::kInvalidNetworkHandle) {
    // This is done to maintain consistency with network-bound
    // URLLoaderFactories used by multi-network CCT. See
    // CorsURLLoaderFactory::IsCorsPreflighLoadOptionAllowed
    // http://crrev.com/c/5899528.
    url_loader_factory_params->disable_web_security = true;
  }
  CreateURLLoaderFactory(std::move(factory_receiver),
                         std::move(url_loader_factory_params));
}

void NetworkContext::ActivateDohProbes() {
  DCHECK(url_request_context_->host_resolver());

  doh_probes_request_.reset();
  doh_probes_request_ =
      url_request_context_->host_resolver()->CreateDohProbeRequest();
  doh_probes_request_->Start();
}

void NetworkContext::SetClient(
    mojo::PendingRemote<mojom::NetworkContextClient> client) {
  client_.reset();
  client_.Bind(std::move(client));
}

void NetworkContext::CreateSocketFactory(
    mojo::PendingReceiver<mojom::SocketFactory> receiver) {
  socket_factory_receivers_.Add(socket_factory_.get(), std::move(receiver));
}

void NetworkContext::CreateURLLoaderFactory(
    mojo::PendingReceiver<mojom::URLLoaderFactory> receiver,
    mojom::URLLoaderFactoryParamsPtr params) {
  scoped_refptr<ResourceSchedulerClient> resource_scheduler_client =
      base::MakeRefCounted<ResourceSchedulerClient>(
          ResourceScheduler::ClientId::Create(),
          IsBrowserInitiated(params->process_id.is_browser()),
          resource_scheduler_.get(),
          url_request_context_->network_quality_estimator());
  CreateURLLoaderFactory(std::move(receiver), std::move(params),
                         std::move(resource_scheduler_client));
}

void NetworkContext::ResetURLLoaderFactories() {
  // Move all factories to a temporary vector so ClearBindings() does not
  // invalidate the iterator if the factory gets deleted.
  std::vector<PrefetchMatchingURLLoaderFactory*> factories;
  factories.reserve(url_loader_factories_.size());
  for (const auto& factory : url_loader_factories_) {
    if (!factory->ShouldIgnoreFactoryReset()) {
      factories.push_back(factory.get());
    }
  }
  for (auto* factory : factories) {
    factory->ClearBindings();
  }
}

void NetworkContext::GetViaObliviousHttp(
    mojom::ObliviousHttpRequestPtr request,
    mojo::PendingRemote<mojom::ObliviousHttpClient> client) {
  ohttp_handler_.StartRequest(std::move(request), std::move(client));
}

void NetworkContext::GetCookieManager(
    mojo::PendingReceiver<mojom::CookieManager> receiver) {
  cookie_manager_->AddReceiver(std::move(receiver));
}

void NetworkContext::OnRCMDisconnect(
    const network::RestrictedCookieManager* rcm) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = restricted_cookie_managers_.find(rcm);
  CHECK(it != restricted_cookie_managers_.end());
  restricted_cookie_managers_.erase(it);
}

void NetworkContext::RemoveConnectionChangeObserver(
    const net::ConnectionChangeNotifier::Observer* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto it = connection_change_observers_.find(observer);
  if (it != connection_change_observers_.end()) {
    connection_change_observers_.erase(it);
  }
}

void NetworkContext::GetRestrictedCookieManager(
    mojo::PendingReceiver<mojom::RestrictedCookieManager> receiver,
    mojom::RestrictedCookieManagerRole role,
    const url::Origin& origin,
    const net::IsolationInfo& isolation_info,
    const net::CookieSettingOverrides& cookie_setting_overrides,
    const net::CookieSettingOverrides& devtools_cookie_setting_overrides,
    bool prefer_bound_cookie_context,
    mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer) {
  std::unique_ptr<RestrictedCookieManager> ptr =
      std::make_unique<RestrictedCookieManager>(
          role, url_request_context_->cookie_store(),
          cookie_manager_->cookie_settings(), origin, isolation_info,
          cookie_setting_overrides, devtools_cookie_setting_overrides,
          prefer_bound_cookie_context, std::move(cookie_observer),
          network_service_->GetMetricsUpdater());

  auto callback = base::BindOnce(&NetworkContext::OnRCMDisconnect,
                                 base::Unretained(this), ptr.get());
  ptr->InstallReceiver(std::move(receiver), std::move(callback));
  restricted_cookie_managers_.insert(std::move(ptr));
}

void NetworkContext::GetTrustTokenQueryAnswerer(
    mojo::PendingReceiver<mojom::TrustTokenQueryAnswerer> receiver,
    const url::Origin& top_frame_origin) {
  // Only called when Trust Tokens is enabled, i.e. trust_token_store_ is
  // non-null.
  DCHECK(trust_token_store_);
  DCHECK(network_service_);

  std::optional<SuitableTrustTokenOrigin> suitable_top_frame_origin =
      SuitableTrustTokenOrigin::Create(top_frame_origin);

  const SynchronousTrustTokenKeyCommitmentGetter* const key_commitment_getter =
      network_service_->trust_token_key_commitments();

  // It's safe to dereference |suitable_top_frame_origin| here as, during the
  // process of vending the TrustTokenQueryAnswerer, the browser ensures that
  // the requesting context's top frame origin is suitable for Trust Tokens.
  auto answerer = std::make_unique<TrustTokenQueryAnswerer>(
      std::move(*suitable_top_frame_origin), trust_token_store_.get(),
      key_commitment_getter);

  trust_token_query_answerers_.Add(std::move(answerer), std::move(receiver));
}

void NetworkContext::GetStoredTrustTokenCounts(
    GetStoredTrustTokenCountsCallback callback) {
  if (trust_token_store_) {
    auto get_trust_token_counts_from_store =
        [](NetworkContext::GetStoredTrustTokenCountsCallback callback,
           TrustTokenStore* trust_token_store) {
          std::vector<mojom::StoredTrustTokensForIssuerPtr> result;
          for (auto& issuer_count_pair :
               trust_token_store->GetStoredTrustTokenCounts()) {
            result.push_back(mojom::StoredTrustTokensForIssuer::New(
                std::move(issuer_count_pair.first), issuer_count_pair.second));
          }
          std::move(callback).Run(std::move(result));
        };
    trust_token_store_->ExecuteOrEnqueue(
        base::BindOnce(get_trust_token_counts_from_store, std::move(callback)));
  } else {
    // The Trust Tokens feature is disabled, return immediately with an empty
    // vector.
    std::move(callback).Run({});
  }
}

void NetworkContext::GetPrivateStateTokenRedemptionRecords(
    GetPrivateStateTokenRedemptionRecordsCallback callback) {
  // The Trust Tokens feature is disabled, return immediately with an empty
  // map.
  if (!trust_token_store_) {
    base::flat_map<url::Origin, std::vector<mojom::ToplevelRedemptionRecordPtr>>
        empty_result;
    std::move(callback).Run(std::move(empty_result));
    return;
  }
  auto get_redemption_records_from_store =
      [](NetworkContext::GetPrivateStateTokenRedemptionRecordsCallback callback,
         TrustTokenStore* trust_token_store) {
        std::move(callback).Run(trust_token_store->GetRedemptionRecords());
      };
  trust_token_store_->ExecuteOrEnqueue(
      base::BindOnce(get_redemption_records_from_store, std::move(callback)));
}

void NetworkContext::DeleteStoredTrustTokens(
    const url::Origin& issuer,
    DeleteStoredTrustTokensCallback callback) {
  if (!trust_token_store_) {
    std::move(callback).Run(
        mojom::DeleteStoredTrustTokensStatus::kFailureFeatureDisabled);
    return;
  }

  std::optional<SuitableTrustTokenOrigin> suitable_issuer_origin =
      SuitableTrustTokenOrigin::Create(issuer);
  if (!suitable_issuer_origin) {
    std::move(callback).Run(
        mojom::DeleteStoredTrustTokensStatus::kFailureInvalidOrigin);
    return;
  }

  trust_token_store_->ExecuteOrEnqueue(base::BindOnce(
      [](SuitableTrustTokenOrigin issuer,
         DeleteStoredTrustTokensCallback callback, TrustTokenStore* store) {
        const bool did_delete_tokens = store->DeleteStoredTrustTokens(issuer);
        const auto status =
            did_delete_tokens
                ? mojom::DeleteStoredTrustTokensStatus::kSuccessTokensDeleted
                : mojom::DeleteStoredTrustTokensStatus::kSuccessNoTokensDeleted;
        std::move(callback).Run(status);
      },
      std::move(*suitable_issuer_origin), std::move(callback)));
}

void NetworkContext::SetBlockTrustTokens(bool block) {
  block_trust_tokens_ = block;
}

void NetworkContext::OnProxyLookupComplete(
    ProxyLookupRequest* proxy_lookup_request) {
  auto it = proxy_lookup_requests_.find(proxy_lookup_request);
  CHECK(it != proxy_lookup_requests_.end());
  proxy_lookup_requests_.erase(it);
}

void NetworkContext::OnProxyCheckingHostResolverRequestComplete(
    ProxyCheckingHostResolverRequest* request) {
  auto it = proxy_checking_host_resolver_requests_.find(request);
  CHECK(it != proxy_checking_host_resolver_requests_.end());
  proxy_checking_host_resolver_requests_.erase(it);
}

void NetworkContext::SetTLS13EarlyDataEnabled(bool enabled) {
  url_request_context_->http_transaction_factory()
      ->GetSession()
      ->SetTLS13EarlyDataEnabled(enabled);
}

void NetworkContext::DisableQuic() {
  url_request_context_->http_transaction_factory()->GetSession()->DisableQuic();
}

void NetworkContext::DestroyURLLoaderFactory(
    PrefetchMatchingURLLoaderFactory* url_loader_factory) {
  if (is_destructing_) {
    return;
  }
  auto it = url_loader_factories_.find(url_loader_factory);
  CHECK(it != url_loader_factories_.end());
  url_loader_factories_.erase(it);
}

void NetworkContext::Remove(WebTransport* transport) {
  auto it = web_transports_.find(transport);
  if (it != web_transports_.end()) {
    web_transports_.erase(it);
  }
}

void NetworkContext::LoaderCreated(const OriginatingProcessId& process_id) {
  loader_count_per_process_[process_id] += 1;
}

void NetworkContext::LoaderDestroyed(const OriginatingProcessId& process_id) {
  auto it = loader_count_per_process_.find(process_id);
  CHECK(it != loader_count_per_process_.end());
  it->second -= 1;
  if (it->second == 0) {
    loader_count_per_process_.erase(it);
  }
}

bool NetworkContext::CanCreateLoader(const OriginatingProcessId& process_id) {
  auto it = loader_count_per_process_.find(process_id);
  uint32_t count = (it == loader_count_per_process_.end() ? 0 : it->second);
  return count < max_loaders_per_process_;
}

size_t NetworkContext::GetNumOutstandingResolveHostRequestsForTesting() const {
  size_t sum = proxy_checking_host_resolver_requests_.size();
  if (internal_host_resolver_) {
    sum += internal_host_resolver_->GetNumOutstandingRequestsForTesting();
  }
  for (const auto& host_resolver : host_resolvers_) {
    sum += host_resolver->GetNumOutstandingRequestsForTesting();  // IN-TEST
  }
  return sum;
}

bool NetworkContext::SkipReportingPermissionCheck() const {
#if BUILDFLAG(ENABLE_REPORTING)
  return params_ && params_->skip_reporting_send_permission_check;
#else
  return false;
#endif  // BUILDFLAG(ENABLE_REPORTING)
}

void NetworkContext::ClearTrustTokenData(mojom::ClearDataFilterPtr filter,
                                         base::OnceClosure done) {
  if (!trust_token_store_) {
    std::move(done).Run();
    return;
  }
  trust_token_store_->ExecuteOrEnqueue(base::BindOnce(
      [](mojom::ClearDataFilterPtr filter, base::OnceClosure done,
         TrustTokenStore* store) {
        std::ignore = store->ClearDataForFilter(std::move(filter));
        std::move(done).Run();
      },
      std::move(filter), std::move(done)));
}

void NetworkContext::ClearTrustTokenSessionOnlyData(
    ClearTrustTokenSessionOnlyDataCallback callback) {
  // Only called when Private State Tokens is enabled, i.e.,
  // `trust_token_store_` is non-null.
  DCHECK(trust_token_store_);
  DCHECK(cookie_manager_);

  DeleteCookiePredicate cookie_predicate =
      cookie_manager_->cookie_settings().CreateDeleteCookieOnExitPredicate();
  if (!cookie_predicate) {
    std::move(callback).Run(false);
    return;
  }

  auto store_predicate = base::BindRepeating(
      [](DeleteCookiePredicate predicate, const std::string& origin) {
        return predicate.Run(origin, net::CookieSourceScheme::kSecure);
      },
      std::move(cookie_predicate));
  trust_token_store_->ExecuteOrEnqueue(base::BindOnce(
      [](base::RepeatingCallback<bool(const std::string&)> pred,
         ClearTrustTokenSessionOnlyDataCallback cb, TrustTokenStore* store) {
        bool any_data_deleted = store->ClearDataForPredicate(std::move(pred));
        std::move(cb).Run(any_data_deleted);
      },
      std::move(store_predicate), std::move(callback)));
}

void NetworkContext::ClearNetworkingHistoryBetween(
    base::Time start_time,
    base::Time end_time,
    base::OnceClosure completion_callback) {
#if BUILDFLAG(IS_CT_SUPPORTED)
  auto barrier = base::BarrierClosure(3, std::move(completion_callback));
  sct_auditing_handler()->ClearPendingReports(barrier);
#else
  auto barrier = base::BarrierClosure(2, std::move(completion_callback));
#endif  // BUIDLFLAG(IS_CT_SUPPORTED)

  url_request_context_->transport_security_state()->DeleteAllDynamicDataBetween(
      start_time, end_time, barrier);

  // TODO(mmenke): Neither of these methods waits until the changes have been
  // commited to disk. They probably should, as most similar methods net/
  // exposes do.
  // May not be set in all tests.
  if (network_qualities_pref_delegate_) {
    network_qualities_pref_delegate_->ClearPrefs();
  }

  url_request_context_->http_server_properties()->Clear(barrier);
}

void NetworkContext::ClearHttpCache(base::Time start_time,
                                    base::Time end_time,
                                    mojom::ClearDataFilterPtr filter,
                                    ClearHttpCacheCallback callback) {
  ClearHttpCacheInternal(start_time, end_time, std::move(filter),
                         ClearHttpCacheMode::kPhysical, std::move(callback));
}

void NetworkContext::ClearHttpCacheLogically(
    base::Time start_time,
    base::Time end_time,
    mojom::ClearDataFilterPtr filter,
    ClearHttpCacheLogicallyCallback callback) {
  ClearHttpCacheInternal(start_time, end_time, std::move(filter),
                         ClearHttpCacheMode::kLogical, std::move(callback));
}

void NetworkContext::ClearHttpCacheInternal(base::Time start_time,
                                            base::Time end_time,
                                            mojom::ClearDataFilterPtr filter,
                                            ClearHttpCacheMode mode,
                                            base::OnceClosure callback) {
  base::UmaHistogramEnumeration("NetworkService.ClearHttpCacheMode", mode);

  if (mode == ClearHttpCacheMode::kLogical &&
      base::FeatureList::IsEnabled(net::features::kLogicalClearHttpCache)) {
    net::HttpCache* cache =
        url_request_context_->http_transaction_factory()->GetCache();
    net::HttpCache::InvalidationFilter filter_for_callback;
    if (cache) {
      // Step 1: Add a logical filter to the HttpCache. This is near-instant
      // and ensures that subsequent requests won't see invalidated data.
      net::HttpCache::InvalidationFilter invalidation_filter;
      invalidation_filter.begin_time = start_time;
      // Cap the end_time to Now() so we don't accidentally invalidate future
      // cache entries if the caller passes Time::Max().
      invalidation_filter.end_time = std::min(end_time, base::Time::Now());
      if (filter) {
        invalidation_filter.filter_type =
            ConvertClearDataFilterType(filter->type);
        invalidation_filter.origins = base::flat_set<url::Origin>(
            filter->origins.begin(), filter->origins.end());
        invalidation_filter.domains = base::flat_set<std::string>(
            filter->domains.begin(), filter->domains.end());
      } else {
        invalidation_filter.filter_type = net::UrlFilterType::kFalseIfMatches;
      }
      filter_for_callback = invalidation_filter;

      cache->AddInvalidationFilter(std::move(invalidation_filter));
      // Queue the filter for disk persistence and invoke `callback` once
      // LogicalInvalidationStore::Save() finishes saving to disk.
      OnLogicalFilterAdded(filter_for_callback, std::move(callback));
    } else {
      if (callback) {
        std::move(callback).Run();
      }
    }

    // Step 2: Trigger the slow physical cleanup in the background.
    // When it completes, the logical filter is removed since the data is
    // physically gone.
    auto logical_cleanup_done_callback = base::BindOnce(
        &RemoveInvalidationFilterCallback, weak_factory_.GetWeakPtr(),
        std::move(filter_for_callback));

    StartHttpCacheDataRemover(std::move(filter), start_time, end_time,
                              std::move(logical_cleanup_done_callback));

    // Step 3: Responding to the caller immediately is omitted to wait for
    // persistence.
    return;
  }

  // It's safe to use Unretained below as the HttpCacheDataRemover is owned by
  // |this| and guarantees it won't call its callback if deleted.
  StartHttpCacheDataRemover(std::move(filter), start_time, end_time,
                            std::move(callback));
}

void NetworkContext::ComputeHttpCacheSize(
    base::Time start_time,
    base::Time end_time,
    ComputeHttpCacheSizeCallback callback) {
  // It's safe to use Unretained below as the HttpCacheDataCounter is owned by
  // |this| and guarantees it won't call its callback if deleted.
  http_cache_data_counters_.push_back(HttpCacheDataCounter::CreateAndStart(
      url_request_context_, start_time, end_time,
      base::BindOnce(&NetworkContext::OnHttpCacheSizeComputed,
                     base::Unretained(this), std::move(callback))));
}

net::HttpCache* NetworkContext::GetHttpCache() {
  if (!url_request_context_ ||
      !url_request_context_->http_transaction_factory()) {
    return nullptr;
  }
  return url_request_context_->http_transaction_factory()->GetCache();
}

void NetworkContext::NotifyBrowserIdle() {
  net::HttpCache* cache = GetHttpCache();
  if (!cache) {
    return;
  }
  disk_cache::Backend* backend = cache->GetCurrentBackend();
  if (!backend) {
    return;
  }
  backend->OnBrowserIdle();
}

void NetworkContext::ProcessSharedCacheEligibleEntriesForTesting(
    base::OnceClosure callback) {
  auto scoped_closure_runner = base::ScopedClosureRunner(std::move(callback));
#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)
  if (net::HttpCache* cache = GetHttpCache()) {
    if (disk_cache::Backend* backend = cache->GetCurrentBackend()) {
      if (backend->SupportsSharedCache()) {
        backend->ProcessAllSharedCacheEligibleEntriesForTest(  // IN-TEST
            std::move(scoped_closure_runner));
      }
    }
  }
#endif  // BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)
}

void NetworkContext::ClearCorsPreflightCache(
    mojom::ClearDataFilterPtr filter,
    ClearCorsPreflightCacheCallback callback) {
  cors_preflight_controller_.ClearCorsPreflightCache(std::move(filter));
  std::move(callback).Run();
}

void NetworkContext::ClearHostCache(mojom::ClearDataFilterPtr filter,
                                    ClearHostCacheCallback callback) {
  net::HostCache* host_cache =
      url_request_context_->host_resolver()->GetHostCache();
  DCHECK(host_cache);
  host_cache->ClearForHosts(MakeDomainFilter(filter.get()));
  std::move(callback).Run();
}

void NetworkContext::ClearHttpAuthCache(base::Time start_time,
                                        base::Time end_time,
                                        mojom::ClearDataFilterPtr filter,
                                        ClearHttpAuthCacheCallback callback) {
  net::HttpNetworkSession* http_session =
      url_request_context_->http_transaction_factory()->GetSession();
  DCHECK(http_session);

  if (http_session->http_auth_cache()->ClearEntriesAddedBetween(
          start_time, end_time, BuildUrlFilter(std::move(filter)))) {
    // TODO(mmenke): Use another error code for this, as ERR_ABORTED has
    // somewhat magical handling with respect to navigations.
    http_session->CloseAllConnections(net::ERR_ABORTED, "Clearing auth cache");
  }

  std::move(callback).Run();
}

void NetworkContext::ClearReportingCacheReports(
    mojom::ClearDataFilterPtr filter,
    ClearReportingCacheReportsCallback callback) {
#if BUILDFLAG(ENABLE_REPORTING)
  net::ReportingService* reporting_service =
      url_request_context_->reporting_service();
  if (reporting_service) {
    if (filter) {
      reporting_service->RemoveBrowsingData(
          net::ReportingBrowsingDataRemover::DATA_TYPE_REPORTS,
          BuildOriginFilter(std::move(filter)));
    } else {
      reporting_service->RemoveAllBrowsingData(
          net::ReportingBrowsingDataRemover::DATA_TYPE_REPORTS);
    }
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)

  std::move(callback).Run();
}

void NetworkContext::ClearReportingCacheClients(
    mojom::ClearDataFilterPtr filter,
    ClearReportingCacheClientsCallback callback) {
#if BUILDFLAG(ENABLE_REPORTING)
  net::ReportingService* reporting_service =
      url_request_context_->reporting_service();
  if (reporting_service) {
    if (filter) {
      reporting_service->RemoveBrowsingData(
          net::ReportingBrowsingDataRemover::DATA_TYPE_CLIENTS,
          BuildOriginFilter(std::move(filter)));
    } else {
      reporting_service->RemoveAllBrowsingData(
          net::ReportingBrowsingDataRemover::DATA_TYPE_CLIENTS);
    }
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)

  std::move(callback).Run();
}

void NetworkContext::ClearNetworkErrorLogging(
    mojom::ClearDataFilterPtr filter,
    ClearNetworkErrorLoggingCallback callback) {
#if BUILDFLAG(ENABLE_REPORTING)
  net::NetworkErrorLoggingService* logging_service =
      url_request_context_->network_error_logging_service();
  if (logging_service) {
    if (filter) {
      logging_service->RemoveBrowsingData(BuildOriginFilter(std::move(filter)));
    } else {
      logging_service->RemoveAllBrowsingData();
    }
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)

  std::move(callback).Run();
}

void NetworkContext::SetDocumentReportingEndpoints(
    const base::UnguessableToken& reporting_source,
    const url::Origin& origin,
    const net::IsolationInfo& isolation_info,
    const base::flat_map<std::string, std::string>& endpoints) {
#if BUILDFLAG(ENABLE_REPORTING)
  DCHECK(!reporting_source.is_empty());
  DCHECK_EQ(net::IsolationInfo::RequestType::kOther,
            isolation_info.request_type());
  net::ReportingService* reporting_service =
      url_request_context()->reporting_service();
  if (reporting_service) {
    reporting_service->SetDocumentReportingEndpoints(reporting_source, origin,
                                                     isolation_info, endpoints);
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)
}

void NetworkContext::SendReportsAndRemoveSource(
    const base::UnguessableToken& reporting_source) {
#if BUILDFLAG(ENABLE_REPORTING)
  DCHECK(!reporting_source.is_empty());
  net::ReportingService* reporting_service =
      url_request_context()->reporting_service();
  if (reporting_service) {
    reporting_service->SendReportsAndRemoveSource(reporting_source);
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)
}

void NetworkContext::SendReportsForSource(
    const base::UnguessableToken& reporting_source) {
#if BUILDFLAG(ENABLE_REPORTING)
  CHECK(!reporting_source.is_empty());
  net::ReportingService* reporting_service =
      url_request_context()->reporting_service();
  if (reporting_service) {
    reporting_service->SendReportsForSource(reporting_source);
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)
}

void NetworkContext::QueueReport(
    const std::string& type,
    const std::string& group,
    const GURL& url,
    const std::optional<base::UnguessableToken>& reporting_source,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    base::DictValue body) {
  QueueReportInternal(type, group, url, reporting_source,
                      network_anonymization_key, std::move(body),
                      net::ReportingTargetType::kDeveloper);
}

void NetworkContext::QueueEnterpriseReport(const std::string& type,
                                           const std::string& group,
                                           const GURL& url,
                                           base::DictValue body) {
  // Enterprise reports don't use a |reporting_source| or
  // |network_anonymization_key|. Enterprise endpoints are profile-bound and not
  // document-bound like web developer endpoints.
  QueueReportInternal(type, group, url, /*reporting_source=*/std::nullopt,
                      net::NetworkAnonymizationKey(), std::move(body),
                      net::ReportingTargetType::kEnterprise);
}

void NetworkContext::QueueReportInternal(
    const std::string& type,
    const std::string& group,
    const GURL& url,
    const std::optional<base::UnguessableToken>& reporting_source,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    base::DictValue body,
    net::ReportingTargetType target_type) {
#if BUILDFLAG(ENABLE_REPORTING)
  // If |reporting_source| is provided, it must not be empty.
  DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
  // Enterprise reports have an empty |network_anonymization_key|.
  if (target_type == net::ReportingTargetType::kDeveloper &&
      require_network_anonymization_key_) {
    DCHECK(!network_anonymization_key.IsEmpty());
  }

  // Get the ReportingService.
  net::URLRequestContext* request_context = url_request_context();
  net::ReportingService* reporting_service =
      request_context->reporting_service();
  // TODO(paulmeyer): Remove this once the network service ships everywhere.
  if (!reporting_service) {
    return;
  }

  std::string reported_user_agent = "";
  if (request_context->http_user_agent_settings() != nullptr) {
    reported_user_agent =
        request_context->http_user_agent_settings()->GetUserAgent();
  }

  reporting_service->QueueReport(
      url, reporting_source, network_anonymization_key, reported_user_agent,
      group, type, std::move(body), 0 /* depth */, target_type);
#endif  // BUILDFLAG(ENABLE_REPORTING)
}

void NetworkContext::QueueConnectionAllowlistReport(
    const GURL& context,
    const GURL& resource,
    const net::NetworkAnonymizationKey& key,
    const std::optional<base::UnguessableToken>& reporting_source,
    const std::string& group,
    bool enforced) {
  base::DictValue body;
  // Strip username, password, and ref fragments from the blocked resource URL.
  body.Set("connection", resource.GetAsReferrer().spec());
  body.Set("disposition", enforced ? "enforce" : "report");

  QueueReport("connection-allowlist", group, context, reporting_source, key,
              std::move(body));
}

void NetworkContext::QueueSignedExchangeReport(
    mojom::SignedExchangeReportPtr report,
    const net::NetworkAnonymizationKey& network_anonymization_key) {
#if BUILDFLAG(ENABLE_REPORTING)
  if (require_network_anonymization_key_) {
    DCHECK(!network_anonymization_key.IsEmpty());
  }

  net::NetworkErrorLoggingService* logging_service =
      url_request_context_->network_error_logging_service();
  if (!logging_service) {
    return;
  }

  std::string user_agent;
  if (url_request_context_->http_user_agent_settings() != nullptr) {
    user_agent =
        url_request_context_->http_user_agent_settings()->GetUserAgent();
  }
  net::NetworkErrorLoggingService::SignedExchangeReportDetails details;
  details.network_anonymization_key = network_anonymization_key;
  details.success = report->success;
  details.type = std::move(report->type);
  details.outer_url = std::move(report->outer_url);
  details.inner_url = std::move(report->inner_url);
  details.cert_url = std::move(report->cert_url);
  details.referrer = std::move(report->referrer);
  details.server_ip_address = std::move(report->server_ip_address);
  details.protocol = std::move(report->protocol);
  details.method = std::move(report->method);
  details.status_code = report->status_code;
  details.elapsed_time = report->elapsed_time;
  details.user_agent = std::move(user_agent);
  logging_service->QueueSignedExchangeReport(std::move(details));
#endif  // BUILDFLAG(ENABLE_REPORTING)
}

#if BUILDFLAG(ENABLE_REPORTING)
void NetworkContext::AddReportingApiObserver(
    mojo::PendingRemote<network::mojom::ReportingApiObserver> observer) {
  if (url_request_context() && url_request_context()->reporting_service()) {
    if (!is_observing_reporting_service_) {
      is_observing_reporting_service_ = true;
      url_request_context()->reporting_service()->AddReportingCacheObserver(
          this);
      reporting_api_observers_.set_disconnect_handler(
          base::BindRepeating(&NetworkContext::OnReportingObserverDisconnect,
                              weak_factory_.GetWeakPtr()));
    }
    auto id = reporting_api_observers_.Add(std::move(observer));

    auto service_reports =
        url_request_context()->reporting_service()->GetReports();
    for (const net::ReportingReport* service_report : service_reports) {
      reporting_api_observers_.Get(id)->OnReportAdded(*service_report);
    }

    base::flat_map<url::Origin, std::vector<net::ReportingEndpoint>>
        endpoints_by_origin = url_request_context()
                                  ->reporting_service()
                                  ->GetV1ReportingEndpointsByOrigin();
    for (auto const& origin_and_endpoints : endpoints_by_origin) {
      OnEndpointsUpdatedForOrigin(origin_and_endpoints.second);
    }
  }
}

void NetworkContext::OnReportAdded(const net::ReportingReport* service_report) {
  for (const auto& observer : reporting_api_observers_) {
    observer->OnReportAdded(*service_report);
  }
}

void NetworkContext::OnEndpointsUpdatedForOrigin(
    const std::vector<net::ReportingEndpoint>& endpoints) {
  for (const auto& observer : reporting_api_observers_) {
    observer->OnEndpointsUpdatedForOrigin(endpoints);
  }
}

void NetworkContext::OnReportUpdated(
    const net::ReportingReport* service_report) {
  for (const auto& observer : reporting_api_observers_) {
    observer->OnReportUpdated(*service_report);
  }
}

void NetworkContext::OnReportingObserverDisconnect(
    mojo::RemoteSetElementId /*mojo_id*/) {
  if (!reporting_api_observers_.size()) {
    DCHECK(url_request_context());
    DCHECK(url_request_context()->reporting_service());
    url_request_context()->reporting_service()->RemoveReportingCacheObserver(
        this);
    is_observing_reporting_service_ = false;
  }
}

void NetworkContext::AddVariationsHeadersToReportingRequest(
    net::URLRequest* request) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  variations::AppendVariationsHeaderWithCustomValue(
      request->url(),
      IsIncognitoFromParams(*params_) ? variations::InIncognito::kYes
                                      : variations::InIncognito::kNo,
      variations_headers_.get(), request);
}
#endif  // BUILDFLAG(ENABLE_REPORTING)

void NetworkContext::ClearDomainReliability(
    mojom::ClearDataFilterPtr filter,
    DomainReliabilityClearMode mode,
    ClearDomainReliabilityCallback callback) {
  if (domain_reliability_monitor_) {
    domain_reliability::DomainReliabilityClearMode dr_mode;
    if (mode ==
        mojom::NetworkContext::DomainReliabilityClearMode::CLEAR_CONTEXTS) {
      dr_mode = domain_reliability::CLEAR_CONTEXTS;
    } else {
      dr_mode = domain_reliability::CLEAR_BEACONS;
    }

    domain_reliability_monitor_->ClearBrowsingData(
        dr_mode, BuildOriginFilter(std::move(filter)));
  }
  std::move(callback).Run();
}

void NetworkContext::CloseAllConnections(CloseAllConnectionsCallback callback) {
  net::HttpNetworkSession* http_session =
      url_request_context_->http_transaction_factory()->GetSession();
  DCHECK(http_session);

  // TODO(mmenke): Use another error code for this, as ERR_ABORTED has somewhat
  // magical handling with respect to navigations.
  http_session->CloseAllConnections(net::ERR_ABORTED,
                                    "Embedder closing all connections");

  std::move(callback).Run();
}

void NetworkContext::CloseIdleConnections(
    CloseIdleConnectionsCallback callback) {
  net::HttpNetworkSession* http_session =
      url_request_context_->http_transaction_factory()->GetSession();
  DCHECK(http_session);

  http_session->CloseIdleConnections("Embedder closing idle connections");

  std::move(callback).Run();
}

void NetworkContext::SetNetworkConditions(
    const base::UnguessableToken& throttling_profile_id,
    const base::UnguessableToken& throttling_client_id,
    std::vector<mojom::MatchedNetworkConditionsPtr> conditions) {
  std::vector<MatchedNetworkConditions> network_conditions;
  for (auto& condition : conditions) {
    network_conditions.emplace_back(
        std::move(condition->pattern),
        NetworkConditions{condition->conditions->offline,
                          condition->conditions->latency.InMillisecondsF(),
                          condition->conditions->download_throughput,
                          condition->conditions->upload_throughput,
                          condition->conditions->packet_loss,
                          condition->conditions->packet_queue_length,
                          condition->conditions->packet_reordering,
                          condition->conditions->rule_id});
  }
  ThrottlingController::SetConditions(throttling_profile_id,
                                      throttling_client_id,
                                      std::move(network_conditions));
}

void NetworkContext::SetAcceptLanguage(const std::string& new_accept_language) {
  // This may only be called on NetworkContexts created with the constructor
  // that calls MakeURLRequestContext().
  DCHECK(user_agent_settings_);
  user_agent_settings_->set_accept_language(new_accept_language);
}

void NetworkContext::SetEnableReferrers(bool enable_referrers) {
  // This may only be called on NetworkContexts created with the constructor
  // that calls MakeURLRequestContext().
  DCHECK(network_delegate_);
  network_delegate_->set_enable_referrers(enable_referrers);
}

#if BUILDFLAG(IS_CT_SUPPORTED)
void NetworkContext::SetCTPolicy(mojom::CTPolicyPtr ct_policy) {
  if (!require_ct_delegate_) {
    return;
  }

  require_ct_delegate_->UpdateCTPolicies(ct_policy->excluded_hosts,
                                         ct_policy->excluded_spkis);
}

void NetworkContext::MaybeEnqueueSCTReport(
    const net::HostPortPair& host_port_pair,
    const net::X509Certificate* validated_certificate_chain,
    const net::SignedCertificateTimestampAndStatusList&
        signed_certificate_timestamps) {
  sct_auditing_handler()->MaybeEnqueueReport(host_port_pair,
                                             validated_certificate_chain,
                                             signed_certificate_timestamps);
}

void NetworkContext::SetSCTAuditingMode(mojom::SCTAuditingMode mode) {
  sct_auditing_handler()->SetMode(mode);
}

void NetworkContext::CanSendSCTAuditingReport(
    base::OnceCallback<void(bool)> callback) {
  // If the NetworkContextClient hasn't been set yet or has disconnected for
  // some reason, just return `false`. (One case where this could occur is when
  // restarting SCTAuditingReporter instances loaded form disk at startup -- see
  // crbug.com/1347180 for more details on that case.)
  if (!client_) {
    std::move(callback).Run(false);
    return;
  }
  client_->OnCanSendSCTAuditingReport(std::move(callback));
}

void NetworkContext::OnNewSCTAuditingReportSent() {
  client_->OnNewSCTAuditingReportSent();
}
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

void NetworkContext::CreateUDPSocket(
    mojo::PendingReceiver<mojom::UDPSocket> receiver,
    mojo::PendingRemote<mojom::UDPSocketListener> listener) {
  socket_factory_->CreateUDPSocket(std::move(receiver), std::move(listener));
}

void NetworkContext::CreateRestrictedUDPSocket(
    const net::IPEndPoint& addr,
    mojom::RestrictedUDPSocketMode mode,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    mojom::RestrictedUDPSocketParamsPtr params,
    mojo::PendingReceiver<mojom::RestrictedUDPSocket> receiver,
    mojo::PendingRemote<mojom::UDPSocketListener> listener,
    bool allow_multicast,
    bool allow_source_specific_multicast,
    CreateRestrictedUDPSocketCallback callback) {
  // SimpleHostResolver is transitively owned by |this|.
  socket_factory_->CreateRestrictedUDPSocket(
      addr, mode, traffic_annotation, std::move(params), std::move(receiver),
      std::move(listener), SimpleHostResolver::Create(this), allow_multicast,
      allow_source_specific_multicast, std::move(callback));
}

void NetworkContext::CreateTCPServerSocket(
    const net::IPEndPoint& local_addr,
    mojom::TCPServerSocketOptionsPtr options,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    mojo::PendingReceiver<mojom::TCPServerSocket> receiver,
    CreateTCPServerSocketCallback callback) {
  socket_factory_->CreateTCPServerSocket(
      local_addr, std::move(options),
      static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
      std::move(receiver), std::move(callback));
}

void NetworkContext::CreateTCPConnectedSocket(
    const std::optional<net::IPEndPoint>& local_addr,
    const net::AddressList& remote_addr_list,
    mojom::TCPConnectedSocketOptionsPtr tcp_connected_socket_options,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    mojo::PendingReceiver<mojom::TCPConnectedSocket> receiver,
    mojo::PendingRemote<mojom::SocketObserver> observer,
    CreateTCPConnectedSocketCallback callback) {
  socket_factory_->CreateTCPConnectedSocket(
      local_addr, remote_addr_list, std::move(tcp_connected_socket_options),
      traffic_annotation, std::move(receiver), std::move(observer),
      std::move(callback));
}

void NetworkContext::CreateTCPBoundSocket(
    const net::IPEndPoint& local_addr,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    mojo::PendingReceiver<mojom::TCPBoundSocket> receiver,
    CreateTCPBoundSocketCallback callback) {
  socket_factory_->CreateTCPBoundSocket(
      local_addr,
      static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
      std::move(receiver), std::move(callback));
}

void NetworkContext::CreateProxyResolvingSocketFactory(
    mojo::PendingReceiver<mojom::ProxyResolvingSocketFactory> receiver) {
  proxy_resolving_socket_factories_.Add(
      std::make_unique<ProxyResolvingSocketFactoryMojo>(url_request_context()),
      std::move(receiver));
}

void NetworkContext::LookUpProxyForURL(
    const GURL& url,
    const net::NetworkAnonymizationKey& network_anonyization_key,
    mojo::PendingRemote<mojom::ProxyLookupClient> proxy_lookup_client) {
  DCHECK(proxy_lookup_client);
  std::unique_ptr<ProxyLookupRequest> proxy_lookup_request(
      std::make_unique<ProxyLookupRequest>(std::move(proxy_lookup_client), this,
                                           network_anonyization_key));
  ProxyLookupRequest* proxy_lookup_request_ptr = proxy_lookup_request.get();
  proxy_lookup_requests_.insert(std::move(proxy_lookup_request));
  proxy_lookup_request_ptr->Start(url);
}

void NetworkContext::ForceReloadProxyConfig(
    ForceReloadProxyConfigCallback callback) {
  net::ConfiguredProxyResolutionService* configured_proxy_resolution_service =
      nullptr;
  if (url_request_context()
          ->proxy_resolution_service()
          ->CastToConfiguredProxyResolutionService(
              &configured_proxy_resolution_service)) {
    configured_proxy_resolution_service->ForceReloadProxyConfig();
  } else {
    LOG(WARNING)
        << "NetworkContext::ForceReloadProxyConfig() had no effect, as the "
           "underlying ProxyResolutionService does not support that concept.";
  }
  std::move(callback).Run();
}

void NetworkContext::ClearBadProxiesCache(
    ClearBadProxiesCacheCallback callback) {
  url_request_context()->proxy_resolution_service()->ClearBadProxiesCache();
  std::move(callback).Run();
}

void NetworkContext::CreateWebSocket(
    const GURL& url,
    const std::vector<std::string>& requested_protocols,
    net::StorageAccessApiStatus storage_access_api_status,
    const net::IsolationInfo& isolation_info,
    std::vector<mojom::HttpHeaderPtr> additional_headers,
    const network::OriginatingProcessId& process_id,
    const url::Origin& origin,
    network::mojom::ClientSecurityStatePtr client_security_state,
    uint32_t options,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
    mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
        url_loader_network_observer,
    mojo::PendingRemote<mojom::WebSocketAuthenticationHandler> auth_handler,
    mojo::PendingRemote<mojom::TrustedHeaderClient> header_client,
    const std::optional<base::UnguessableToken>& throttling_profile_id,
    const base::UnguessableToken& network_restrictions_id,
    mojom::IPAddressSpace target_address_space,
    std::optional<int64_t> target_network) {
#if BUILDFLAG(ENABLE_WEBSOCKETS)
  if (!websocket_factory_) {
    websocket_factory_ = std::make_unique<WebSocketFactory>(this);
  }

  DCHECK(process_id);

  websocket_factory_->CreateWebSocket(
      url, requested_protocols, storage_access_api_status, isolation_info,
      std::move(additional_headers), process_id, origin,
      std::move(client_security_state), options,
      static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
      std::move(handshake_client), std::move(url_loader_network_observer),
      std::move(auth_handler), std::move(header_client), throttling_profile_id,
      network_restrictions_id, target_address_space,
      target_network.value_or(net::handles::kInvalidNetworkHandle));
#endif  // BUILDFLAG(ENABLE_WEBSOCKETS)
}

void NetworkContext::CreateWebTransport(
    const GURL& url,
    const url::Origin& origin,
    const net::NetworkAnonymizationKey& key,
    std::vector<mojom::WebTransportCertificateFingerprintPtr> fingerprints,
    const std::vector<std::string>& application_protocols,
    mojom::WebTransportCongestionControl congestion_control,
    std::optional<uint16_t>
        anticipated_concurrent_incoming_unidirectional_streams,
    std::optional<uint16_t>
        anticipated_concurrent_incoming_bidirectional_streams,
    std::vector<net::HttpRequestHeaders::HeaderKeyValuePair> additional_headers,
    mojo::PendingRemote<mojom::WebTransportHandshakeClient>
        pending_handshake_client,
    mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
        url_loader_network_observer,
    mojom::ClientSecurityStatePtr client_security_state,
    const base::UnguessableToken& network_restrictions_id) {
  if (!IsNetworkForNetworkRestrictionsIdAndUrlAllowed(network_restrictions_id,
                                                      url, key)) {
    mojo::Remote<mojom::WebTransportHandshakeClient> remote_handshake_client(
        std::move(pending_handshake_client));
    remote_handshake_client->OnHandshakeFailed(
        net::WebTransportError(net::ERR_NETWORK_ACCESS_REVOKED));
    return;
  }
  web_transports_.insert(std::make_unique<WebTransport>(
      url, origin, key, fingerprints, application_protocols, congestion_control,
      anticipated_concurrent_incoming_unidirectional_streams,
      anticipated_concurrent_incoming_bidirectional_streams,
      std::move(additional_headers), this, std::move(pending_handshake_client),
      std::move(url_loader_network_observer),
      std::move(client_security_state)));
}

void NetworkContext::CreateNetLogExporter(
    mojo::PendingReceiver<mojom::NetLogExporter> receiver) {
  net_log_exporter_receivers_.Add(std::make_unique<NetLogExporter>(this),
                                  std::move(receiver));
}

void NetworkContext::ResolveHost(
    mojom::HostResolverHostPtr host,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    mojom::ResolveHostParametersPtr optional_parameters,
    mojo::PendingRemote<mojom::ResolveHostClient> response_client) {
  // Dns request is disallowed if network access is disabled for the partition
  // nonce or the network_restrictions_id.
  // TODO(crbug.com/447954811): For Connection Allowlist DNS lookups, define a
  // less-strict mechanism that matches against the host portion of the URL.
  GURL url = host->is_host_port_pair()
                 ? url::SchemeHostPort(url::kHttpsScheme,
                                       host->get_host_port_pair().host(),
                                       host->get_host_port_pair().port())
                       .GetURL()
                 : host->get_scheme_host_port().GetURL();
  bool is_network_disallowed_for_restrictions_id =
      (optional_parameters &&
       optional_parameters->network_restrictions_id.has_value() &&
       !IsHostResolutionForNetworkRestrictionsIdAndHostAllowed(
           optional_parameters->network_restrictions_id.value(), *host,
           network_anonymization_key));
  if (is_network_disallowed_for_restrictions_id) {
    mojo::Remote<mojom::ResolveHostClient> remote_response_client(
        std::move(response_client));
    remote_response_client->OnComplete(
        net::ERR_NETWORK_ACCESS_REVOKED,
        net::ResolveErrorInfo(net::ERR_NETWORK_ACCESS_REVOKED),
        /*resolved_addresses=*/{},
        /*alternative_endpoints=*/{});
    return;
  }

  if (optional_parameters && optional_parameters->direct_only) {
    auto request = std::make_unique<ProxyCheckingHostResolverRequest>(
        this, std::move(host), network_anonymization_key,
        std::move(optional_parameters), std::move(response_client));
    auto* request_ptr = request.get();
    proxy_checking_host_resolver_requests_.insert(std::move(request));
    request_ptr->Start(url);
    return;
  }

  if (!internal_host_resolver_) {
    internal_host_resolver_ = std::make_unique<HostResolver>(
        url_request_context_->host_resolver(), url_request_context_->net_log());
  }
  internal_host_resolver_->ResolveHost(
      std::move(host), network_anonymization_key,
      std::move(optional_parameters), std::move(response_client));
}

void NetworkContext::CreateHostResolver(
    const std::optional<net::DnsConfigOverrides>& config_overrides,
    mojo::PendingReceiver<mojom::HostResolver> receiver) {
  net::HostResolver* internal_resolver = url_request_context_->host_resolver();
  std::unique_ptr<net::HostResolver> private_internal_resolver;

  if (config_overrides &&
      config_overrides.value() != net::DnsConfigOverrides()) {
    // If custom configuration is needed, create a separate internal resolver
    // with the specified configuration overrides. Because we are using a non-
    // standard resolver, disable the cache.
    //
    // TODO(crbug.com/40577881): Consider allowing per-resolve overrides, so the
    // same net::HostResolver with the same scheduler and cache can be used with
    // different overrides.  But since this is only used for special cases for
    // now, much easier to create entirely separate net::HostResolver instances.
    net::HostResolver::ManagerOptions options;
    options.insecure_dns_mode = net::InsecureDnsMode::kEnabledBuiltIn;
    // Assume additional types are unnecessary for these special cases.
    options.additional_types_via_insecure_dns_enabled = false;
    options.dns_config_overrides = config_overrides.value();
    private_internal_resolver =
        network_service_->host_resolver_factory()->CreateStandaloneResolver(
            url_request_context_->net_log(), std::move(options),
            /* host_mapping_rules */ "", /* enable_caching */ false,
            /* enable_stale */ false);
    private_internal_resolver->SetRequestContext(url_request_context_);
    internal_resolver = private_internal_resolver.get();
  }

  host_resolvers_.emplace(std::make_unique<HostResolver>(
      std::move(receiver),
      base::BindOnce(&NetworkContext::OnHostResolverShutdown,
                     base::Unretained(this)),
      internal_resolver, std::move(private_internal_resolver),
      url_request_context_->net_log()));
}

void NetworkContext::VerifyCertInternal(
    const scoped_refptr<net::X509Certificate>& certificate,
    const net::HostPortPair& host_port,
    const std::string& ocsp_response,
    const std::string& sct_list,
    CTVerificationMode ct_verification_mode,
    VerifyCertCallback callback) {
  uint64_t cert_verify_id = ++next_cert_verify_id_;
  CHECK_NE(0u, next_cert_verify_id_);  // The request ID should not wrap around.
  auto pending_cert_verify = std::make_unique<PendingCertVerify>();
  pending_cert_verify->callback = std::move(callback);
  pending_cert_verify->result = std::make_unique<net::CertVerifyResult>();
  pending_cert_verify->certificate = certificate;
  pending_cert_verify->host_port = host_port;
  net::CertVerifier* cert_verifier =
      g_cert_verifier_for_testing ? g_cert_verifier_for_testing
                                  : url_request_context_->cert_verifier();
  int flags = 0;
  switch (ct_verification_mode) {
    case CTVerificationMode::kTlsCertificate:
      break;
    case CTVerificationMode::kSignedExchange:
      flags = net::CertVerifier::VERIFY_SXG_CT_REQUIREMENTS;
      break;
  }
  int result = cert_verifier->Verify(
      net::CertVerifier::RequestParams(certificate, host_port.host(), flags,
                                       ocsp_response, sct_list),
      pending_cert_verify->result.get(),
      base::BindOnce(&NetworkContext::OnVerifyCertComplete,
                     base::Unretained(this), cert_verify_id),
      &pending_cert_verify->request,
      net::NetLogWithSource::Make(url_request_context_->net_log(),
                                  net::NetLogSourceType::CERT_VERIFIER_JOB));
  cert_verifier_requests_[cert_verify_id] = std::move(pending_cert_verify);

  if (result != net::ERR_IO_PENDING) {
    OnVerifyCertComplete(cert_verify_id, result);
  }
}

void NetworkContext::VerifyCert(
    const scoped_refptr<net::X509Certificate>& certificate,
    const net::HostPortPair& host_port,
    const std::string& ocsp_response,
    const std::string& sct_list,
    VerifyCertCallback callback) {
  VerifyCertInternal(certificate, host_port, ocsp_response, sct_list,
                     CTVerificationMode::kTlsCertificate, std::move(callback));
}

void NetworkContext::VerifyCertForSignedExchange(
    const scoped_refptr<net::X509Certificate>& certificate,
    const net::HostPortPair& host_port,
    const std::string& ocsp_response,
    const std::string& sct_list,
    VerifyCertCallback callback) {
  VerifyCertInternal(certificate, host_port, ocsp_response, sct_list,
                     CTVerificationMode::kSignedExchange, std::move(callback));
}

void NetworkContext::Verify2QwacCertBinding(
    const std::string& binding,
    const std::string& hostname,
    const scoped_refptr<net::X509Certificate>& tls_certificate,
    Verify2QwacCertBindingCallback callback) {
  net::CertVerifier* cert_verifier =
      g_cert_verifier_for_testing ? g_cert_verifier_for_testing
                                  : url_request_context_->cert_verifier();
  cert_verifier->Verify2QwacBinding(
      binding, hostname, tls_certificate, std::move(callback),
      net::NetLogWithSource::Make(
          url_request_context_->net_log(),
          net::NetLogSourceType::CERT_VERIFIER_2QWAC_JOB));
}

void NetworkContext::NotifyExternalCacheHit(const GURL& url,
                                            const std::string& http_method,
                                            const net::NetworkIsolationKey& key,
                                            bool include_credentials) {
  net::HttpCache* cache =
      url_request_context_->http_transaction_factory()->GetCache();
  if (!cache) {
    return;
  }
  cache->OnExternalCacheHit(url, http_method, key, include_credentials);
}

#if BUILDFLAG(IS_ANDROID)
void NetworkContext::SetHttpCacheMaxSize(base::ByteSize http_cache_max_size,
                                         bool force_initialization) {
  // Note: we do not update params_->http_cache_max_size.
  net::HttpCache* cache =
      url_request_context_->http_transaction_factory()->GetCache();
  if (!cache) {
    return;
  }
  cache->SetMaxBytes(http_cache_max_size, force_initialization);
}
#endif  // BUILDFLAG(IS_ANDROID)

void NetworkContext::SetCorsOriginAccessListsForOrigin(
    const url::Origin& source_origin,
    std::vector<mojom::CorsOriginPatternPtr> allow_patterns,
    std::vector<mojom::CorsOriginPatternPtr> block_patterns,
    SetCorsOriginAccessListsForOriginCallback callback) {
  cors_origin_access_list_.SetAllowListForOrigin(source_origin, allow_patterns);
  cors_origin_access_list_.SetBlockListForOrigin(source_origin, block_patterns);
  std::move(callback).Run();
}

void NetworkContext::AddHSTS(const std::string& host,
                             base::Time expiry,
                             bool include_subdomains,
                             AddHSTSCallback callback) {
  net::TransportSecurityState* state =
      url_request_context_->transport_security_state();
  state->AddHSTS(host, expiry, include_subdomains);
  std::move(callback).Run();
}

void NetworkContext::IsHSTSActiveForHost(const std::string& host,
                                         bool is_top_level_nav,
                                         IsHSTSActiveForHostCallback callback) {
  net::TransportSecurityState* security_state =
      url_request_context_->transport_security_state();

  if (!security_state) {
    std::move(callback).Run(false);
    return;
  }

  std::move(callback).Run(
      security_state->ShouldUpgradeToSSL(host, is_top_level_nav));
}

void NetworkContext::GetHSTSState(const std::string& domain,
                                  GetHSTSStateCallback callback) {
  base::DictValue result;

  if (base::IsStringASCII(domain)) {
    net::TransportSecurityState* transport_security_state =
        url_request_context()->transport_security_state();
    if (transport_security_state) {
      net::TransportSecurityState::STSState static_sts_state;
      bool found_sts_static = transport_security_state->GetStaticSTSState(
          domain, &static_sts_state);
      if (found_sts_static) {
        result.Set("static_upgrade_mode",
                   static_cast<int>(static_sts_state.upgrade_mode));
        result.Set("static_sts_include_subdomains",
                   static_sts_state.include_subdomains);
        result.Set("static_sts_observed",
                   static_sts_state.last_observed.InSecondsFSinceUnixEpoch());
        result.Set("static_sts_expiry",
                   static_sts_state.expiry.InSecondsFSinceUnixEpoch());
        result.Set("static_sts_domain", static_sts_state.domain);
      }

      net::TransportSecurityState::STSState dynamic_sts_state;
      bool found_sts_dynamic = transport_security_state->GetDynamicSTSState(
          domain, &dynamic_sts_state);

      if (found_sts_dynamic) {
        result.Set("dynamic_upgrade_mode",
                   static_cast<int>(dynamic_sts_state.upgrade_mode));
        result.Set("dynamic_sts_include_subdomains",
                   dynamic_sts_state.include_subdomains);
        result.Set("dynamic_sts_observed",
                   dynamic_sts_state.last_observed.InSecondsFSinceUnixEpoch());
        result.Set("dynamic_sts_expiry",
                   dynamic_sts_state.expiry.InSecondsFSinceUnixEpoch());
        result.Set("dynamic_sts_domain", dynamic_sts_state.domain);
      }

      result.Set("result", found_sts_static || found_sts_dynamic);
    } else {
      result.Set("error", "no TransportSecurityState active");
    }
  } else {
    result.Set("error", "non-ASCII domain name");
  }

  std::move(callback).Run(std::move(result));
}

void NetworkContext::DeleteDynamicDataForHost(
    const std::string& host,
    DeleteDynamicDataForHostCallback callback) {
  net::TransportSecurityState* transport_security_state =
      url_request_context()->transport_security_state();
  if (!transport_security_state) {
    std::move(callback).Run(false);
    return;
  }

  std::move(callback).Run(
      transport_security_state->DeleteDynamicDataForHost(host));
}

void NetworkContext::EnableStaticKeyPinningForTesting(
    EnableStaticKeyPinningForTestingCallback callback) {
  net::TransportSecurityState* state =
      url_request_context_->transport_security_state();
  state->EnableStaticPinsForTesting();
  state->SetPinningListAlwaysTimelyForTesting(true);
  std::move(callback).Run();
}

void NetworkContext::VerifyCertificateForTesting(
    const scoped_refptr<net::X509Certificate>& certificate,
    const std::string& hostname,
    const std::string& ocsp_response,
    const std::string& sct_list,
    VerifyCertificateForTestingCallback callback) {
  net::CertVerifier* cert_verifier = url_request_context_->cert_verifier();

  auto state = std::make_unique<TestVerifyCertState>();
  auto* request = &state->request;
  auto* result = &state->result;

  cert_verifier->Verify(
      net::CertVerifier::RequestParams(certificate.get(), hostname, 0,
                                       ocsp_response, sct_list),
      result,
      base::BindOnce(TestVerifyCertCallback, std::move(state),
                     std::move(callback)),
      request,
      net::NetLogWithSource::Make(net::NetLog::Get(),
                                  net::NetLogSourceType::NONE));
}

void NetworkContext::GetTrustAnchorIDsForTesting(
    GetTrustAnchorIDsForTestingCallback callback) {
  const net::SSLContextConfig& ssl_context_config =
      url_request_context_->ssl_config_service()->GetSSLContextConfig();
  std::move(callback).Run(net::x509_util::ParseTlsTrustAnchorIDs(
      ssl_context_config.SelectAllTrustAnchorIDs()));
}

void NetworkContext::PreconnectSockets(
    uint32_t num_streams,
    const GURL& original_url,
    mojom::CredentialsMode credentials_mode,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    const base::UnguessableToken& network_restrictions_id,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    const std::optional<net::ConnectionKeepAliveConfig>& keepalive_config,
    mojo::PendingRemote<mojom::ConnectionChangeObserverClient>
        connection_change_observer_client) {
  DCHECK(!require_network_anonymization_key_ ||
         !network_anonymization_key.IsEmpty());

  if (base::FeatureList::IsEnabled(
          net::features::kEarlyCookieLoadOnPreconnect)) {
    net::CookieStore* cookie_store = url_request_context_->cookie_store();
    if (cookie_store) {
      cookie_store->OnPreconnect(original_url);
    }
  }

  GURL url = GetHSTSRedirectForPreconnect(original_url);

  // |PreconnectSockets| may receive arguments from the renderer, which is not
  // guaranteed to validate them.
  if (num_streams == 0) {
    return;
  }

  // Preconnect is disallowed if network access is disabled for the
  // network_restrictions_id.
  if (!IsNetworkForNetworkRestrictionsIdAndUrlAllowed(
          network_restrictions_id, url, network_anonymization_key)) {
    return;
  }

  std::string user_agent;
  if (url_request_context_->http_user_agent_settings()) {
    user_agent =
        url_request_context_->http_user_agent_settings()->GetUserAgent();
  }
  net::HttpRequestInfo request_info;
  request_info.url = url;
  request_info.method = net::HttpRequestHeaders::kGetMethod;
  request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
                                       user_agent);
  request_info.traffic_annotation = traffic_annotation;

  if (keepalive_config.has_value() ||
      connection_change_observer_client.is_valid()) {
    request_info.connection_management_config =
        net::ConnectionManagementConfig();
    request_info.connection_management_config->keep_alive_config =
        keepalive_config;
    if (connection_change_observer_client.is_valid()) {
      auto change_observer = std::make_unique<ConnectionChangeObserver>(
          std::move(connection_change_observer_client), this);

      request_info.connection_management_config->connection_change_observer =
          change_observer->GetWeakPtr();
      connection_change_observers_.insert(std::move(change_observer));
    }
  }

  switch (credentials_mode) {
    case mojom::CredentialsMode::kOmit:
      request_info.load_flags = net::LOAD_DO_NOT_SAVE_COOKIES;
      request_info.privacy_mode = net::PRIVACY_MODE_ENABLED;
      break;

    case mojom::CredentialsMode::kSameOrigin:
      // Not yet implemented. If you need this credentials mode please update
      // this branch to set the correct request_info fields.
      NOTREACHED() << "kSameOrigin not yet implemented";

    case mojom::CredentialsMode::kInclude:
      request_info.load_flags = net::LOAD_NORMAL;
      request_info.privacy_mode = net::PRIVACY_MODE_DISABLED;
      break;

    case mojom::CredentialsMode::kOmitBug_775438_Workaround:
      request_info.load_flags = net::LOAD_DO_NOT_SAVE_COOKIES;
      request_info.privacy_mode =
          net::PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS;
      break;
  }

  request_info.network_anonymization_key = network_anonymization_key;

  net::HttpTransactionFactory* factory =
      url_request_context_->http_transaction_factory();
  net::HttpNetworkSession* session = factory->GetSession();
  net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
  http_stream_factory->PreconnectStreams(
      base::saturated_cast<int32_t>(num_streams), request_info,
      base::OnceClosure());
}

#if BUILDFLAG(IS_P2P_ENABLED)
void NetworkContext::CreateP2PSocketManager(
    const net::NetworkAnonymizationKey& network_anonymization_key,
    mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient> client,
    mojo::PendingReceiver<mojom::P2PTrustedSocketManager>
        trusted_socket_manager,
    mojo::PendingReceiver<mojom::P2PSocketManager> socket_manager_receiver) {
  std::unique_ptr<P2PSocketManager> socket_manager =
      std::make_unique<P2PSocketManager>(
          network_anonymization_key, std::move(client),
          std::move(trusted_socket_manager), std::move(socket_manager_receiver),
          base::BindRepeating(&NetworkContext::DestroySocketManager,
                              base::Unretained(this)),
          url_request_context_);
  socket_managers_[socket_manager.get()] = std::move(socket_manager);
}
#endif  // BUILDFLAG(IS_P2P_ENABLED)

void NetworkContext::CreateMdnsResponder(
    mojo::PendingReceiver<mojom::MdnsResponder> responder_receiver) {
#if BUILDFLAG(ENABLE_MDNS)
  if (!mdns_responder_manager_) {
    mdns_responder_manager_ = std::make_unique<MdnsResponderManager>();
  }

  mdns_responder_manager_->CreateMdnsResponder(std::move(responder_receiver));
#else
  NOTREACHED();
#endif  // BUILDFLAG(ENABLE_MDNS)
}

void NetworkContext::AddDomainReliabilityContextForTesting(
    const url::Origin& origin,
    const GURL& upload_url,
    AddDomainReliabilityContextForTestingCallback callback) {
  auto config = std::make_unique<domain_reliability::DomainReliabilityConfig>();
  config->origin = origin;
  config->include_subdomains = false;
  config->collectors.push_back(std::make_unique<GURL>(upload_url));
  config->success_sample_rate = 1.0;
  config->failure_sample_rate = 1.0;
  domain_reliability_monitor_->AddContextForTesting(std::move(config));
  std::move(callback).Run();
}

void NetworkContext::ForceDomainReliabilityUploadsForTesting(
    ForceDomainReliabilityUploadsForTestingCallback callback) {
  domain_reliability_monitor_->ForceUploadsForTesting();
  std::move(callback).Run();
}

void NetworkContext::SetSplitAuthCacheByNetworkAnonymizationKey(
    bool split_auth_cache_by_network_anonymization_key) {
  url_request_context_->http_transaction_factory()
      ->GetSession()
      ->http_auth_cache()
      ->SetKeyServerEntriesByNetworkAnonymizationKey(
          split_auth_cache_by_network_anonymization_key);
}

void NetworkContext::SaveHttpAuthCacheProxyEntries(
    SaveHttpAuthCacheProxyEntriesCallback callback) {
  net::HttpAuthCache* http_auth_cache =
      url_request_context_->http_transaction_factory()
          ->GetSession()
          ->http_auth_cache();
  base::UnguessableToken cache_key =
      network_service_->http_auth_cache_proxy_copier()->SaveHttpAuthCache(
          *http_auth_cache);
  std::move(callback).Run(cache_key);
}

void NetworkContext::LoadHttpAuthCacheProxyEntries(
    const base::UnguessableToken& cache_key,
    LoadHttpAuthCacheProxyEntriesCallback callback) {
  net::HttpAuthCache* http_auth_cache =
      url_request_context_->http_transaction_factory()
          ->GetSession()
          ->http_auth_cache();
  network_service_->http_auth_cache_proxy_copier()->LoadHttpAuthCache(
      cache_key, http_auth_cache);
  std::move(callback).Run();
}

void NetworkContext::AddAuthCacheEntry(
    const net::AuthChallengeInfo& challenge,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    const net::AuthCredentials& credentials,
    AddAuthCacheEntryCallback callback) {
  net::HttpAuthCache* http_auth_cache =
      url_request_context_->http_transaction_factory()
          ->GetSession()
          ->http_auth_cache();
  http_auth_cache->Add(challenge.challenger,
                       challenge.is_proxy ? net::HttpAuth::AUTH_PROXY
                                          : net::HttpAuth::AUTH_SERVER,
                       challenge.realm,
                       net::HttpAuth::StringToScheme(challenge.scheme),
                       network_anonymization_key, challenge.challenge,
                       credentials, challenge.path);
  std::move(callback).Run();
}

void NetworkContext::SetCorsNonWildcardRequestHeadersSupport(bool value) {
  if (!base::FeatureList::IsEnabled(
          features::kCorsNonWildcardRequestHeadersSupport)) {
    return;
  }
  cors_non_wildcard_request_headers_support_ =
      cors::NonWildcardRequestHeadersSupport(value);
}

#if BUILDFLAG(IS_CHROMEOS)
void NetworkContext::LookupProxyAuthCredentials(
    const net::ProxyServer& proxy_server,
    const std::string& auth_scheme,
    const std::string& realm,
    LookupProxyAuthCredentialsCallback callback) {
  net::HttpAuth::Scheme net_scheme =
      net::HttpAuth::StringToScheme(base::ToLowerASCII(auth_scheme));
  if (net_scheme == net::HttpAuth::Scheme::AUTH_SCHEME_MAX) {
    std::move(callback).Run(std::nullopt);
    return;
  }
  net::HttpAuthCache* http_auth_cache =
      url_request_context_->http_transaction_factory()
          ->GetSession()
          ->http_auth_cache();
  // TODO(crbug.com/40704785): Mapping proxy addresses to URLs is a
  // lossy conversion, shouldn't do this.
  const char* scheme =
      proxy_server.is_secure_http_like() ? "https://" : "http://";
  url::SchemeHostPort scheme_host_port(
      GURL(scheme + proxy_server.host_port_pair().ToString()));
  if (!scheme_host_port.IsValid()) {
    std::move(callback).Run(std::nullopt);
    return;
  }

  //  Unlike server credentials, proxy credentials are not keyed on
  //  NetworkAnonymizationKey.
  net::HttpAuthCache::Entry* entry = http_auth_cache->Lookup(
      scheme_host_port, net::HttpAuth::AUTH_PROXY, realm, net_scheme,
      net::NetworkAnonymizationKey());
  if (entry) {
    std::move(callback).Run(entry->credentials());
  } else {
    std::move(callback).Run(std::nullopt);
  }
}
#endif  // BUILDFLAG(IS_CHROMEOS)

const net::HttpAuthPreferences* NetworkContext::GetHttpAuthPreferences() const {
  return &http_auth_merged_preferences_;
}

size_t NetworkContext::NumOpenWebTransports() const {
  return std::ranges::count(web_transports_, false, &WebTransport::torn_down);
}

WebTransport* NetworkContext::GetWebTransportForTesting() {
  CHECK_EQ(web_transports_.size(), 1u);
  return web_transports_.begin()->get();
}

size_t NetworkContext::CountURLLoaderFactoriesBoundToNetworkForTesting(
    net::handles::NetworkHandle target_network) const {
  return std::ranges::count_if(
      url_loader_factories_, [target_network](const auto& factory) {
        return factory->GetBoundNetworkForTesting() == target_network;
      });
}

void NetworkContext::OnHttpAuthDynamicParamsChanged(
    const mojom::HttpAuthDynamicParams*
        http_auth_dynamic_network_service_params) {
  http_auth_merged_preferences_.SetServerAllowlist(
      http_auth_dynamic_network_service_params->server_allowlist);
  http_auth_merged_preferences_.SetDelegateAllowlist(
      http_auth_dynamic_network_service_params->delegate_allowlist);
  http_auth_merged_preferences_.set_delegate_by_kdc_policy(
      http_auth_dynamic_network_service_params->delegate_by_kdc_policy);
  http_auth_merged_preferences_.set_negotiate_disable_cname_lookup(
      http_auth_dynamic_network_service_params->negotiate_disable_cname_lookup);
  http_auth_merged_preferences_.set_negotiate_enable_port(
      http_auth_dynamic_network_service_params->enable_negotiate_port);
  http_auth_merged_preferences_.set_basic_over_http_enabled(
      http_auth_dynamic_network_service_params->basic_over_http_enabled);
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  http_auth_merged_preferences_.set_ntlm_v2_enabled(
      http_auth_dynamic_network_service_params->ntlm_v2_enabled);
#endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)

#if BUILDFLAG(IS_ANDROID)
  http_auth_merged_preferences_.set_auth_android_negotiate_account_type(
      http_auth_dynamic_network_service_params->android_negotiate_account_type);
#endif  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
  http_auth_merged_preferences_.set_allow_gssapi_library_load(
      http_auth_dynamic_network_service_params->allow_gssapi_library_load);
#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
  if (http_auth_dynamic_network_service_params->allowed_schemes.has_value()) {
    http_auth_merged_preferences_.SetAllowedSchemes(base::flat_set<std::string>(
        http_auth_dynamic_network_service_params->allowed_schemes->begin(),
        http_auth_dynamic_network_service_params->allowed_schemes->end()));
  } else {
    http_auth_merged_preferences_.SetAllowedSchemes(std::nullopt);
  }

  url_matcher_ = std::make_unique<url_matcher::URLMatcher>();
  url_matcher::util::AddAllowFiltersWithLimit(
      url_matcher_.get(), http_auth_dynamic_network_service_params
                              ->patterns_allowed_to_use_all_schemes);
  proxy_url_matcher_ = std::make_unique<url_matcher::URLMatcher>();
  url_matcher::util::AddAllowFiltersWithLimit(
      proxy_url_matcher_.get(),
      http_auth_dynamic_network_service_params
          ->patterns_allowed_to_use_all_schemes_for_proxies);
  http_auth_merged_preferences_.set_http_auth_scheme_filter(
      base::BindRepeating(&NetworkContext::IsAllowedToUseAllHttpAuthSchemes,
                          base::Unretained(this)));
}

URLRequestContextOwner NetworkContext::MakeURLRequestContext(
    mojo::PendingRemote<mojom::URLLoaderFactory>
        url_loader_factory_for_cert_net_fetcher,
    scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store,
    OnURLRequestContextBuilderConfiguredCallback
        on_url_request_context_builder_configured,
    net::handles::NetworkHandle bound_network) {
  URLRequestContextBuilderMojo builder;
  const base::CommandLine* command_line =
      base::CommandLine::ForCurrentProcess();

  bool is_network_bound = bound_network != net::handles::kInvalidNetworkHandle;
  if (is_network_bound) {
    builder.BindToNetwork(bound_network);
  }

  std::unique_ptr<net::CertVerifier> cert_verifier;
  if (g_cert_verifier_for_testing) {
    cert_verifier = std::make_unique<WrappedTestingCertVerifier>();
  } else {
    DCHECK(params_->cert_verifier_params);
    // base::Unretained() is safe below because |this| will own
    // |cert_verifier|.
    // TODO(crbug.com/40693524): this cert verifier should deal with
    // disconnections if the CertVerifierService is run outside of the browser
    // process.
    cert_verifier = std::make_unique<cert_verifier::MojoCertVerifier>(
        std::move(params_->cert_verifier_params->cert_verifier_service),
        std::move(params_->cert_verifier_params
                      ->cert_verifier_service_client_receiver),
        std::move(url_loader_factory_for_cert_net_fetcher),
        base::BindRepeating(
            &NetworkContext::CreateURLLoaderFactoryForCertNetFetcher,
            base::Unretained(this)));

    // Whether the cert verifier is remote or in-process, we should wrap it in
    // caching and coalescing layers to avoid extra verifications and IPCs.
    cert_verifier = std::make_unique<net::CachingCertVerifier>(
        std::make_unique<net::CoalescingCertVerifier>(
            std::move(cert_verifier)));
  }

  builder.SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
      *command_line, nullptr, std::move(cert_verifier)));

#if BUILDFLAG(IS_CT_SUPPORTED)
  builder.set_sct_auditing_delegate(
      std::make_unique<SCTAuditingDelegate>(weak_factory_.GetWeakPtr()));
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

  std::unique_ptr<NetworkServiceNetworkDelegate> network_delegate =
      std::make_unique<NetworkServiceNetworkDelegate>(
          params_->enable_referrers,
          params_->validate_referrer_policy_on_initial_request,
          std::move(params_->proxy_error_client), this);
  network_delegate_ = network_delegate.get();
  builder.set_network_delegate(std::move(network_delegate));

  if (params_->initial_custom_proxy_config ||
      params_->custom_proxy_config_client_receiver) {
    builder.set_proxy_delegate(std::make_unique<NetworkServiceProxyDelegate>(
        std::move(params_->initial_custom_proxy_config),
        std::move(params_->custom_proxy_config_client_receiver),
        std::move(params_->custom_proxy_connection_observer_remote)));
  }

  net::NetLog* net_log = nullptr;
  if (network_service_) {
    net_log = network_service_->net_log();
    builder.set_net_log(net_log);
    if (!is_network_bound) {
      // Network bound URLRequestContexts build and configure their own special
      // HostResolverManager and HostResolver. So, don't inject the
      // NetworkService one even if NetworkService is enabled.
      builder.set_host_resolver_manager(
          network_service_->host_resolver_manager());
      builder.set_host_resolver_factory(
          network_service_->host_resolver_factory());
    }
    builder.SetHttpAuthHandlerFactory(
        network_service_->CreateHttpAuthHandlerFactory(this));
    builder.set_network_quality_estimator(
        network_service_->network_quality_estimator());
  }
  trust_token_store_ = std::make_unique<PendingTrustTokenStore>();

  base::FilePath trust_token_path;
  if (GetFullDataFilePath(
          params_->file_paths,
          &network::mojom::NetworkContextFilePaths::trust_token_database_name,
          trust_token_path)) {
    SQLiteTrustTokenPersister::CreateForFilePath(
        base::ThreadPool::CreateSequencedTaskRunner(
            {base::MayBlock(), kTrustTokenDatabaseTaskPriority,
             base::TaskShutdownBehavior::BLOCK_SHUTDOWN}),
        trust_token_path, kTrustTokenWriteBufferingWindow,
        base::BindOnce(&NetworkContext::FinishConstructingTrustTokenStore,
                       weak_factory_.GetWeakPtr()));
  } else {
    trust_token_store_->OnStoreReady(std::make_unique<TrustTokenStore>(
        std::make_unique<InMemoryTrustTokenPersister>(),
        std::make_unique<ExpiryInspectingRecordExpiryDelegate>(
            network_service()->trust_token_key_commitments())));
  }

  std::unique_ptr<net::StaticHttpUserAgentSettings> user_agent_settings =
      std::make_unique<net::StaticHttpUserAgentSettings>(
          params_->accept_language, params_->user_agent);
  // Borrow an alias for future use before giving the builder ownership.
  user_agent_settings_ = user_agent_settings.get();
  builder.set_http_user_agent_settings(std::move(user_agent_settings));

  builder.set_enable_brotli(params_->enable_brotli);
  builder.set_enable_zstd(params_->enable_zstd);

  if (params_->proxy_resolver_factory) {
    builder.SetMojoProxyResolverFactory(
        std::move(params_->proxy_resolver_factory));
  }

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
  if (params_->system_proxy_resolver) {
    builder.SetMojoSystemProxyResolver(
        std::move(params_->system_proxy_resolver));
  }
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

#if BUILDFLAG(IS_CHROMEOS)
  if (params_->dhcp_wpad_url_client) {
    builder.SetDhcpWpadUrlClient(std::move(params_->dhcp_wpad_url_client));
  }
#endif  // BUILDFLAG(IS_CHROMEOS)

  if (!params_->http_cache_enabled) {
    builder.DisableHttpCache();
  } else {
    net::URLRequestContextBuilder::HttpCacheParams cache_params;
    cache_params.max_size = params_->http_cache_max_size;
    if (IsIncognitoFromParams(*params_)) {
      cache_params.type =
          net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY;
    } else {
      // Network-bound NetworkContexts should not persist state on disk.
      CHECK(!is_network_bound);

      cache_params.path = params_->file_paths->http_cache_directory->path();
      if (params_->file_paths->no_vary_search_directory) {
        cache_params.no_vary_search_path =
            params_->file_paths->no_vary_search_directory->path();
      }
      if (params_->file_paths->logical_invalidation_directory) {
        cache_params.logical_invalidation_path =
            params_->file_paths->logical_invalidation_directory->path();
      }
      cache_params.type = network_session_configurator::ChooseCacheType();

      if (params_->http_cache_file_operations_factory) {
        cache_params.file_operations_factory =
            base::MakeRefCounted<MojoBackendFileOperationsFactory>(
                std::move(params_->http_cache_file_operations_factory));
      }

      if (params_->enable_encrypted_http_cache) {
#if BUILDFLAG(ENTERPRISE_CACHE_ENCRYPTION)
        // For enterprise users, we always use simple backend when encryption is
        // enabled.
        cache_params.type =
            net::URLRequestContextBuilder::HttpCacheParams::DISK_SIMPLE;

        // For enterprise users, we wrap `BackendFileOperations` to intercept
        // file I/O with encryption ops, and create and pass in a
        // `CacheEncryptionDelegate` to encrypt/decrypt cache entries on disk.
        if (params_->encryption_provider) {
          std::unique_ptr<net::CacheEncryptionDelegate>
              cache_encryption_delegate = std::make_unique<
                  enterprise_encryption::OSCryptCacheEncryptionDelegate>(
                  std::move(params_->encryption_provider));
          if (!cache_params.file_operations_factory) {
            // Since it's the fallback later anyways, explicitly created here to
            // wrap. EncryptedBackendFileOperationsFactory will wrap this later
            // when os_crypt_cache_encryption_delegate is created and
            // initialized.
            cache_params.file_operations_factory = base::MakeRefCounted<
                disk_cache::TrivialFileOperationsFactory>();
          }
          builder.set_cache_encryption_delegate(
              std::move(cache_encryption_delegate));
        }
#else
        NOTREACHED();
#endif  // BUILDFLAG(ENTERPRISE_CACHE_ENCRYPTION)
      }
    }
    cache_params.reset_cache = params_->reset_http_cache_backend;

#if BUILDFLAG(IS_ANDROID)
    app_status_listeners_.push_back(
        std::make_unique<NetworkContextApplicationStatusListener>(
            cache_params.app_status_listener_getter));
#endif  // BUILDFLAG(IS_ANDROID)
    builder.EnableHttpCache(cache_params);
  }

  std::unique_ptr<net::EchModeGetter> ech_mode_getter;
  if (params_->use_platform_ech_policy) {
#if BUILDFLAG(IS_ANDROID)
    ech_mode_getter = std::make_unique<net::EchModeGetterAndroid>();
#endif
  }
  std::unique_ptr<SSLConfigServiceMojo> ssl_config_service =
      std::make_unique<SSLConfigServiceMojo>(
          std::move(params_->initial_ssl_config),
          std::move(params_->ssl_config_client_receiver),
          std::move(ech_mode_getter));
  SSLConfigServiceMojo* ssl_config_service_raw = ssl_config_service.get();
  builder.set_ssl_config_service(std::move(ssl_config_service));

  if (!params_->initial_proxy_config &&
      !params_->proxy_config_client_receiver.is_valid()) {
    params_->initial_proxy_config =
        net::ProxyConfigWithAnnotation::CreateDirect();
  }
  builder.set_proxy_config_service(std::make_unique<ProxyConfigServiceMojo>(
      std::move(params_->proxy_config_client_receiver),
      std::move(params_->initial_proxy_config),
      std::move(params_->proxy_config_poller_client)));
  builder.set_pac_quick_check_enabled(params_->pac_quick_check_enabled);

  std::unique_ptr<PrefService> pref_service;

  base::FilePath http_server_properties_file_name;
  if (GetFullDataFilePath(params_->file_paths,
                          &network::mojom::NetworkContextFilePaths::
                              http_server_properties_file_name,
                          http_server_properties_file_name)) {
    // Network-bound NetworkContexts should not persist state on disk.
    CHECK(!is_network_bound);
    scoped_refptr<JsonPrefStore> json_pref_store(new JsonPrefStore(
        http_server_properties_file_name, nullptr,
        base::ThreadPool::CreateSequencedTaskRunner(
            {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN,
             base::TaskPriority::BEST_EFFORT})));
    PrefServiceFactory pref_service_factory;
    pref_service_factory.set_user_prefs(json_pref_store);
    pref_service_factory.set_async(true);
    scoped_refptr<PrefRegistrySimple> pref_registry(new PrefRegistrySimple());
    HttpServerPropertiesPrefDelegate::RegisterPrefs(pref_registry.get());
    NetworkQualitiesPrefDelegate::RegisterPrefs(pref_registry.get());
    KnownLegacyScopeDomainsPrefDelegate::RegisterPrefs(pref_registry.get());
    pref_service = pref_service_factory.Create(pref_registry.get());

    builder.SetHttpServerProperties(std::make_unique<net::HttpServerProperties>(
        std::make_unique<HttpServerPropertiesPrefDelegate>(pref_service.get()),
        net_log));

    network_qualities_pref_delegate_ =
        std::make_unique<NetworkQualitiesPrefDelegate>(
            pref_service.get(), network_service_->network_quality_estimator());
  }

  if (session_cleanup_cookie_store) {
    // If the pref service was registered and initialized use it.
    // If not, use nullptr to indicate prefs aren't available.
    std::unique_ptr<net::CookieMonster> cookie_store =
        std::make_unique<net::CookieMonster>(
            session_cleanup_cookie_store.get(), net_log,
            pref_service
                ? std::make_unique<KnownLegacyScopeDomainsPrefDelegate>(
                      pref_service.get())
                : nullptr);
    if (params_->persist_session_cookies) {
      cookie_store->SetPersistSessionCookies(true);
    }

    builder.SetCookieStore(std::move(cookie_store));
  }

  base::FilePath transport_security_persister_file_name;
  if (GetFullDataFilePath(params_->file_paths,
                          &network::mojom::NetworkContextFilePaths::
                              transport_security_persister_file_name,
                          transport_security_persister_file_name)) {
    // Network-bound NetworkContexts should not persist state on disk.
    CHECK(!is_network_bound);
    builder.set_transport_security_persister_file_path(
        transport_security_persister_file_name);
  }
  builder.set_hsts_policy_bypass_list(params_->hsts_policy_bypass_list);

#if BUILDFLAG(ENABLE_REPORTING)
  bool reporting_enabled = base::FeatureList::IsEnabled(features::kReporting);
  if (reporting_enabled) {
    auto reporting_policy = net::ReportingPolicy::Create();
    if (params_->reporting_delivery_interval) {
      reporting_policy->delivery_interval =
          *params_->reporting_delivery_interval;
      reporting_policy->endpoint_backoff_policy.initial_delay_ms =
          params_->reporting_delivery_interval->InMilliseconds();
    }
    builder.set_reporting_policy(std::move(reporting_policy));
  } else {
    builder.set_reporting_policy(nullptr);
  }

  bool nel_enabled =
      base::FeatureList::IsEnabled(features::kNetworkErrorLogging);
  builder.set_network_error_logging_enabled(nel_enabled);

  base::FilePath reporting_and_nel_store_database_name;
  if (GetFullDataFilePath(params_->file_paths,
                          &network::mojom::NetworkContextFilePaths::
                              reporting_and_nel_store_database_name,
                          reporting_and_nel_store_database_name) &&
      (reporting_enabled || nel_enabled)) {
    // Network-bound NetworkContexts should not persist state on disk.
    CHECK(!is_network_bound);
    scoped_refptr<base::SequencedTaskRunner> client_task_runner =
        base::SingleThreadTaskRunner::GetCurrentDefault();
    scoped_refptr<base::SequencedTaskRunner> background_task_runner =
        base::ThreadPool::CreateSequencedTaskRunner(
            {base::MayBlock(),
             net::GetReportingAndNelStoreBackgroundSequencePriority(),
             base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
    std::unique_ptr<net::SQLitePersistentReportingAndNelStore> sqlite_store(
        new net::SQLitePersistentReportingAndNelStore(
            reporting_and_nel_store_database_name, client_task_runner,
            background_task_runner));
    builder.set_persistent_reporting_and_nel_store(std::move(sqlite_store));
  } else {
    builder.set_persistent_reporting_and_nel_store(nullptr);
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)

  net::HttpNetworkSessionParams session_params;
  bool is_quic_force_disabled = false;
  if (network_service_ && network_service_->quic_disabled()) {
    is_quic_force_disabled = true;
  }

  auto quic_context = std::make_unique<net::QuicContext>();
  if (params_->quic_idle_connection_timeout_seconds &&
      params_->quic_idle_connection_timeout_seconds.value() >= 0) {
    quic_context->params()->idle_connection_timeout =
        base::Seconds(params_->quic_idle_connection_timeout_seconds.value());
  }
  network_session_configurator::ParseCommandLineAndFieldTrials(
      *base::CommandLine::ForCurrentProcess(), is_quic_force_disabled,
      &session_params, quic_context->params());

  session_params.key_auth_cache_server_entries_by_network_anonymization_key =
      params_->split_auth_cache_by_network_anonymization_key;

  builder.set_http_network_session_params(session_params);
  builder.set_quic_context(std::move(quic_context));

  if (params_->shared_dictionary_enabled) {
    builder.set_enable_shared_dictionary(true);
    builder.set_enable_shared_zstd(true);
  }

#if BUILDFLAG(ENABLE_REPORTING)
  if (base::FeatureList::IsEnabled(
          features::kReportingApiEnableVariationsHeaders)) {
    builder.set_prepare_upload_request_callback(base::BindRepeating(
        &NetworkContext::AddVariationsHeadersToReportingRequest,
        // `this` outlives the URLRequestContext that owns the ReportingService,
        // which owns the ReportingUploader that calls this callback.
        base::Unretained(this)));
  }
#endif

  builder.SetWrapHttpNetworkLayerCallback(
      base::BindOnce([](std::unique_ptr<net::HttpNetworkLayer> network_layer)
                         -> std::unique_ptr<net::HttpTransactionFactory> {
        return std::make_unique<ThrottlingNetworkTransactionFactory>(
            std::move(network_layer));
      }));

  if (command_line->HasSwitch(switches::kHostResolverRules)) {
    builder.set_host_mapping_rules(
        command_line->GetSwitchValueASCII(switches::kHostResolverRules));
  } else if (command_line->HasSwitch(switches::kHostRules)) {
    LOG(WARNING)
        << "The --" << switches::kHostRules
        << " command line switch is deprecated, and now has the same behavior "
           "as --"
        << switches::kHostResolverRules << ". Use --"
        << switches::kHostResolverRules
        << " directly to avoid this LOG message. If you get certificate error "
           "where --"
        << switches::kHostRules
        << " previously did not give one, you need to ensure the server has a "
           "valid certificate for the mapped hostname, not the destination "
           "hostname.";
    builder.set_host_mapping_rules(
        command_line->GetSwitchValueASCII(switches::kHostRules));
  }

#if BUILDFLAG(IS_WIN)
  if (params_->socket_brokers) {
    builder.set_client_socket_factory(
        std::make_unique<BrokeredClientSocketFactory>(
            std::move(params_->socket_brokers->client)));
  }
#endif

  require_network_anonymization_key_ =
      params_->require_network_anonymization_key;

  // If `require_network_anonymization_key_` is true, but the features that can
  // trigger another URLRequest are not set to respect NetworkAnonymizationKeys,
  // the URLRequests that they create might not have a NAK, so only set the
  // corresponding value in the URLRequestContext to true at the URLRequest
  // layer if all those features are set to respect NAK. The Domain Reliability
  // feature, which is partitioned by NIK instead of NAK, triggers creation of
  // URLRequests as well, so also check `net::HttpCache::IsSplitCacheEnabled()`.
  if (require_network_anonymization_key_ &&
      net::NetworkAnonymizationKey::IsPartitioningEnabled() &&
      net::HttpCache::IsSplitCacheEnabled()) {
    builder.set_require_network_anonymization_key(true);
  }

#if BUILDFLAG(IS_ANDROID)
  builder.set_check_cleartext_permitted(params_->check_clear_text_permitted);
#endif  // BUILDFLAG(IS_ANDROID)

  if (params_->device_bound_sessions_enabled) {
    builder.set_has_device_bound_session_service(true);
    builder.set_device_bound_sessions_restricted_sites(
        params_->device_bound_sessions_restricted_sites);

#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
    if (base::FeatureList::IsEnabled(
            net::features::kDeviceBoundSessionsForSingleSignOn)) {
      builder.set_device_bound_sessions_cookie_access_callback(
          base::BindRepeating(
              &NetworkContext::HasCookieAccessForDeviceBoundSession,
              // `this` outlives the `URLRequestContext` that owns the
              // device_bound_sessions::SessionService which calls this
              // callback.
              base::Unretained(this)));
    }
    device_bound_session_service_delegate_ =
        std::make_unique<DeviceBoundSessionServiceDelegate>(
            std::move(params_->device_bound_sessions_network_observer));
    builder.set_device_bound_sessions_client_cert_handler(base::BindRepeating(
        &DeviceBoundSessionServiceDelegate::SelectClientCertificate,
        base::Unretained(device_bound_session_service_delegate_.get())));
    if (params_->bound_sessions_unexportable_key_service.is_valid()) {
      builder.set_unexportable_key_service(
          std::make_unique<unexportable_keys::UnexportableKeyServiceProxied>(
              std::move(params_->bound_sessions_unexportable_key_service)));
    }
#endif

    base::FilePath device_bound_sessions_file_path;
    if (GetFullDataFilePath(params_->file_paths,
                            &network::mojom::NetworkContextFilePaths::
                                device_bound_sessions_database_name,
                            device_bound_sessions_file_path)) {
      // Network-bound NetworkContexts should not persist state on disk.
      CHECK(!is_network_bound);
      builder.set_device_bound_sessions_file_path(
          device_bound_sessions_file_path);
    }
  }

#if BUILDFLAG(IS_ANDROID)
  builder.enable_stale_dns_resolver(params_->stale_dns_enabled);
#endif  // BUILDFLAG(IS_ANDROID)

  if (on_url_request_context_builder_configured) {
    std::move(on_url_request_context_builder_configured).Run(&builder);
  }
  auto result =
      URLRequestContextOwner(std::move(pref_service), builder.Build());

  // Subscribe the CertVerifier to configuration changes that are exposed via
  // the mojom::SSLConfig, but which are not part of the
  // net::SSLConfig[Service] interfaces.
  ssl_config_service_raw->SetCertVerifierForConfiguring(
      result.url_request_context->cert_verifier());

  // Attach some things to the URLRequestContextBuilder's
  // TransportSecurityState.  Since no requests have been made yet, safe to do
  // this even after the call to Build().

#if BUILDFLAG(CHROME_KEY_PINNING_SUPPORTED)
  if (network_service_->pins_list_updated()) {
    result.url_request_context->transport_security_state()->UpdatePinList(
        network_service_->pinsets(), network_service_->host_pins(),
        network_service_->pins_list_update_time());
  }
#endif  // BUILDFLAG(CHROME_KEY_PINNING_SUPPORTED)

#if BUILDFLAG(IS_CT_SUPPORTED)
  if (params_->enforce_chrome_ct_policy) {
    require_ct_delegate_ = base::MakeRefCounted<
        certificate_transparency::ChromeRequireCTDelegate>();
    result.url_request_context->transport_security_state()
        ->SetRequireCTDelegate(require_ct_delegate_);
  }
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

  if (params_->enable_domain_reliability) {
    domain_reliability_monitor_ =
        std::make_unique<domain_reliability::DomainReliabilityMonitor>(
            result.url_request_context.get(),
            params_->domain_reliability_upload_reporter,
            base::BindRepeating(&NetworkContext::CanUploadDomainReliability,
                                base::Unretained(this)));
    domain_reliability_monitor_->AddBakedInConfigs();
    domain_reliability_monitor_->SetDiscardUploads(
        params_->discard_domain_reliablity_uploads);
  }

  return result;
}

scoped_refptr<SessionCleanupCookieStore>
NetworkContext::MakeSessionCleanupCookieStore() const {
  base::FilePath cookie_path;
  if (!GetFullDataFilePath(
          params_->file_paths,
          &network::mojom::NetworkContextFilePaths::cookie_database_name,
          cookie_path)) {
    DCHECK(!params_->restore_old_session_cookies);
    DCHECK(!params_->persist_session_cookies);
    return nullptr;
  }
  scoped_refptr<base::SequencedTaskRunner> client_task_runner =
      base::SingleThreadTaskRunner::GetCurrentDefault();
  scoped_refptr<base::SequencedTaskRunner> background_task_runner =
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), net::GetCookieStoreBackgroundSequencePriority(),
           base::TaskShutdownBehavior::BLOCK_SHUTDOWN});

  std::unique_ptr<net::CookieCryptoDelegate> crypto_delegate = nullptr;

  if (params_->enable_encrypted_cookies) {
    if (params_->cookie_encryption_provider) {
      crypto_delegate = std::make_unique<CookieOSCryptAsyncDelegate>(
          std::move(params_->cookie_encryption_provider));
    } else {
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
      // A cookie crypto delegate should not be created on Android or iOS
      // to match the behavior of cookie_config::GetCookieCryptoDelegate().
      // See https://crbug.com/449652881
      NOTREACHED();
#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
    }
  }

#if BUILDFLAG(IS_WIN)
  const bool enable_exclusive_access =
      network_service()->exclusive_cookie_database_locking();
#else
  const bool enable_exclusive_access = false;
#endif  // BUILDFLAG(IS_WIN)

  scoped_refptr<net::SQLitePersistentCookieStore> sqlite_store(
      new net::SQLitePersistentCookieStore(
          cookie_path, client_task_runner, background_task_runner,
          params_->restore_old_session_cookies, std::move(crypto_delegate),
          enable_exclusive_access));

  return base::MakeRefCounted<SessionCleanupCookieStore>(sqlite_store);
}

void NetworkContext::OnHttpCacheCleared(base::OnceClosure callback,
                                        HttpCacheDataRemover* remover) {
  bool removed = false;
  for (auto iter = http_cache_data_removers_.begin();
       iter != http_cache_data_removers_.end(); ++iter) {
    if (iter->get() == remover) {
      removed = true;
      http_cache_data_removers_.erase(iter);
      break;
    }
  }
  DCHECK(removed);
  std::move(callback).Run();
}

void NetworkContext::OnHostResolverShutdown(HostResolver* resolver) {
  auto found_resolver = host_resolvers_.find(resolver);
  CHECK(found_resolver != host_resolvers_.end());
  host_resolvers_.erase(found_resolver);
}

void NetworkContext::OnHttpCacheSizeComputed(
    ComputeHttpCacheSizeCallback callback,
    HttpCacheDataCounter* counter,
    bool is_upper_limit,
    int64_t result_or_error) {
  std::erase_if(http_cache_data_counters_, base::MatchesUniquePtr(counter));
  std::move(callback).Run(is_upper_limit, result_or_error);
}

void NetworkContext::OnConnectionError() {
  // If owned by the network service, this call will delete |this|.
  if (on_connection_close_callback_) {
    std::move(on_connection_close_callback_).Run(this);
  }
}

GURL NetworkContext::GetHSTSRedirectForPreconnect(const GURL& original_url) {
  // TODO(lilyhoughton) This needs to be gotten rid of once explicit
  // construction with a URLRequestContext is no longer supported.

  if (!url_request_context_->transport_security_state()) {
    RecordHSTSPreconnectUpgradeReason(
        HSTSRedirectUpgradeReason::kNotUpgradedHSTSUnavailable);
    return original_url;
  }

  if (!original_url.SchemeIs(url::kHttpScheme)) {
    RecordHSTSPreconnectUpgradeReason(
        HSTSRedirectUpgradeReason::kNotUpgradedNotHTTP);
    return original_url;
  }

  // TODO(crbug.com/40725781); This currently doesn't allow for preconnect
  // upgrades when kHstsTopLevelNavigationsOnly is enabled. Revisit this
  // decision after analyzing Net.PreconnectHSTSUpgradesUrl metric.
  //
  // When kHstsTopLevelNavigationsOnly is enabled only top-level navigations
  // will be eligable for HSTS upgrades (not sub-resource requests).
  // Unfortunately we don't know at this point if this request is for a
  // top-level navigation so we need to disallow HSTS upgrades for every
  // preconnect.
  if (!url_request_context_->transport_security_state()->ShouldUpgradeToSSL(
          original_url.GetHost(), /*is_top_level_nav=*/false)) {
    RecordHSTSPreconnectUpgradeReason(
        HSTSRedirectUpgradeReason::kNotUpgradedNoHSTSPin);
    return original_url;
  }

  RecordHSTSPreconnectUpgradeReason(HSTSRedirectUpgradeReason::kUpgraded);

  GURL::Replacements replacements;
  replacements.SetSchemeStr("https");
  return original_url.ReplaceComponents(replacements);
}

#if BUILDFLAG(IS_P2P_ENABLED)
void NetworkContext::DestroySocketManager(P2PSocketManager* socket_manager) {
  auto iter = socket_managers_.find(socket_manager);
  CHECK(iter != socket_managers_.end());
  socket_managers_.erase(iter);
}
#endif  // BUILDFLAG(IS_P2P_ENABLED)

void NetworkContext::CanUploadDomainReliability(
    const url::Origin& origin,
    base::OnceCallback<void(bool)> callback) {
  // If the NetworkContextClient hasn't been set yet or has disconnected for
  // some reason, just return `false`. This could occur in the case of CCT for
  // captive portal -- see crbug.com/446496025 for more details, do the similar
  // check to CanSendSCTAuditingReport().
  if (!client_) {
    std::move(callback).Run(false);
    return;
  }
  client_->OnCanSendDomainReliabilityUpload(
      origin,
      base::BindOnce([](base::OnceCallback<void(bool)> callback,
                        bool allowed) { std::move(callback).Run(allowed); },
                     std::move(callback)));
}

void NetworkContext::OnVerifyCertComplete(uint64_t cert_verify_id, int result) {
  auto iter = cert_verifier_requests_.find(cert_verify_id);
  CHECK(iter != cert_verifier_requests_.end());

  auto pending_cert_verify = std::move(iter->second);
  cert_verifier_requests_.erase(iter);

  bool pkp_bypassed = false;
  if (result == net::OK ||
      result == net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED) {
#if BUILDFLAG(IS_CT_SUPPORTED)
    if (url_request_context_->sct_auditing_delegate()) {
      url_request_context_->sct_auditing_delegate()->MaybeEnqueueReport(
          pending_cert_verify->host_port,
          pending_cert_verify->result->verified_cert.get(),
          pending_cert_verify->result->scts);
    }
#endif  // BUILDFLAG(IS_CT_SUPPORTED)
    net::TransportSecurityState::PKPStatus pin_validity =
        url_request_context_->transport_security_state()->CheckPublicKeyPins(
            pending_cert_verify->host_port.host(),
            pending_cert_verify->result->is_issued_by_known_root,
            pending_cert_verify->result->public_key_hashes);
    switch (pin_validity) {
      case net::TransportSecurityState::PKPStatus::VIOLATED:
        pending_cert_verify->result->cert_status |=
            net::CERT_STATUS_PINNED_KEY_MISSING;
        result = net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
        break;
      case net::TransportSecurityState::PKPStatus::BYPASSED:
        pkp_bypassed = true;
        [[fallthrough]];
      case net::TransportSecurityState::PKPStatus::OK:
        // Do nothing.
        break;
    }
  }

  std::move(pending_cert_verify->callback)
      .Run(result, *pending_cert_verify->result.get(), pkp_bypassed);
}

#if BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)
void NetworkContext::EnsureMounted(network::TransferableDirectory* directory) {
  if (directory->NeedsMount()) {
    dismount_closures_.push_back(directory->Mount());
  }
}
#endif  // BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)

void NetworkContext::InitializeCorsParams() {
  TRACE_EVENT0("loading", "NetworkContext::InitializeCorsParams");
  for (const auto& pattern : params_->cors_origin_access_list) {
    cors_origin_access_list_.SetAllowListForOrigin(pattern->source_origin,
                                                   pattern->allow_patterns);
    cors_origin_access_list_.SetBlockListForOrigin(pattern->source_origin,
                                                   pattern->block_patterns);
  }
  for (const auto& key : params_->cors_exempt_header_list) {
    cors_exempt_header_list_.insert(key);
  }

  acam_preflight_spec_conformant_ = params_->acam_preflight_spec_conformant;
}

void NetworkContext::FinishConstructingTrustTokenStore(
    std::unique_ptr<SQLiteTrustTokenPersister> persister) {
  trust_token_store_->OnStoreReady(std::make_unique<TrustTokenStore>(
      std::move(persister),
      std::make_unique<ExpiryInspectingRecordExpiryDelegate>(
          network_service()->trust_token_key_commitments())));
}

bool NetworkContext::IsAllowedToUseAllHttpAuthSchemes(
    const url::SchemeHostPort& scheme_host_port,
    net::HttpAuth::Target target) {
  if (target == net::HttpAuth::AUTH_PROXY) {
    CHECK(proxy_url_matcher_);
    return !proxy_url_matcher_->MatchURL(scheme_host_port.GetURL()).empty();
  }
  CHECK(url_matcher_);
  return !url_matcher_->MatchURL(scheme_host_port.GetURL()).empty();
}

void NetworkContext::CreateTrustedUrlLoaderFactoryForNetworkService(
    mojo::PendingReceiver<mojom::URLLoaderFactory>
        url_loader_factory_pending_receiver) {
  auto url_loader_factory_params = mojom::URLLoaderFactoryParams::New();
  url_loader_factory_params->is_trusted = true;
  url_loader_factory_params->process_id = OriginatingProcessId::browser();
  CreateURLLoaderFactory(std::move(url_loader_factory_pending_receiver),
                         std::move(url_loader_factory_params));
}

void NetworkContext::SetSharedDictionaryCacheMaxSize(
    std::optional<base::ByteSize> cache_max_size) {
  if (!shared_dictionary_manager_) {
    return;
  }
  shared_dictionary_manager_->SetCacheMaxSize(cache_max_size);
}

void NetworkContext::ClearSharedDictionaryCache(
    base::Time start_time,
    base::Time end_time,
    mojom::ClearDataFilterPtr filter,
    ClearSharedDictionaryCacheCallback callback) {
  if (!shared_dictionary_manager_) {
    std::move(callback).Run();
    return;
  }
  shared_dictionary_manager_->ClearData(start_time, end_time,
                                        BuildUrlFilter(std::move(filter)),
                                        std::move(callback));
}

void NetworkContext::ClearSharedDictionaryCacheForIsolationKey(
    const net::SharedDictionaryIsolationKey& isolation_key,
    ClearSharedDictionaryCacheForIsolationKeyCallback callback) {
  if (!shared_dictionary_manager_) {
    std::move(callback).Run();
    return;
  }
  shared_dictionary_manager_->ClearDataForIsolationKey(isolation_key,
                                                       std::move(callback));
}

#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)
void NetworkContext::RegisterHttpCacheClient(
    const net::NetworkIsolationKey& key,
    mojo::PendingRemote<network::mojom::SharedHttpCacheClientFactory>
        shared_http_cache_client) {
  if (key.IsTransient()) {
    return;
  }
  net::HttpCache* http_cache = GetHttpCache();
  if (!http_cache) {
    return;
  }
  auto split_callback = base::SplitOnceCallback(base::BindOnce(
      [](const net::NetworkIsolationKey& key,
         mojo::PendingRemote<network::mojom::SharedHttpCacheClientFactory>
             shared_http_cache_client,
         net::HttpCache::GetBackendResult result) {
        if (result.first == net::OK && result.second &&
            result.second->SupportsSharedCache()) {
          result.second->RegisterSharedCacheClientRemote(
              key, std::make_unique<MojoSharedHttpCacheClientRemote>(
                       std::move(shared_http_cache_client)));
        }
      },
      key, std::move(shared_http_cache_client)));
  net::HttpCache::GetBackendResult result =
      http_cache->GetBackend(std::move(split_callback.first));
  if (result.first != net::ERR_IO_PENDING) {
    std::move(split_callback.second).Run(result);
  }
}
#endif  // BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)

void NetworkContext::ClearSharedDictionarySessionOnlyData(
    ClearSharedDictionarySessionOnlyDataCallback callback) {
  if (!shared_dictionary_manager_ || !cookie_manager_) {
    std::move(callback).Run();
    return;
  }
  DeleteCookiePredicate cookie_predicate =
      cookie_manager_->cookie_settings().CreateDeleteCookieOnExitPredicate();
  if (!cookie_predicate) {
    std::move(callback).Run();
    return;
  }
  auto url_matcher = base::BindRepeating(
      [](DeleteCookiePredicate predicate, const GURL& url) {
        if (!url.is_valid() || !url.has_host()) {
          return false;
        }
        return predicate.Run(url.host(),
                             url.SchemeIsCryptographic()
                                 ? net::CookieSourceScheme::kSecure
                                 : net::CookieSourceScheme::kNonSecure);
      },
      std::move(cookie_predicate));
  shared_dictionary_manager_->ClearData(
      /*start_time=*/base::Time(), /*end_time=*/base::Time::Max(),
      std::move(url_matcher), std::move(callback));
}

void NetworkContext::GetSharedDictionaryUsageInfo(
    GetSharedDictionaryUsageInfoCallback callback) {
  if (!shared_dictionary_manager_) {
    std::move(callback).Run({});
    return;
  }
  shared_dictionary_manager_->GetUsageInfo(std::move(callback));
}

void NetworkContext::GetSharedDictionaryInfo(
    const net::SharedDictionaryIsolationKey& isolation_key,
    GetSharedDictionaryInfoCallback callback) {
  if (!shared_dictionary_manager_) {
    std::move(callback).Run({});
    return;
  }
  shared_dictionary_manager_->GetSharedDictionaryInfo(isolation_key,
                                                      std::move(callback));
}

void NetworkContext::GetSharedDictionaryOriginsBetween(
    base::Time start_time,
    base::Time end_time,
    GetSharedDictionaryOriginsBetweenCallback callback) {
  if (!shared_dictionary_manager_) {
    std::move(callback).Run({});
    return;
  }
  shared_dictionary_manager_->GetOriginsBetween(start_time, end_time,
                                                std::move(callback));
}

void NetworkContext::PreloadSharedDictionaryInfoForDocument(
    const std::vector<GURL>& urls,
    mojo::PendingReceiver<mojom::PreloadedSharedDictionaryInfoHandle>
        preload_handle) {
  if (shared_dictionary_manager_) {
    shared_dictionary_manager_->PreloadSharedDictionaryInfoForDocument(
        urls, std::move(preload_handle));
  }
}

void NetworkContext::HasPreloadedSharedDictionaryInfoForTesting(
    HasPreloadedSharedDictionaryInfoForTestingCallback callback) {
  std::move(callback).Run(
      shared_dictionary_manager_ &&
      shared_dictionary_manager_->HasPreloadedSharedDictionaryInfo());
}

void NetworkContext::FlushCachedClientCertIfNeeded(
    const net::HostPortPair& host,
    const scoped_refptr<net::X509Certificate>& certificate) {
  net::HttpNetworkSession* http_session =
      url_request_context_->http_transaction_factory()->GetSession();
  DCHECK(http_session);
  if (http_session->ssl_client_context()) {
    http_session->ssl_client_context()->ClearClientCertificateIfNeeded(
        host, certificate);
  }
}

void NetworkContext::FlushMatchingCachedClientCert(
    const scoped_refptr<net::X509Certificate>& certificate) {
  net::HttpNetworkSession* http_session =
      url_request_context_->http_transaction_factory()->GetSession();
  DCHECK(http_session);
  if (http_session->ssl_client_context()) {
    http_session->ssl_client_context()->ClearMatchingClientCertificate(
        certificate);
  }
}

void NetworkContext::FlushClientCertCache() {
  net::HttpNetworkSession* http_session =
      url_request_context_->http_transaction_factory()->GetSession();
  DCHECK(http_session);
  if (http_session->ssl_client_context()) {
    http_session->ssl_client_context()->OnClientCertStoreChanged();
  }
}

void NetworkContext::RestrictNetworkForIds(
    std::vector<mojom::IdAndAllowlistedPatternsPtr> ids_to_patterns,
    RestrictNetworkForIdsCallback callback) {
  auto parse_allowlist =
      [](std::optional<ConnectionAllowlist>& source,
         std::optional<std::string>& dest_endpoint,
         std::optional<
             std::set<std::unique_ptr<url_pattern::SimpleUrlPatternMatcher>>>&
             dest_patterns,
         ConnectionAllowlist::RedirectBehavior& dest_redirect_behavior) {
        if (!source) {
          return;
        }
        dest_endpoint = source->reporting_endpoint;
        dest_redirect_behavior = source->redirect_behavior;
        dest_patterns.emplace();
        for (const std::string& pattern : source->allowlist) {
          // TODO(crbug.com/447954811): We can safely DCHECK here, as we've done
          // pattern validation already while validating the header's syntax.
          // That said, parsing the pattern twice has performance overhead, and
          // it would be ideal to change our infrastructure to allow passing a
          // SimpleUrlPatternMatcher directly rather than creating it anew here.
          auto matcher = url_pattern::SimpleUrlPatternMatcher::Create(
              pattern, /*base_url=*/nullptr);

          DCHECK(matcher.has_value());
          dest_patterns->insert(std::move(matcher.value()));
        }
      };

  for (auto& entry : ids_to_patterns) {
    const base::UnguessableToken& network_restrictions_id =
        entry->network_restrictions_id;

    // Accessing `network_restrictions_ids_[network_restrictions_id]` here
    // ensures that if it's not already present in the set, it's
    // default-constructed. This is important, as an empty
    // `entry->allowlists.enforced->allowlist` represents complete network
    // revocation.
    NetworkRestriction& restriction =
        network_restrictions_ids_[network_restrictions_id];
    restriction.response_url = entry->allowlists.response_url;
    restriction.reporting_source = entry->allowlists.reporting_source;

    parse_allowlist(entry->allowlists.enforced,
                    restriction.enforced_reporting_endpoint,
                    restriction.enforced_allowlisted_patterns,
                    restriction.enforced_redirect_behavior);
    parse_allowlist(entry->allowlists.report_only,
                    restriction.report_only_reporting_endpoint,
                    restriction.report_only_allowlisted_patterns,
                    restriction.report_only_redirect_behavior);
  }

  if (callback) {
    std::move(callback).Run();
  }
}

void NetworkContext::ClearNetworkRestrictions(
    const std::vector<base::UnguessableToken>& network_restrictions_ids) {
  for (const auto& network_restrictions_id : network_restrictions_ids) {
    network_restrictions_ids_.erase(network_restrictions_id);
  }
}

void NetworkContext::Prefetch(
    int32_t request_id,
    uint32_t options,
    const ResourceRequest& request,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    const base::UnguessableToken& network_restrictions_id) {
  if (!prefetch_enabled_) {
    return;
  }

  // Retrieve the NAK for Connection Allowlist enforcement.
  const net::NetworkAnonymizationKey& nak =
      request.trusted_params.has_value()
          ? request.trusted_params->isolation_info.network_anonymization_key()
          : net::NetworkAnonymizationKey::CreateTransient();

  // TODO(crbug.com/536913419): Handle the Connection Allowlist redirects
  // directive correctly, rather than cancelling the whole prefetch.
  if (!IsNetworkForNetworkRestrictionsIdAndUrlAllowed(
          network_restrictions_id, request.url, nak, /*is_redirect=*/true)) {
    return;
  }

  // The UrlLoaderFactory used below is different from the one used for
  // subresources, which is normally where enforcement for Connection Allowlist
  // happens. Enforce here instead before delegating the request to the
  // prefetch-specific factory. This request is also an initial prefetch and
  // not a redirect, so perform the allowlist check accordingly.
  if (!IsNetworkForNetworkRestrictionsIdAndUrlAllowed(
          network_restrictions_id, request.url, nak, /*is_redirect=*/false)) {
    return;
  }

  PrefetchURLLoaderClient* client = prefetch_cache_->Emplace(request);
  if (!client) {
    // This is normal if we already have a prefetch in progress for the {NIK,
    // URL} combination.
    return;
  }

  prefetch_url_loader_factory_remote_->CreateLoaderAndStart(
      client->GetURLLoaderPendingReceiver(), request_id, options, request,
      client->BindNewPipeAndPassRemote(), traffic_annotation);
}

void NetworkContext::GetDeviceBoundSessionManager(
    mojo::PendingReceiver<network::mojom::DeviceBoundSessionManager>
        device_bound_session_manager) {
  if (device_bound_session_manager_) {
    device_bound_session_manager_->AddReceiver(
        std::move(device_bound_session_manager));
  }
}

void NetworkContext::AddQuicHints(
    const std::vector<url::SchemeHostPort>& origins,
    const net::NetworkAnonymizationKey& network_anonymization_key) {
  CHECK(url_request_context_);

  for (const auto& origin : origins) {
    url::CanonHostInfo host_info;
    std::string canonical_host(
        net::CanonicalizeHost(origin.host(), &host_info));
    if (!host_info.IsIPAddress() &&
        !net::IsCanonicalizedHostCompliant(canonical_host)) {
      LOG(ERROR) << "Invalid QUIC hint host: " << origin.host();
      continue;
    }

    // The AlternativeService hostname can be used to signal a change of host.
    // By passing in an empty host, the origin's host will be used.
    net::AlternativeService alternative_service(net::NextProto::kProtoQUIC, "",
                                                origin.port());

    url::SchemeHostPort canonical_origin(url::kHttpsScheme, canonical_host,
                                         origin.port());
    url_request_context_->http_server_properties()->SetQuicAlternativeService(
        canonical_origin, network_anonymization_key, alternative_service,
        base::Time::Max(), quic::ParsedQuicVersionVector());
  }
}

void NetworkContext::AddWildcardQuicHints(
    std::vector<mojom::WildcardQuicHintPtr> hints) {
  if (!url_request_context_ ||
      !url_request_context_->http_server_properties()) {
    return;
  }

  for (const auto& hint : hints) {
    if (!hint || hint->host_suffix.empty()) {
      continue;
    }
    if (hint->port == 0 ||
        !net::IsPortAllowedForScheme(hint->port, url::kHttpsScheme)) {
      DVLOG(1) << "Invalid or restricted QUIC hint port: " << hint->port;
      continue;
    }

    std::string_view domain = hint->host_suffix;
    if (domain.starts_with("*.")) {
      domain.remove_prefix(2);
    } else if (domain.starts_with(".")) {
      domain.remove_prefix(1);
    } else {
      DVLOG(1) << "Invalid QUIC hint suffix (missing wildcard prefix): "
               << hint->host_suffix;
      continue;
    }

    if (domain.empty()) {
      DVLOG(1) << "Invalid QUIC hint suffix: " << hint->host_suffix;
      continue;
    }

    url::CanonHostInfo host_info;
    std::string canonical_domain = net::CanonicalizeHost(domain, &host_info);
    if (canonical_domain.ends_with(".")) {
      canonical_domain.pop_back();
    }

    if (canonical_domain.empty() || host_info.IsIPAddress() ||
        !net::IsCanonicalizedHostCompliant(canonical_domain)) {
      DVLOG(1) << "Invalid QUIC hint suffix: " << hint->host_suffix;
      continue;
    }

    std::string canonical_suffix = base::StrCat({".", canonical_domain});
    url_request_context_->http_server_properties()
        ->SetKnownQuicAlternativeService(canonical_suffix, hint->port,
                                         hint->port,
                                         /*is_suffix=*/true);
  }
}

void NetworkContext::SetTryQuicByDefault(bool enable) {
  if (!url_request_context_ ||
      !url_request_context_->http_server_properties()) {
    return;
  }
  url_request_context_->http_server_properties()->SetTryQuicByDefault(enable);
}

bool NetworkContext::IsNetworkForNetworkRestrictionsIdAndUrlAllowed(
    const base::UnguessableToken& network_restrictions_id,
    const GURL& url,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    bool is_redirect) {
  if (!base::FeatureList::IsEnabled(network::features::kConnectionAllowlists)) {
    return true;
  }

  // If network hasn't been revoked for the network restrictions ID, it's
  // allowed. Likewise, local schemes that reach this point should be excluded
  // as they don't generate network requests.
  if (network_restrictions_ids_.empty() || url.SchemeIsLocal()) {
    return true;
  }
  auto it = network_restrictions_ids_.find(network_restrictions_id);
  if (it == network_restrictions_ids_.end()) {
    return true;
  }

  const NetworkRestriction& restriction = it->second;

  // For connection allowlist feature, network_restrictions_ids_ map contains
  // the allowed URL Patterns.
  // If there are no allowlisted URLs then it is assumed that all network URLs
  // are restricted.
  auto restriction_allowed = [&](const NetworkRestriction& r, bool enforced) {
    const auto& patterns = enforced ? r.enforced_allowlisted_patterns
                                    : r.report_only_allowlisted_patterns;
    if (!patterns.has_value()) {
      // A null pattern implies the response does not contain the corresponding
      // header at all. No restriction should be applied.
      return true;
    }

    if (is_redirect) {
      // For redirects, the URL is not matched against the patterns. Connection
      // allowlist's redirect directive specifies the behavior.
      const auto& redirect_behavior = enforced
                                          ? r.enforced_redirect_behavior
                                          : r.report_only_redirect_behavior;
      return redirect_behavior == ConnectionAllowlist::RedirectBehavior::kAllow;
    }

    // Match the URL against the patterns.
    return std::ranges::any_of(
        *patterns,
        [&url](const std::unique_ptr<url_pattern::SimpleUrlPatternMatcher>&
                   matcher) { return matcher->Match(url); });
  };

  // First, check against the report-only allowlist, reporting violations:
  if (restriction.report_only_reporting_endpoint.has_value() &&
      !restriction_allowed(restriction, /*enforced=*/false)) {
    QueueConnectionAllowlistReport(
        restriction.response_url, url, network_anonymization_key,
        restriction.reporting_source,
        *restriction.report_only_reporting_endpoint, /*enforced=*/false);
  }

  // Then, match against the enforced allowlist, and return `false` to cancel
  // the request if a violation is found:
  if (!restriction_allowed(restriction, /*enforced=*/true)) {
    if (restriction.enforced_reporting_endpoint.has_value()) {
      QueueConnectionAllowlistReport(
          restriction.response_url, url, network_anonymization_key,
          restriction.reporting_source,
          *restriction.enforced_reporting_endpoint, /*enforced=*/true);
    }
    return false;
  }

  return true;
}

bool NetworkContext::IsHostResolutionForNetworkRestrictionsIdAndHostAllowed(
    const base::UnguessableToken& network_restrictions_id,
    const mojom::HostResolverHost& host,
    const net::NetworkAnonymizationKey& network_anonymization_key) {
  if (!base::FeatureList::IsEnabled(network::features::kConnectionAllowlists)) {
    return true;
  }

  auto it = network_restrictions_ids_.find(network_restrictions_id);
  if (it == network_restrictions_ids_.end()) {
    return true;
  }

  std::string host_fragment = host.is_host_port_pair()
                                  ? host.get_host_port_pair().host()
                                  : host.get_scheme_host_port().host();
  GURL synthetic_url = GURL(base::StrCat(
      {url::kHttpsScheme, url::kStandardSchemeSeparator, host_fragment}));
  if (!synthetic_url.is_valid()) {
    return false;
  }

  // Per
  // https://wicg.github.io/connection-allowlists/#abstract-opdef-match-a-host-to-a-connection-allowlist,
  // we need to match `synthetic_url` against a host-only variant against each
  // URLPattern corresponding to `nonce`.
  const NetworkRestriction& restriction = it->second;

  auto restriction_allowed = [&](const NetworkRestriction& r, bool enforced) {
    const auto& patterns = enforced ? r.enforced_allowlisted_patterns
                                    : r.report_only_allowlisted_patterns;
    return !patterns.has_value() ||
           std::ranges::any_of(
               *patterns,
               [&synthetic_url](
                   const std::unique_ptr<url_pattern::SimpleUrlPatternMatcher>&
                       matcher) {
                 return matcher->HostOnlyMatch(synthetic_url);
               });
  };

  // First, check against the report-only allowlist, reporting violations:
  if (restriction.report_only_reporting_endpoint.has_value() &&
      !restriction_allowed(restriction, /*enforced=*/false)) {
    QueueConnectionAllowlistReport(restriction.response_url, synthetic_url,
                                   network_anonymization_key,
                                   restriction.reporting_source,
                                   *restriction.report_only_reporting_endpoint,
                                   /*enforced=*/false);
  }

  // Then, match against the enforced allowlist, and return `false` to cancel
  // the request if a violation is found:
  if (!restriction_allowed(restriction, /*enforced=*/true)) {
    if (restriction.enforced_reporting_endpoint.has_value()) {
      QueueConnectionAllowlistReport(restriction.response_url, synthetic_url,
                                     network_anonymization_key,
                                     restriction.reporting_source,
                                     *restriction.enforced_reporting_endpoint,
                                     /*enforced=*/true);
    }
    return false;
  }

  // If we didn't block the request via the enforcement check directly above,
  // it should be allowed:
  return true;
}

void NetworkContext::InitializePrefetchURLLoaderFactory() {
  TRACE_EVENT0("loading", "NetworkContext::InitializePrefetchURLLoaderFactory");
  auto pending_receiver =
      prefetch_url_loader_factory_remote_.BindNewPipeAndPassReceiver();
  CreateURLLoaderFactory(std::move(pending_receiver),
                         CreateURLLoaderFactoryParamsForPrefetch());
}

GURL NetworkContext::GetNetworkRestrictionResponseUrlForTesting(
    const base::UnguessableToken& network_restrictions_id) const {
  auto it = network_restrictions_ids_.find(network_restrictions_id);
  if (it == network_restrictions_ids_.end()) {
    return GURL();
  }
  return it->second.response_url;
}

void NetworkContext::SetVariationsHeaders(
    variations::mojom::VariationsHeadersPtr variations_headers) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  variations_headers_ = std::move(variations_headers);
}


bool NetworkContext::HasCookieAccessForDeviceBoundSession(
    const net::device_bound_sessions::CookieAccessCheckParams& params) {
  if (!cookie_manager_) {
    return false;
  }
  return cookie_manager_->cookie_settings().IsFullCookieAccessAllowed(
      params.provider_origin->GetURL(),
      net::SiteForCookies::FromOrigin(*params.relying_party_origin),
      *params.relying_party_origin,
      {net::CookieSettingOverride::kStorageAccessGrantEligible},
      // TODO(crbug.com/353772143): update once partitioned cookies are
      // supported. DBSC does not support cookie partition yet.
      /*cookie_partition_key=*/std::nullopt);
}

void NetworkContext::OnInvalidationFiltersLoaded(
    LogicalInvalidationStore::LoadResult result,
    std::vector<net::HttpCache::InvalidationFilter> loaded_filters) {
  net::HttpCache* cache =
      url_request_context_->http_transaction_factory()->GetCache();
  if (!cache) {
    return;
  }

  // 1. Determine and save the final list of filters.
  if (logical_invalidation_store_) {
    // Skip saving if no filters were added or removed during load, avoiding a
    // redundant startup write (and avoiding overwriting an unparsable file
    // with an empty list).
    const bool skipped =
        pending_additions_.empty() && pending_removals_.empty();
    base::UmaHistogramBoolean(
        "Net.HttpCache.LogicalInvalidation.StartupSaveSkipped", skipped);
    if (!skipped) {
      std::vector<net::HttpCache::InvalidationFilter> filters_to_save(
          loaded_filters);
      filters_to_save.append_range(pending_additions_);
      std::erase_if(filters_to_save, [&](const auto& filter) {
        return std::ranges::contains(pending_removals_, filter);
      });
      std::ranges::sort(filters_to_save, std::less<>());
      auto [first, last] =
          std::ranges::unique(filters_to_save, std::equal_to<>());
      filters_to_save.erase(first, last);
      logical_invalidation_store_->Save(std::move(filters_to_save));
    }
  }

  // 2. Determine which loaded filters need to be registered logically in
  // memory.
  std::vector<net::HttpCache::InvalidationFilter> filters_to_register_logically;
  for (auto& filter : loaded_filters) {
    if (!std::ranges::contains(pending_removals_, filter) &&
        !std::ranges::contains(pending_additions_, filter)) {
      filters_to_register_logically.push_back(std::move(filter));
    }
  }

  // 4. Register the logical filters in memory before starting physical purges.
  for (auto& filter : filters_to_register_logically) {
    filter.was_loaded_from_disk = true;
    cache->AddInvalidationFilter(filter);
  }

  // 5. Start background physical purges for newly registered filters.
  for (const auto& filter : filters_to_register_logically) {
    mojom::ClearDataFilterPtr filter_ptr = mojom::ClearDataFilter::New();
    filter_ptr->type =
        (filter.filter_type == net::UrlFilterType::kTrueIfMatches)
            ? mojom::ClearDataFilter_Type::DELETE_MATCHES
            : mojom::ClearDataFilter_Type::KEEP_MATCHES;
    filter_ptr->origins.assign_range(filter.origins);
    filter_ptr->domains.assign_range(filter.domains);

    auto logical_cleanup_done_callback = base::BindOnce(
        &RemoveInvalidationFilterCallback, weak_factory_.GetWeakPtr(), filter);

    StartHttpCacheDataRemover(std::move(filter_ptr), filter.begin_time,
                              filter.end_time,
                              std::move(logical_cleanup_done_callback));
  }

  // 6. Set state to loaded and clear queues.
  initial_filters_loaded_ = true;
  pending_additions_.clear();
  pending_removals_.clear();
}

void NetworkContext::StartHttpCacheDataRemover(
    mojom::ClearDataFilterPtr filter,
    base::Time start_time,
    base::Time end_time,
    base::OnceClosure done_callback) {
  http_cache_data_removers_.push_back(HttpCacheDataRemover::CreateAndStart(
      url_request_context_, std::move(filter), start_time, end_time,
      base::BindOnce(&NetworkContext::OnHttpCacheCleared,
                     base::Unretained(this), std::move(done_callback))));
}

void NetworkContext::UpdatePersistenceQueueOrSave(
    const net::HttpCache::InvalidationFilter& filter,
    std::vector<net::HttpCache::InvalidationFilter>* pending_queue,
    base::OnceClosure callback) {
  if (!initial_filters_loaded_) {
    pending_queue->push_back(filter);
    if (callback) {
      std::move(callback).Run();
    }
    return;
  }
  if (logical_invalidation_store_) {
    net::HttpCache* cache =
        url_request_context_->http_transaction_factory()->GetCache();
    if (cache) {
      logical_invalidation_store_->Save(cache->invalidation_filters(),
                                        std::move(callback));
      return;
    }
  }
  if (callback) {
    std::move(callback).Run();
  }
}

void NetworkContext::OnLogicalFilterAdded(
    const net::HttpCache::InvalidationFilter& filter,
    base::OnceClosure callback) {
  UpdatePersistenceQueueOrSave(filter, &pending_additions_,
                               std::move(callback));
}

void NetworkContext::OnLogicalFilterRemoved(
    const net::HttpCache::InvalidationFilter& filter) {
  UpdatePersistenceQueueOrSave(filter, &pending_removals_);
}

}  // namespace network
