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

#include "content/browser/devtools/protocol/network_handler.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <memory>
#include <string_view>
#include <utility>
#include <variant>

#include "base/barrier_closure.h"
#include "base/base64.h"
#include "base/check_deref.h"
#include "base/command_line.h"
#include "base/containers/queue.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/i18n/i18n_constants.h"
#include "base/i18n/icu_string_conversions.h"
#include "base/memory/raw_ptr.h"
#include "base/process/process_handle.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_view_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_io_context.h"
#include "content/browser/devtools/devtools_stream_file.h"
#include "content/browser/devtools/devtools_stream_pipe.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/devtools/protocol/devtools_network_resource_loader.h"
#include "content/browser/devtools/protocol/handler_helpers.h"
#include "content/browser/devtools/protocol/network.h"
#include "content/browser/devtools/protocol/page.h"
#include "content/browser/devtools/protocol/protocol.h"
#include "content/browser/devtools/protocol/security.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/loader/url_loader_factory_utils.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_csp_context.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_params_helper.h"
#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/browser/web_package/signed_exchange_error.h"
#include "content/common/web_package/signed_exchange_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "ipc/constants.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/cert/ct_policy_status.h"
#include "net/cert/ct_sct_to_string.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_partition_key.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/cookies/cookie_util.h"
#include "net/filter/source_stream_type.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "net/ssl/ssl_cipher_suite_names.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/url_request/referrer_policy.h"
#include "services/network/public/cpp/data_element.h"
#include "services/network/public/cpp/devtools_observer_util.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/client_security_state.mojom-shared.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "services/network/public/mojom/device_bound_sessions.mojom.h"
#include "services/network/public/mojom/devtools_observer.mojom.h"
#include "services/network/public/mojom/http_raw_headers.mojom.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "services/network/public/mojom/service_worker_router_info.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
#include "third_party/abseil-cpp/absl/functional/overload.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "url/third_party/mozilla/url_parse.h"

namespace content {
namespace protocol {

namespace {

using GetCookiesCallback = Network::Backend::GetCookiesCallback;
using GetAllCookiesCallback = Network::Backend::GetAllCookiesCallback;
using SetCookieCallback = Network::Backend::SetCookieCallback;
using SetCookiesCallback = Network::Backend::SetCookiesCallback;
using DeleteCookiesCallback = Network::Backend::DeleteCookiesCallback;
using ClearBrowserCookiesCallback =
    Network::Backend::ClearBrowserCookiesCallback;

static constexpr char kInvalidCookieFields[] = "Invalid cookie fields";

Network::CertificateTransparencyCompliance SerializeCTPolicyCompliance(
    net::ct::CTPolicyCompliance ct_compliance) {
  switch (ct_compliance) {
    case net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS:
      return Network::CertificateTransparencyComplianceEnum::Compliant;
    case net::ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS:
    case net::ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS:
      return Network::CertificateTransparencyComplianceEnum::NotCompliant;
    case net::ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY:
    case net::ct::CTPolicyCompliance::
        CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE:
      return Network::CertificateTransparencyComplianceEnum::Unknown;
    case net::ct::CTPolicyCompliance::CT_POLICY_COUNT:
      NOTREACHED();
  }
  NOTREACHED();
}

namespace {
Network::CookiePriority BuildCookiePriority(net::CookiePriority priority) {
  switch (priority) {
    case net::CookiePriority::COOKIE_PRIORITY_HIGH:
      return Network::CookiePriorityEnum::High;
    case net::CookiePriority::COOKIE_PRIORITY_MEDIUM:
      return Network::CookiePriorityEnum::Medium;
    case net::CookiePriority::COOKIE_PRIORITY_LOW:
      return Network::CookiePriorityEnum::Low;
  }
}
Network::CookieSourceScheme BuildCookieSourceScheme(
    net::CookieSourceScheme scheme) {
  switch (scheme) {
    case net::CookieSourceScheme::kUnset:
      return Network::CookieSourceSchemeEnum::Unset;
    case net::CookieSourceScheme::kNonSecure:
      return Network::CookieSourceSchemeEnum::NonSecure;
    case net::CookieSourceScheme::kSecure:
      return Network::CookieSourceSchemeEnum::Secure;
  }
}
std::optional<Network::CookieSameSite> BuildCookieSameSite(
    net::CookieSameSite same_site) {
  switch (same_site) {
    case net::CookieSameSite::STRICT_MODE:
      return Network::CookieSameSiteEnum::Strict;
    case net::CookieSameSite::LAX_MODE:
      return Network::CookieSameSiteEnum::Lax;
    case net::CookieSameSite::NO_RESTRICTION:
      return Network::CookieSameSiteEnum::None;
    case net::CookieSameSite::UNSPECIFIED:
      return std::nullopt;
  }
}

std::unique_ptr<Network::CookiePartitionKey> BuildCookiePartitionKey(
    const std::string& top_level_site,
    bool has_cross_site_ancestor) {
  return Network::CookiePartitionKey::Create()
      .SetTopLevelSite(top_level_site)
      .SetHasCrossSiteAncestor(has_cross_site_ancestor)
      .Build();
}

}  // namespace

std::unique_ptr<Network::Cookie> BuildCookie(
    const net::CanonicalCookie& cookie) {
  DCHECK(cookie.ExpiryDate().is_null() || !cookie.ExpiryDate().is_inf());
  std::unique_ptr<Network::Cookie> devtools_cookie =
      Network::Cookie::Create()
          .SetName(cookie.Name())
          .SetValue(cookie.Value())
          .SetDomain(cookie.Domain())
          .SetPath(cookie.Path())
          .SetExpires(cookie.ExpiryDate().is_null()
                          ? -1
                          : cookie.ExpiryDate().InSecondsFSinceUnixEpoch())
          .SetSize(cookie.Name().length() + cookie.Value().length())
          .SetHttpOnly(cookie.IsHttpOnly())
          .SetSecure(cookie.SecureAttribute())
          .SetSession(!cookie.IsPersistent())
          .SetPriority(BuildCookiePriority(cookie.Priority()))
          .SetSourceScheme(BuildCookieSourceScheme(cookie.SourceScheme()))
          .SetSourcePort(cookie.SourcePort())
          .Build();

  std::optional<Network::CookieSourceScheme> maybe_same_site =
      BuildCookieSameSite(cookie.SameSite());
  if (maybe_same_site) {
    devtools_cookie->SetSameSite(*maybe_same_site);
  }
  std::optional<net::CookiePartitionKey> partition_key = cookie.PartitionKey();
  if (partition_key) {
    if (partition_key->IsSerializeable()) {
      base::expected<net::CookiePartitionKey::SerializedCookiePartitionKey,
                     std::string>
          key_serialized_result =
              net::CookiePartitionKey::Serialize(partition_key);
      CHECK(key_serialized_result.has_value());
      devtools_cookie->SetPartitionKey(BuildCookiePartitionKey(
          key_serialized_result->TopLevelSite(),
          key_serialized_result->has_cross_site_ancestor()));
    } else {
      devtools_cookie->SetPartitionKeyOpaque(partition_key->site().opaque());
      // IsSerializeable may return false when the partition key's site is not
      // opaque since we introduced nonce-based cookie partitioning in
      // https://crrev.com/c/3285244.
      // TODO(1225444,1229638): Surface nonce-based cookie partition keys in
      // DevTools.
    }
  }
  return devtools_cookie;
}

class CookieRetrieverNetworkService
    : public base::RefCounted<CookieRetrieverNetworkService> {
 public:
  static void Retrieve(network::mojom::CookieManager* cookie_manager,
                       const std::vector<GURL>& urls,
                       const net::NetworkIsolationKey& network_isolation_key,
                       const net::SiteForCookies& site_for_cookies,
                       std::unique_ptr<GetCookiesCallback> callback) {
    scoped_refptr<CookieRetrieverNetworkService> self =
        new CookieRetrieverNetworkService(std::move(callback));
    net::CookieOptions cookie_options = net::CookieOptions::MakeAllInclusive();
    for (const auto& url : urls) {
      cookie_manager->GetCookieList(
          url, cookie_options,
          net::CookiePartitionKeyCollection(
              net::CookiePartitionKey::FromNetworkIsolationKey(
                  network_isolation_key, site_for_cookies,
                  net::SchemefulSite(url), /*main_frame_navigation=*/false)),
          base::BindOnce(&CookieRetrieverNetworkService::GotCookies, self));
    }
  }

 private:
  friend class base::RefCounted<CookieRetrieverNetworkService>;

  CookieRetrieverNetworkService(std::unique_ptr<GetCookiesCallback> callback)
      : callback_(std::move(callback)) {}

  void GotCookies(const net::CookieAccessResultList& cookies,
                  const net::CookieAccessResultList& excluded_cookies) {
    for (const auto& cookie_with_access_result : cookies) {
      const net::CanonicalCookie& cookie = cookie_with_access_result.cookie;

      base::expected<net::CookiePartitionKey::SerializedCookiePartitionKey,
                     std::string>
          serialized_partition_key =
              net::CookiePartitionKey::Serialize(cookie.PartitionKey());
      // We could be missing cookies that have unserializable partition key.
      // Reference the CookiePartitionKey::IsSerializable docs for more details.
      // Default to true for has_cross_site_ancestor if the partition key is
      // unserializable to avoid false positives.
      std::string key = base::StringPrintf(
          "%s::%s::%s::%d::%s::%d", cookie.Name().c_str(),
          cookie.Domain().c_str(), cookie.Path().c_str(),
          cookie.SecureAttribute(),
          serialized_partition_key.has_value()
              ? serialized_partition_key->TopLevelSite().c_str()
              : serialized_partition_key.error().c_str(),
          serialized_partition_key.has_value()
              ? serialized_partition_key->has_cross_site_ancestor()
              : true);
      all_cookies_.emplace(std::move(key), cookie);
    }
  }

  ~CookieRetrieverNetworkService() {
    auto cookies = std::make_unique<Array<Network::Cookie>>();
    for (const auto& entry : all_cookies_) {
      cookies->emplace_back(BuildCookie(entry.second));
    }
    callback_->sendSuccess(std::move(cookies));
  }

  std::unique_ptr<GetCookiesCallback> callback_;
  absl::flat_hash_map<std::string, net::CanonicalCookie> all_cookies_;
};

namespace {
std::vector<net::CanonicalCookie> FilterCookies(
    const std::vector<net::CanonicalCookie>& cookies,
    const std::optional<std::string>& name,
    const std::optional<std::string>& normalized_domain,
    const std::optional<std::string>& path,
    const Network::CookiePartitionKey* partition_key,
    bool filter_by_partition_key) {
  std::vector<net::CanonicalCookie> result;

  for (const auto& cookie : cookies) {
    if (name.has_value() && cookie.Name() != name.value()) {
      continue;
    }
    if (normalized_domain.has_value() &&
        cookie.Domain() != normalized_domain.value()) {
      continue;
    }
    if (path.has_value() && !path.value().empty() &&
        cookie.Path() != path.value()) {
      continue;
    }

    if (filter_by_partition_key) {
      if (!!cookie.PartitionKey() != !!partition_key) {
        continue;
      }

      if (cookie.PartitionKey().has_value()) {
        base::expected<net::CookiePartitionKey::SerializedCookiePartitionKey,
                       std::string>
            serialized_result =
                net::CookiePartitionKey::Serialize(cookie.PartitionKey());

        if (!serialized_result.has_value() ||
            (serialized_result->TopLevelSite() !=
             const_cast<Network::CookiePartitionKey*>(partition_key)
                 ->GetTopLevelSite())) {
          continue;
        }

        if (serialized_result->has_cross_site_ancestor() !=
            const_cast<Network::CookiePartitionKey*>(partition_key)
                ->GetHasCrossSiteAncestor()) {
          continue;
        }
      }
    }

    result.push_back(cookie);
  }

  return result;
}

void DeleteFilteredCookies(
    network::mojom::CookieManager* cookie_manager,
    const std::optional<std::string>& name,
    const std::optional<std::string>& normalized_domain,
    const std::optional<std::string>& path,
    const Network::CookiePartitionKey* partition_key,
    bool filter_by_partition_key,
    base::RepeatingCallback<bool(const net::CanonicalCookie&)> filter,
    base::OnceClosure success_callback,
    const std::vector<net::CanonicalCookie>& cookies) {
  std::vector<net::CanonicalCookie> filtered_list =
      FilterCookies(cookies, name, normalized_domain, path, partition_key,
                    filter_by_partition_key);

  std::erase_if(filtered_list, [&](const net::CanonicalCookie& cookie) {
    return !filter.Run(cookie);
  });

  base::RepeatingClosure barrier_closure =
      base::BarrierClosure(filtered_list.size(), std::move(success_callback));

  for (auto& cookie : filtered_list) {
    cookie_manager->DeleteCanonicalCookie(
        cookie, base::BindOnce([](base::RepeatingClosure callback,
                                  bool) { callback.Run(); },
                               barrier_closure));
  }
}

std::variant<net::CookieSourceScheme, Response> GetSourceSchemeFromProtocol(
    const std::string& source_scheme) {
  if (source_scheme == Network::CookieSourceSchemeEnum::Unset) {
    return net::CookieSourceScheme::kUnset;
  } else if (source_scheme == Network::CookieSourceSchemeEnum::NonSecure) {
    return net::CookieSourceScheme::kNonSecure;
  } else if (source_scheme == Network::CookieSourceSchemeEnum::Secure) {
    return net::CookieSourceScheme::kSecure;
  }
  return Response::InvalidParams("Invalid cookie source scheme");
}

std::variant<int, Response> GetCookieSourcePort(int source_port) {
  // Only {url::PORT_UNSPECIFIED, [1,65535]} are valid.
  if (source_port == url::PORT_UNSPECIFIED ||
      (source_port >= 1 && source_port <= 65535)) {
    return source_port;
  }

  return Response::InvalidParams("Invalid source port");
}

}  // namespace

std::variant<std::unique_ptr<net::CanonicalCookie>, Response>
MakeCookieFromProtocolValues(const std::string& name,
                             const std::string& value,
                             const std::string& url_spec,
                             const std::string& domain,
                             const std::string& path,
                             bool secure,
                             bool http_only,
                             const std::string& same_site,
                             double expires,
                             const std::string& priority,
                             const std::optional<std::string>& source_scheme,
                             const std::optional<int>& source_port,
                             const Network::CookiePartitionKey* partition_key) {
  std::string normalized_domain = domain;

  if (url_spec.empty() && domain.empty()) {
    return Response::InvalidParams(
        "At least one of the url or domain needs to be specified");
  }

  GURL source_url;
  if (!url_spec.empty()) {
    source_url = GURL(url_spec);
    if (!source_url.SchemeIsHTTPOrHTTPS()) {
      return Response::InvalidParams("URL must have scheme http or https");
    }

    secure = secure || source_url.SchemeIsCryptographic();
    if (normalized_domain.empty()) {
      normalized_domain = source_url.GetHost();
    }
  }

  std::string url_host = normalized_domain;
  if (!normalized_domain.empty()) {
    // The value of |url_host| may have trickled down from a cookie domain,
    // where leading periods are legal. However, since we want to use it as a
    // URL host, we must the leading period if it exists.
    if (normalized_domain[0] == '.') {
      url_host.erase(0, 1);
    }
    // If there is no leading period, clear out |normalized_domain|, but keep
    // the value of |url_host|. CreateSanitizedCookie will determine the proper
    // domain from the URL we construct with |url_host|.
    else {
      normalized_domain = "";
    }
  }
  GURL url = GURL((secure ? "https://" : "http://") + url_host);

  base::Time expiration_date;
  if (expires >= 0) {
    expiration_date = expires ? base::Time::FromSecondsSinceUnixEpoch(expires)
                              : base::Time::UnixEpoch();
  }

  net::CookieSameSite css = net::CookieSameSite::UNSPECIFIED;
  if (same_site == Network::CookieSameSiteEnum::Lax) {
    css = net::CookieSameSite::LAX_MODE;
  }
  if (same_site == Network::CookieSameSiteEnum::Strict) {
    css = net::CookieSameSite::STRICT_MODE;
  }
  if (same_site == Network::CookieSameSiteEnum::None) {
    css = net::CookieSameSite::NO_RESTRICTION;
  }

  net::CookiePriority cp = net::CookiePriority::COOKIE_PRIORITY_MEDIUM;
  if (priority == Network::CookiePriorityEnum::High) {
    cp = net::CookiePriority::COOKIE_PRIORITY_HIGH;
  } else if (priority == Network::CookiePriorityEnum::Medium) {
    cp = net::CookiePriority::COOKIE_PRIORITY_MEDIUM;
  } else if (priority == Network::CookiePriorityEnum::Low) {
    cp = net::CookiePriority::COOKIE_PRIORITY_LOW;
  }

  std::optional<net::CookiePartitionKey> cookie_partition_key;
  if (partition_key && !const_cast<Network::CookiePartitionKey*>(partition_key)
                            ->GetTopLevelSite()
                            .empty()) {
    base::expected<net::CookiePartitionKey, std::string>
        deserialized_partition_key =
            net::CookiePartitionKey::FromUntrustedInput(
                const_cast<Network::CookiePartitionKey*>(partition_key)
                    ->GetTopLevelSite(),
                const_cast<Network::CookiePartitionKey*>(partition_key)
                    ->GetHasCrossSiteAncestor());
    if (!deserialized_partition_key.has_value()) {
      return Response::InvalidParams(
          "Deserializing cookie partition key failed");
    }
    cookie_partition_key = deserialized_partition_key.value();
  }
  // TODO(crbug.com/40188414) Add Partitioned to DevTools cookie structures.
  std::unique_ptr<net::CanonicalCookie> cookie =
      net::CanonicalCookie::CreateSanitizedCookie(
          url, name, value, normalized_domain, path, base::Time(),
          expiration_date, base::Time(), secure, http_only, css, cp,
          cookie_partition_key, /*status=*/nullptr);

  if (!cookie) {
    return Response::InvalidParams("Sanitizing cookie failed");
  }

  // Update the cookie's sourceScheme unless it's undefined in which case we'll
  // keep the value that was implied from `url` via CreateSanitizedCookie.
  if (source_scheme.has_value()) {
    auto cookie_source_scheme_or_error =
        GetSourceSchemeFromProtocol(source_scheme.value());
    if (std::holds_alternative<Response>(cookie_source_scheme_or_error)) {
      return std::get<Response>(std::move(cookie_source_scheme_or_error));
    }
    net::CookieSourceScheme cookie_source_scheme =
        std::get<net::CookieSourceScheme>(cookie_source_scheme_or_error);
    if (cookie->SecureAttribute() &&
        cookie_source_scheme == net::CookieSourceScheme::kNonSecure) {
      return Response::InvalidParams(
          "Secure attribute cannot be set for a cookie with an insecure source "
          "scheme");
    }

    cookie->SetSourceScheme(cookie_source_scheme);
  }

  // Update the cookie's port unless it's undefined in which case we'll
  // keep the value that was implied from `url` via CreateSanitizedCookie.
  if (source_port.has_value()) {
    auto cookie_source_port_or_error = GetCookieSourcePort(source_port.value());
    if (std::holds_alternative<Response>(cookie_source_port_or_error)) {
      return std::get<Response>(std::move(cookie_source_port_or_error));
    }
    int port_value = std::get<int>(cookie_source_port_or_error);

    // If the url has a port specified it must match the source_port value.
    // Otherwise this set cookie request is considered malformed.
    // Note: Default port values (https: 443, http: 80) are ignored. They will
    // be treated as if they were not specified.
    if (source_url.has_port() && source_url.IntPort() != port_value) {
      return Response::InvalidParams(
          "Source port does not match the url's specified port");
    }

    cookie->SetSourcePort(port_value);
  }

  return cookie;
}

std::vector<GURL> ComputeCookieURLs(
    RenderFrameHostImpl* frame_host,
    std::unique_ptr<Array<String>>& protocol_urls) {
  std::vector<GURL> urls;

  if (protocol_urls) {
    for (const std::string& url : *protocol_urls) {
      urls.emplace_back(url);
    }
  } else {
    base::queue<RenderFrameHostImpl*> queue;
    queue.push(frame_host);
    while (!queue.empty()) {
      RenderFrameHostImpl* node = queue.front();
      queue.pop();

      urls.push_back(node->GetLastCommittedURL());
      for (size_t i = 0; i < node->child_count(); ++i) {
        queue.push(node->child_at(i)->current_frame_host());
      }
    }
  }

  return urls;
}

String resourcePriority(net::RequestPriority priority) {
  switch (priority) {
    case net::MINIMUM_PRIORITY:
    case net::IDLE:
      return Network::ResourcePriorityEnum::VeryLow;
    case net::LOWEST:
      return Network::ResourcePriorityEnum::Low;
    case net::LOW:
      return Network::ResourcePriorityEnum::Medium;
    case net::MEDIUM:
      return Network::ResourcePriorityEnum::High;
    case net::HIGHEST:
      return Network::ResourcePriorityEnum::VeryHigh;
  }
  NOTREACHED();
}

String referrerPolicy(network::mojom::ReferrerPolicy referrer_policy) {
  switch (referrer_policy) {
    case network::mojom::ReferrerPolicy::kAlways:
      return Network::Request::ReferrerPolicyEnum::UnsafeUrl;
    case network::mojom::ReferrerPolicy::kDefault:
      return referrerPolicy(blink::ReferrerUtils::NetToMojoReferrerPolicy(
          blink::ReferrerUtils::GetDefaultNetReferrerPolicy()));
    case network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade:
      return Network::Request::ReferrerPolicyEnum::NoReferrerWhenDowngrade;
    case network::mojom::ReferrerPolicy::kNever:
      return Network::Request::ReferrerPolicyEnum::NoReferrer;
    case network::mojom::ReferrerPolicy::kOrigin:
      return Network::Request::ReferrerPolicyEnum::Origin;
    case network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin:
      return Network::Request::ReferrerPolicyEnum::OriginWhenCrossOrigin;
    case network::mojom::ReferrerPolicy::kSameOrigin:
      return Network::Request::ReferrerPolicyEnum::SameOrigin;
    case network::mojom::ReferrerPolicy::kStrictOrigin:
      return Network::Request::ReferrerPolicyEnum::StrictOrigin;
    case network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin:
      return Network::Request::ReferrerPolicyEnum::StrictOriginWhenCrossOrigin;
  }
  NOTREACHED();
}

String referrerPolicy(net::ReferrerPolicy referrer_policy) {
  return referrerPolicy(
      blink::ReferrerUtils::NetToMojoReferrerPolicy(referrer_policy));
}

String securityState(const GURL& url, const net::CertStatus& cert_status) {
  if (!url.SchemeIsCryptographic()) {
    // Some origins are considered secure even though they're not cryptographic,
    // so treat them as secure in the UI.
    if (network::IsUrlPotentiallyTrustworthy(url)) {
      return Security::SecurityStateEnum::Secure;
    }
    return Security::SecurityStateEnum::Insecure;
  }
  if (net::IsCertStatusError(cert_status)) {
    return Security::SecurityStateEnum::Insecure;
  }
  return Security::SecurityStateEnum::Secure;
}

std::optional<DevToolsURLLoaderInterceptor::InterceptionStage>
ToInterceptorStage(
    const protocol::Network::InterceptionStage& interceptor_stage) {
  if (interceptor_stage == protocol::Network::InterceptionStageEnum::Request) {
    return DevToolsURLLoaderInterceptor::kRequest;
  }
  if (interceptor_stage ==
      protocol::Network::InterceptionStageEnum::HeadersReceived) {
    return DevToolsURLLoaderInterceptor::kResponse;
  }
  return std::nullopt;
}

double timeDelta(base::TimeTicks time,
                 base::TimeTicks start,
                 double invalid_value = -1) {
  return time.is_null() ? invalid_value : (time - start).InMillisecondsF();
}

std::unique_ptr<Network::ResourceTiming> GetTiming(
    const net::LoadTimingInfo& load_timing) {
  if (load_timing.receive_headers_end.is_null()) {
    return nullptr;
  }

  const base::TimeTicks kNullTicks;
  auto timing =
      Network::ResourceTiming::Create()
          .SetRequestTime((load_timing.request_start - kNullTicks).InSecondsF())
          .SetProxyStart(timeDelta(load_timing.proxy_resolve_start,
                                   load_timing.request_start))
          .SetProxyEnd(timeDelta(load_timing.proxy_resolve_end,
                                 load_timing.request_start))
          .SetDnsStart(timeDelta(load_timing.connect_timing.domain_lookup_start,
                                 load_timing.request_start))
          .SetDnsEnd(timeDelta(load_timing.connect_timing.domain_lookup_end,
                               load_timing.request_start))
          .SetConnectStart(timeDelta(load_timing.connect_timing.connect_start,
                                     load_timing.request_start))
          .SetConnectEnd(timeDelta(load_timing.connect_timing.connect_end,
                                   load_timing.request_start))
          .SetSslStart(timeDelta(load_timing.connect_timing.ssl_start,
                                 load_timing.request_start))
          .SetSslEnd(timeDelta(load_timing.connect_timing.ssl_end,
                               load_timing.request_start))
          .SetWorkerStart(-1)
          .SetWorkerReady(-1)
          .SetWorkerFetchStart(timeDelta(load_timing.service_worker_fetch_start,
                                         load_timing.request_start))
          .SetWorkerRespondWithSettled(
              timeDelta(load_timing.service_worker_respond_with_settled,
                        load_timing.request_start))
          .SetSendStart(
              timeDelta(load_timing.send_start, load_timing.request_start))
          .SetSendEnd(
              timeDelta(load_timing.send_end, load_timing.request_start))
          .SetPushStart(
              timeDelta(load_timing.push_start, load_timing.request_start, 0))
          .SetPushEnd(
              timeDelta(load_timing.push_end, load_timing.request_start, 0))
          .SetReceiveHeadersStart(timeDelta(load_timing.receive_headers_start,
                                            load_timing.request_start))
          .SetReceiveHeadersEnd(timeDelta(load_timing.receive_headers_end,
                                          load_timing.request_start))
          .Build();

  if (base::FeatureList::IsEnabled(
          blink::features::kServiceWorkerStaticRouterTimingInfo)) {
    if (!load_timing.service_worker_router_evaluation_start.is_null()) {
      timing->SetWorkerRouterEvaluationStart(
          timeDelta(load_timing.service_worker_router_evaluation_start,
                    load_timing.request_start));
    }

    if (!load_timing.service_worker_cache_lookup_start.is_null()) {
      timing->SetWorkerCacheLookupStart(
          timeDelta(load_timing.service_worker_cache_lookup_start,
                    load_timing.request_start));
    }
  }

  return timing;
}

std::unique_ptr<Network::ConnectTiming> GetConnectTiming(
    const base::TimeTicks timestamp) {
  const base::TimeTicks kNullTicks;
  return Network::ConnectTiming::Create()
      .SetRequestTime((timestamp - kNullTicks).InSecondsF())
      .Build();
}

std::unique_ptr<base::DictValue> GetRawHeaders(
    const std::vector<network::mojom::HttpRawHeaderPairPtr>& headers) {
  auto headers_dict = std::make_unique<base::DictValue>();
  for (const auto& header : headers) {
    std::string header_value;
    if (!base::ConvertToUtf8AndNormalize(header->value, base::kCodepageLatin1,
                                         &header_value)) {
      // For response headers, the encoding could be anything, so conversion
      // might fail; in that case this is the most useful thing we can do.
      header_value = header->value;
    }
    // TODO(crbug.com/40228605): Once there's an API to do this without
    // a double lookup, switch do doing so.
    base::Value* value = headers_dict->Find(header->key);
    if (value) {
      *value = base::Value(value->GetString() + '\n' + header_value);
    } else {
      headers_dict->Set(header->key, header_value);
    }
  }
  return headers_dict;
}

String GetProtocol(const GURL& url,
                   const network::mojom::URLResponseHeadDevToolsInfo& info) {
  std::string protocol = info.alpn_negotiated_protocol;
  if (protocol.empty() || protocol == "unknown") {
    if (info.was_fetched_via_spdy) {
      protocol = "h2";
    } else if (url.SchemeIsHTTPOrHTTPS()) {
      protocol = "http";
      if (info.headers) {
        if (info.headers->GetHttpVersion() == net::HttpVersion(0, 9)) {
          protocol = "http/0.9";
        } else if (info.headers->GetHttpVersion() == net::HttpVersion(1, 0)) {
          protocol = "http/1.0";
        } else if (info.headers->GetHttpVersion() == net::HttpVersion(1, 1)) {
          protocol = "http/1.1";
        }
      }
    } else {
      protocol = url.GetScheme();
    }
  }
  return protocol;
}

bool GetPostData(
    const network::ResourceRequestBody& request_body,
    protocol::Array<protocol::Network::PostDataEntry>* data_entries,
    std::string* result) {
  const std::vector<network::DataElement>* elements = request_body.elements();
  if (elements->empty()) {
    return false;
  }
  for (const auto& element : *elements) {
    // TODO(caseq): Also support blobs.
    const auto* bytes_element = element.TryAs<network::DataElementBytes>();
    if (!bytes_element) {
      return false;
    }
    base::span<const uint8_t> bytes = bytes_element->bytes();
    auto data_entry = protocol::Network::PostDataEntry::Create().Build();
    data_entry->SetBytes(protocol::Binary::fromSpan(bytes));
    data_entries->push_back(std::move(data_entry));
    result->append(base::as_string_view(bytes));
  }
  return true;
}

String SignedExchangeErrorErrorFieldToString(SignedExchangeError::Field field) {
  switch (field) {
    case SignedExchangeError::Field::kSignatureSig:
      return Network::SignedExchangeErrorFieldEnum::SignatureSig;
    case SignedExchangeError::Field::kSignatureIintegrity:
      return Network::SignedExchangeErrorFieldEnum::SignatureIntegrity;
    case SignedExchangeError::Field::kSignatureCertUrl:
      return Network::SignedExchangeErrorFieldEnum::SignatureCertUrl;
    case SignedExchangeError::Field::kSignatureCertSha256:
      return Network::SignedExchangeErrorFieldEnum::SignatureCertSha256;
    case SignedExchangeError::Field::kSignatureValidityUrl:
      return Network::SignedExchangeErrorFieldEnum::SignatureValidityUrl;
    case SignedExchangeError::Field::kSignatureTimestamps:
      return Network::SignedExchangeErrorFieldEnum::SignatureTimestamps;
  }
  NOTREACHED();
}

std::unique_ptr<Network::SignedExchangeError> BuildSignedExchangeError(
    const SignedExchangeError& error) {
  std::unique_ptr<Network::SignedExchangeError> signed_exchange_error =
      Network::SignedExchangeError::Create().SetMessage(error.message).Build();
  if (error.field) {
    signed_exchange_error->SetSignatureIndex(error.field->first);
    signed_exchange_error->SetErrorField(
        SignedExchangeErrorErrorFieldToString(error.field->second));
  }
  return signed_exchange_error;
}

std::unique_ptr<Array<Network::SignedExchangeError>> BuildSignedExchangeErrors(
    const std::vector<SignedExchangeError>& errors) {
  auto signed_exchange_errors =
      std::make_unique<protocol::Array<Network::SignedExchangeError>>();
  for (const auto& error : errors) {
    signed_exchange_errors->emplace_back(BuildSignedExchangeError(error));
  }
  return signed_exchange_errors;
}

std::unique_ptr<Array<Network::SetCookieBlockedReason>>
GetProtocolBlockedSetCookieReason(net::CookieInclusionStatus status) {
  std::unique_ptr<Array<Network::SetCookieBlockedReason>> blockedReasons =
      std::make_unique<Array<Network::SetCookieBlockedReason>>();
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_SECURE_ONLY)) {
    blockedReasons->push_back(Network::SetCookieBlockedReasonEnum::SecureOnly);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SAMESITE_STRICT)) {
    if (status.HasSchemefulDowngradeWarning()) {
      blockedReasons->push_back(
          Network::SetCookieBlockedReasonEnum::SchemefulSameSiteStrict);
    } else {
      blockedReasons->push_back(
          Network::SetCookieBlockedReasonEnum::SameSiteStrict);
    }
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_LAX)) {
    if (status.HasSchemefulDowngradeWarning()) {
      blockedReasons->push_back(
          Network::SetCookieBlockedReasonEnum::SchemefulSameSiteLax);
    } else {
      blockedReasons->push_back(
          Network::SetCookieBlockedReasonEnum::SameSiteLax);
    }
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::
              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) {
    if (status.HasSchemefulDowngradeWarning()) {
      blockedReasons->push_back(Network::SetCookieBlockedReasonEnum::
                                    SchemefulSameSiteUnspecifiedTreatedAsLax);
    } else {
      blockedReasons->push_back(
          Network::SetCookieBlockedReasonEnum::SameSiteUnspecifiedTreatedAsLax);
    }
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SAMESITE_NONE_INSECURE)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::SameSiteNoneInsecure);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_USER_PREFERENCES)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::UserPreferences);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::
              EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::ThirdPartyBlockedInFirstPartySet);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_THIRD_PARTY_PHASEOUT)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::ThirdPartyPhaseout);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_FAILURE_TO_STORE)) {
    blockedReasons->push_back(Network::SetCookieBlockedReasonEnum::SyntaxError);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_NONCOOKIEABLE_SCHEME)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::SchemeNotSupported);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_OVERWRITE_SECURE)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::OverwriteSecure);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_INVALID_DOMAIN)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::InvalidDomain);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_INVALID_PREFIX)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::InvalidPrefix);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::NameValuePairExceedsMaxSize);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_DISALLOWED_CHARACTER)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::DisallowedCharacter);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_UNKNOWN_ERROR)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::UnknownError);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_NO_COOKIE_CONTENT)) {
    blockedReasons->push_back(
        Network::SetCookieBlockedReasonEnum::NoCookieContent);
  }

  return blockedReasons;
}

std::unique_ptr<Array<Network::CookieBlockedReason>>
GetProtocolBlockedCookieReason(net::CookieInclusionStatus status) {
  std::unique_ptr<Array<Network::CookieBlockedReason>> blockedReasons =
      std::make_unique<Array<Network::CookieBlockedReason>>();

  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_SECURE_ONLY)) {
    blockedReasons->push_back(Network::CookieBlockedReasonEnum::SecureOnly);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_NOT_ON_PATH)) {
    blockedReasons->push_back(Network::CookieBlockedReasonEnum::NotOnPath);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_DOMAIN_MISMATCH)) {
    blockedReasons->push_back(Network::CookieBlockedReasonEnum::DomainMismatch);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SAMESITE_STRICT)) {
    if (status.HasSchemefulDowngradeWarning()) {
      blockedReasons->push_back(
          Network::CookieBlockedReasonEnum::SchemefulSameSiteStrict);
    } else {
      blockedReasons->push_back(
          Network::CookieBlockedReasonEnum::SameSiteStrict);
    }
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_LAX)) {
    if (status.HasSchemefulDowngradeWarning()) {
      blockedReasons->push_back(
          Network::CookieBlockedReasonEnum::SchemefulSameSiteLax);
    } else {
      blockedReasons->push_back(Network::CookieBlockedReasonEnum::SameSiteLax);
    }
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::
              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) {
    if (status.HasSchemefulDowngradeWarning()) {
      blockedReasons->push_back(Network::CookieBlockedReasonEnum::
                                    SchemefulSameSiteUnspecifiedTreatedAsLax);
    } else {
      blockedReasons->push_back(
          Network::CookieBlockedReasonEnum::SameSiteUnspecifiedTreatedAsLax);
    }
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SAMESITE_NONE_INSECURE)) {
    blockedReasons->push_back(
        Network::CookieBlockedReasonEnum::SameSiteNoneInsecure);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_USER_PREFERENCES)) {
    blockedReasons->push_back(
        Network::CookieBlockedReasonEnum::UserPreferences);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::
              EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET)) {
    blockedReasons->push_back(
        Network::CookieBlockedReasonEnum::ThirdPartyBlockedInFirstPartySet);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_THIRD_PARTY_PHASEOUT)) {
    blockedReasons->push_back(
        Network::CookieBlockedReasonEnum::ThirdPartyPhaseout);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE)) {
    blockedReasons->push_back(
        Network::CookieBlockedReasonEnum::NameValuePairExceedsMaxSize);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_UNKNOWN_ERROR)) {
    blockedReasons->push_back(Network::CookieBlockedReasonEnum::UnknownError);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_PORT_MISMATCH)) {
    blockedReasons->push_back(Network::CookieBlockedReasonEnum::PortMismatch);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SCHEME_MISMATCH)) {
    blockedReasons->push_back(Network::CookieBlockedReasonEnum::SchemeMismatch);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_ANONYMOUS_CONTEXT)) {
    blockedReasons->push_back(
        Network::CookieBlockedReasonEnum::AnonymousContext);
  }
  return blockedReasons;
}

std::unique_ptr<Array<Network::BlockedSetCookieWithReason>>
BuildProtocolBlockedSetCookies(
    const net::CookieAndLineAccessResultList& net_list) {
  std::unique_ptr<Array<Network::BlockedSetCookieWithReason>> protocol_list =
      std::make_unique<Array<Network::BlockedSetCookieWithReason>>();

  for (const net::CookieAndLineWithAccessResult& cookie : net_list) {
    std::unique_ptr<Array<Network::SetCookieBlockedReason>> blocked_reasons =
        GetProtocolBlockedSetCookieReason(cookie.access_result.status);
    if (!blocked_reasons->size()) {
      continue;
    }

    protocol_list->push_back(
        Network::BlockedSetCookieWithReason::Create()
            .SetBlockedReasons(std::move(blocked_reasons))
            .SetCookieLine(cookie.cookie_string)
            .SetCookie(cookie.cookie.has_value()
                           ? BuildCookie(cookie.cookie.value())
                           : nullptr)
            .Build());
  }
  return protocol_list;
}

Network::CookieExemptionReason GetProtocolCookieExemptionReason(
    net::CookieInclusionStatus status) {
  switch (status.exemption_reason()) {
    case net::CookieInclusionStatus::ExemptionReason::kNone:
      return Network::CookieExemptionReasonEnum::None;
    case net::CookieInclusionStatus::ExemptionReason::kUserSetting:
      return Network::CookieExemptionReasonEnum::UserSetting;
    case net::CookieInclusionStatus::ExemptionReason::kEnterprisePolicy:
      return Network::CookieExemptionReasonEnum::EnterprisePolicy;
    case net::CookieInclusionStatus::ExemptionReason::kStorageAccess:
      return Network::CookieExemptionReasonEnum::StorageAccess;
    case net::CookieInclusionStatus::ExemptionReason::kTopLevelStorageAccess:
      return Network::CookieExemptionReasonEnum::TopLevelStorageAccess;
    case net::CookieInclusionStatus::ExemptionReason::kScheme:
      return Network::CookieExemptionReasonEnum::Scheme;
    case net::CookieInclusionStatus::ExemptionReason::
        kSameSiteNoneCookiesInSandbox:
      return Network::CookieExemptionReasonEnum::SameSiteNoneCookiesInSandbox;
  }
}

std::unique_ptr<Array<Network::ExemptedSetCookieWithReason>>
BuildProtocolExemptedSetCookies(
    const net::CookieAndLineAccessResultList& net_list) {
  std::unique_ptr<Array<Network::ExemptedSetCookieWithReason>> protocol_list =
      std::make_unique<Array<Network::ExemptedSetCookieWithReason>>();

  for (const auto& cookie : net_list) {
    Network::CookieExemptionReason exemption_reason =
        GetProtocolCookieExemptionReason(cookie.access_result.status);
    if (exemption_reason != Network::CookieExemptionReasonEnum::None) {
      // The exempted cookies are guaranteed to be valid.
      protocol_list->push_back(
          Network::ExemptedSetCookieWithReason::Create()
              .SetExemptionReason(std::move(exemption_reason))
              .SetCookieLine(cookie.cookie_string)
              .SetCookie(BuildCookie(cookie.cookie.value()))
              .Build());
    }
  }
  return protocol_list;
}

std::pair<std::unique_ptr<Array<Network::CookieBlockedReason>>,
          Network::CookieExemptionReason>
GetProtocolAssociatedCookie(net::CookieInclusionStatus status) {
  std::unique_ptr<Array<Network::CookieBlockedReason>> blocked_reasons =
      std::make_unique<Array<Network::CookieBlockedReason>>();
  blocked_reasons = GetProtocolBlockedCookieReason(status);

  Network::CookieExemptionReason exemption_reason =
      GetProtocolCookieExemptionReason(status);

  return std::make_pair(std::move(blocked_reasons),
                        std::move(exemption_reason));
}

std::unique_ptr<Array<Network::AssociatedCookie>>
BuildProtocolAssociatedCookies(const net::CookieAccessResultList& net_list) {
  auto protocol_list = std::make_unique<Array<Network::AssociatedCookie>>();

  for (const net::CookieWithAccessResult& cookie : net_list) {
    std::pair<std::unique_ptr<Array<Network::CookieBlockedReason>>,
              Network::CookieExemptionReason>
        cookie_with_reasons =
            GetProtocolAssociatedCookie(cookie.access_result.status);
    // Note that the condition below is not always true, as there might be
    // blocked reasons that we do not report.
    if (cookie_with_reasons.first->size() ||
        cookie.access_result.status.IsInclude()) {
      protocol_list->push_back(
          Network::AssociatedCookie::Create()
              .SetCookie(BuildCookie(cookie.cookie))
              .SetBlockedReasons(std::move(cookie_with_reasons.first))
              .SetExemptionReason(std::move(cookie_with_reasons.second))
              .Build());
    }
  }
  return protocol_list;
}

std::unique_ptr<protocol::Network::DeviceBoundSessionKey>
BuildProtocolDeviceBoundSessionKey(
    const net::device_bound_sessions::SessionKey& key) {
  return protocol::Network::DeviceBoundSessionKey::Create()
      .SetSite(key.site.Serialize())
      .SetId(key.id.value())
      .Build();
}

const char* GetProtocolSessionUsage(
    network::mojom::DeviceBoundSessionUsage usage) {
  switch (usage) {
    case network::mojom::DeviceBoundSessionUsage::kSiteMatchNotInScope:
      return Network::DeviceBoundSessionWithUsage::UsageEnum::NotInScope;
    case network::mojom::DeviceBoundSessionUsage::kInScopeRefreshNotYetNeeded:
      return Network::DeviceBoundSessionWithUsage::UsageEnum::
          InScopeRefreshNotYetNeeded;
    case network::mojom::DeviceBoundSessionUsage::kInScopeRefreshNotAllowed:
      return Network::DeviceBoundSessionWithUsage::UsageEnum::
          InScopeRefreshNotAllowed;
    case network::mojom::DeviceBoundSessionUsage::
        kInScopeProactiveRefreshNotPossible:
      return Network::DeviceBoundSessionWithUsage::UsageEnum::
          ProactiveRefreshNotPossible;
    case network::mojom::DeviceBoundSessionUsage::
        kInScopeProactiveRefreshAttempted:
      return Network::DeviceBoundSessionWithUsage::UsageEnum::
          ProactiveRefreshAttempted;
    case network::mojom::DeviceBoundSessionUsage::kDeferred:
      return Network::DeviceBoundSessionWithUsage::UsageEnum::Deferred;
    case network::mojom::DeviceBoundSessionUsage::kUnknown:
    case network::mojom::DeviceBoundSessionUsage::kNoSiteMatchNotInScope:
      NOTREACHED();
  }
}

std::unique_ptr<protocol::Array<protocol::Network::DeviceBoundSessionWithUsage>>
BuildProtocolDeviceBoundSessionUsages(
    const std::vector<network::mojom::DeviceBoundSessionWithUsagePtr>&
        device_bound_session_usages) {
  if (!base::FeatureList::IsEnabled(features::kDeviceBoundSessionsDevTools)) {
    return nullptr;
  }
  auto protocol_list = std::make_unique<
      protocol::Array<protocol::Network::DeviceBoundSessionWithUsage>>();
  for (const auto& session_usage : device_bound_session_usages) {
    // Don't send the usage if the usage is unknown or if the session's site is
    // irrelevant.
    if (session_usage->usage ==
            network::mojom::DeviceBoundSessionUsage::kNoSiteMatchNotInScope ||
        session_usage->usage ==
            network::mojom::DeviceBoundSessionUsage::kUnknown) {
      continue;
    }
    protocol_list->push_back(
        protocol::Network::DeviceBoundSessionWithUsage::Create()
            .SetSessionKey(
                BuildProtocolDeviceBoundSessionKey(session_usage->session_key))
            .SetUsage(GetProtocolSessionUsage(session_usage->usage))
            .Build());
  }
  if (protocol_list->empty()) {
    return nullptr;
  }
  return protocol_list;
}

using SourceTypeEnum = net::SourceStreamType;
namespace ContentEncodingEnum = protocol::Network::ContentEncodingEnum;
std::optional<SourceTypeEnum> SourceTypeFromProtocol(
    const protocol::Network::ContentEncoding& encoding) {
  if (ContentEncodingEnum::Gzip == encoding) {
    return SourceTypeEnum::kGzip;
  }
  if (ContentEncodingEnum::Br == encoding) {
    return SourceTypeEnum::kBrotli;
  }
  if (ContentEncodingEnum::Deflate == encoding) {
    return SourceTypeEnum::kDeflate;
  }
  if (ContentEncodingEnum::Zstd == encoding) {
    return SourceTypeEnum::kZstd;
  }
  return std::nullopt;
}

}  // namespace

class BackgroundSyncRestorer {
 public:
  BackgroundSyncRestorer(const std::string& host_id,
                         StoragePartition* storage_partition)
      : host_id_(host_id), storage_partition_(storage_partition) {
    SetServiceWorkerOfflineStatus(true);
  }

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

  ~BackgroundSyncRestorer() { SetServiceWorkerOfflineStatus(false); }

  void SetStoragePartition(StoragePartition* storage_partition) {
    storage_partition_ = storage_partition;
  }

 private:
  void SetServiceWorkerOfflineStatus(bool offline) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    scoped_refptr<DevToolsAgentHost> host =
        DevToolsAgentHost::GetForId(host_id_);
    if (!host || !storage_partition_ ||
        host->GetType() != DevToolsAgentHost::kTypeServiceWorker) {
      return;
    }
    scoped_refptr<ServiceWorkerDevToolsAgentHost> service_worker_host =
        static_cast<ServiceWorkerDevToolsAgentHost*>(host.get());
    scoped_refptr<BackgroundSyncContextImpl> sync_context =
        static_cast<StoragePartitionImpl*>(storage_partition_)
            ->GetBackgroundSyncContext();
    if (offline) {
      auto* swcontext = static_cast<ServiceWorkerContextWrapper*>(
          storage_partition_->GetServiceWorkerContext());
      ServiceWorkerVersion* version =
          swcontext->GetLiveVersion(service_worker_host->version_id());
      if (!version) {
        return;
      }
      offline_sw_registration_id_ = version->registration_id();
    }
    if (offline_sw_registration_id_ ==
        blink::mojom::kInvalidServiceWorkerRegistrationId) {
      return;
    }
    sync_context->background_sync_manager()->EmulateServiceWorkerOffline(
        offline_sw_registration_id_, offline);
  }

  std::string host_id_;
  raw_ptr<StoragePartition> storage_partition_;
  int64_t offline_sw_registration_id_ =
      blink::mojom::kInvalidServiceWorkerRegistrationId;
};

NetworkHandler::NetworkHandler(
    const std::string& host_id,
    const base::UnguessableToken& devtools_token,
    DevToolsIOContext* io_context,
    DevToolsSession* session,
    StoragePartition* maybe_storage_partition,
    base::RepeatingClosure update_loader_factories_callback,
    DevToolsAgentHostClient* client,
    base::OnceClosure cleanup_after_modifications_callback)
    : DevToolsDomainHandler(Network::Metainfo::domainName),
      host_id_(host_id),
      devtools_token_(devtools_token),
      io_context_(io_context),
      client_(client),
      browser_context_(nullptr),
      storage_partition_(maybe_storage_partition),
      host_(nullptr),
      enabled_(false),
#if BUILDFLAG(ENABLE_REPORTING)
      reporting_receiver_(this),
#endif  // BUILDFLAG(ENABLE_REPORTING)
#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
      device_bound_session_receiver_(this),
#endif  // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
      bypass_service_worker_(false),
      cache_disabled_(false),
      update_loader_factories_callback_(
          std::move(update_loader_factories_callback)),
      cleanup_after_modifications_callback_(
          std::move(cleanup_after_modifications_callback)),
      root_session_(*session->GetRootSession()),
      throttling_client_id_(base::UnguessableToken::Create()) {
  DCHECK(io_context_);
  static bool have_configured_service_worker_context = false;
  if (have_configured_service_worker_context) {
    return;
  }
  have_configured_service_worker_context = true;
}

NetworkHandler::~NetworkHandler() {
  if (did_modifications_ && cleanup_after_modifications_callback_) {
    std::move(cleanup_after_modifications_callback_).Run();
  }
}

// static
std::unique_ptr<Array<Network::Cookie>> NetworkHandler::BuildCookieArray(
    const std::vector<net::CanonicalCookie>& cookie_list) {
  auto cookies = std::make_unique<Array<Network::Cookie>>();

  for (const net::CanonicalCookie& cookie : cookie_list) {
    cookies->emplace_back(BuildCookie(cookie));
  }

  return cookies;
}

// static
net::Error NetworkHandler::NetErrorFromString(const std::string& error,
                                              bool* ok) {
  *ok = true;
  if (error == Network::ErrorReasonEnum::Failed) {
    return net::ERR_FAILED;
  }
  if (error == Network::ErrorReasonEnum::Aborted) {
    return net::ERR_ABORTED;
  }
  if (error == Network::ErrorReasonEnum::TimedOut) {
    return net::ERR_TIMED_OUT;
  }
  if (error == Network::ErrorReasonEnum::AccessDenied) {
    return net::ERR_ACCESS_DENIED;
  }
  if (error == Network::ErrorReasonEnum::ConnectionClosed) {
    return net::ERR_CONNECTION_CLOSED;
  }
  if (error == Network::ErrorReasonEnum::ConnectionReset) {
    return net::ERR_CONNECTION_RESET;
  }
  if (error == Network::ErrorReasonEnum::ConnectionRefused) {
    return net::ERR_CONNECTION_REFUSED;
  }
  if (error == Network::ErrorReasonEnum::ConnectionAborted) {
    return net::ERR_CONNECTION_ABORTED;
  }
  if (error == Network::ErrorReasonEnum::ConnectionFailed) {
    return net::ERR_CONNECTION_FAILED;
  }
  if (error == Network::ErrorReasonEnum::NameNotResolved) {
    return net::ERR_NAME_NOT_RESOLVED;
  }
  if (error == Network::ErrorReasonEnum::InternetDisconnected) {
    return net::ERR_INTERNET_DISCONNECTED;
  }
  if (error == Network::ErrorReasonEnum::AddressUnreachable) {
    return net::ERR_ADDRESS_UNREACHABLE;
  }
  if (error == Network::ErrorReasonEnum::BlockedByClient) {
    return net::ERR_BLOCKED_BY_CLIENT;
  }
  if (error == Network::ErrorReasonEnum::BlockedByResponse) {
    return net::ERR_BLOCKED_BY_RESPONSE;
  }
  *ok = false;
  return net::ERR_FAILED;
}

// static
String NetworkHandler::NetErrorToString(int net_error) {
  switch (net_error) {
    case net::ERR_ABORTED:
      return Network::ErrorReasonEnum::Aborted;
    case net::ERR_TIMED_OUT:
      return Network::ErrorReasonEnum::TimedOut;
    case net::ERR_ACCESS_DENIED:
      return Network::ErrorReasonEnum::AccessDenied;
    case net::ERR_CONNECTION_CLOSED:
      return Network::ErrorReasonEnum::ConnectionClosed;
    case net::ERR_CONNECTION_RESET:
      return Network::ErrorReasonEnum::ConnectionReset;
    case net::ERR_CONNECTION_REFUSED:
      return Network::ErrorReasonEnum::ConnectionRefused;
    case net::ERR_CONNECTION_ABORTED:
      return Network::ErrorReasonEnum::ConnectionAborted;
    case net::ERR_CONNECTION_FAILED:
      return Network::ErrorReasonEnum::ConnectionFailed;
    case net::ERR_NAME_NOT_RESOLVED:
      return Network::ErrorReasonEnum::NameNotResolved;
    case net::ERR_INTERNET_DISCONNECTED:
      return Network::ErrorReasonEnum::InternetDisconnected;
    case net::ERR_ADDRESS_UNREACHABLE:
      return Network::ErrorReasonEnum::AddressUnreachable;
    case net::ERR_BLOCKED_BY_CLIENT:
      return Network::ErrorReasonEnum::BlockedByClient;
    case net::ERR_BLOCKED_BY_RESPONSE:
      return Network::ErrorReasonEnum::BlockedByResponse;
    default:
      return Network::ErrorReasonEnum::Failed;
  }
}

// static
bool NetworkHandler::AddInterceptedResourceType(
    const std::string& resource_type,
    base::flat_set<blink::mojom::ResourceType>* intercepted_resource_types) {
  if (resource_type == protocol::Network::ResourceTypeEnum::Document) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kMainFrame);
    intercepted_resource_types->insert(blink::mojom::ResourceType::kSubFrame);
    return true;
  }
  if (resource_type == protocol::Network::ResourceTypeEnum::Stylesheet) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kStylesheet);
    return true;
  }
  if (resource_type == protocol::Network::ResourceTypeEnum::Image) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kImage);
    return true;
  }
  if (resource_type == protocol::Network::ResourceTypeEnum::Media) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kMedia);
    return true;
  }
  if (resource_type == protocol::Network::ResourceTypeEnum::Font) {
    intercepted_resource_types->insert(
        blink::mojom::ResourceType::kFontResource);
    return true;
  }
  if (resource_type == protocol::Network::ResourceTypeEnum::Script) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kScript);
    return true;
  }

  // Map several fetch-like CDP resource types to the underlying `kXhr` Blink
  // resource type. This is necessary because Blink's loader subsystem, where
  // interception occurs, does not differentiate between these types at a
  // protocol level. This mapping provides a functional interception mechanism
  // and resolves the issue where filtering for 'Fetch' or 'EventSource' would
  // silently fail. See https://crbug.com/40256663#comment10 for context.
  if (resource_type == protocol::Network::ResourceTypeEnum::XHR ||
      resource_type == protocol::Network::ResourceTypeEnum::Fetch ||
      resource_type == protocol::Network::ResourceTypeEnum::EventSource) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kXhr);
    if (resource_type == protocol::Network::ResourceTypeEnum::Fetch) {
      intercepted_resource_types->insert(blink::mojom::ResourceType::kPrefetch);
    }
    return true;
  }

  if (resource_type ==
      protocol::Network::ResourceTypeEnum::CSPViolationReport) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kCspReport);
    return true;
  }
  if (resource_type == protocol::Network::ResourceTypeEnum::Ping) {
    intercepted_resource_types->insert(blink::mojom::ResourceType::kPing);
    return true;
  }
  if (resource_type == protocol::Network::ResourceTypeEnum::Other) {
    intercepted_resource_types->insert(
        blink::mojom::ResourceType::kSubResource);
    intercepted_resource_types->insert(blink::mojom::ResourceType::kObject);
    intercepted_resource_types->insert(blink::mojom::ResourceType::kWorker);
    intercepted_resource_types->insert(
        blink::mojom::ResourceType::kSharedWorker);
    intercepted_resource_types->insert(blink::mojom::ResourceType::kFavicon);
    intercepted_resource_types->insert(
        blink::mojom::ResourceType::kServiceWorker);
    intercepted_resource_types->insert(
        blink::mojom::ResourceType::kPluginResource);
    return true;
  }
  return false;
}

// static
const char* NetworkHandler::ResourceTypeToString(
    blink::mojom::ResourceType resource_type) {
  switch (resource_type) {
    case blink::mojom::ResourceType::kMainFrame:
      return protocol::Network::ResourceTypeEnum::Document;
    case blink::mojom::ResourceType::kSubFrame:
      return protocol::Network::ResourceTypeEnum::Document;
    case blink::mojom::ResourceType::kStylesheet:
      return protocol::Network::ResourceTypeEnum::Stylesheet;
    case blink::mojom::ResourceType::kScript:
      return protocol::Network::ResourceTypeEnum::Script;
    case blink::mojom::ResourceType::kImage:
      return protocol::Network::ResourceTypeEnum::Image;
    case blink::mojom::ResourceType::kFontResource:
      return protocol::Network::ResourceTypeEnum::Font;
    case blink::mojom::ResourceType::kSubResource:
      return protocol::Network::ResourceTypeEnum::Other;
    case blink::mojom::ResourceType::kObject:
      return protocol::Network::ResourceTypeEnum::Other;
    case blink::mojom::ResourceType::kMedia:
      return protocol::Network::ResourceTypeEnum::Media;
    case blink::mojom::ResourceType::kWorker:
      return protocol::Network::ResourceTypeEnum::Other;
    case blink::mojom::ResourceType::kSharedWorker:
      return protocol::Network::ResourceTypeEnum::Other;
    case blink::mojom::ResourceType::kPrefetch:
      return protocol::Network::ResourceTypeEnum::Fetch;
    case blink::mojom::ResourceType::kFavicon:
      return protocol::Network::ResourceTypeEnum::Other;
    case blink::mojom::ResourceType::kXhr:
      return protocol::Network::ResourceTypeEnum::XHR;
    case blink::mojom::ResourceType::kPing:
      return protocol::Network::ResourceTypeEnum::Ping;
    case blink::mojom::ResourceType::kServiceWorker:
      return protocol::Network::ResourceTypeEnum::Other;
    case blink::mojom::ResourceType::kCspReport:
      return protocol::Network::ResourceTypeEnum::CSPViolationReport;
    case blink::mojom::ResourceType::kPluginResource:
      return protocol::Network::ResourceTypeEnum::Other;
    default:
      return protocol::Network::ResourceTypeEnum::Other;
  }
}

// static
std::vector<NetworkHandler*> NetworkHandler::ForAgentHost(
    DevToolsAgentHostImpl* host) {
  return host->HandlersByName<NetworkHandler>(Network::Metainfo::domainName);
}

void NetworkHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ = std::make_unique<Network::Frontend>(dispatcher->channel());
  Network::Dispatcher::wire(dispatcher, this);
}

void NetworkHandler::SetRenderer(int render_process_host_id,
                                 RenderFrameHostImpl* frame_host) {
  RenderProcessHost* process_host =
      RenderProcessHost::FromID(render_process_host_id);
  if (process_host) {
    storage_partition_ = process_host->GetStoragePartition();
    browser_context_ = process_host->GetBrowserContext();
  } else {
    storage_partition_ = nullptr;
    browser_context_ = nullptr;
  }
  MaybeEnableDurableMessages(base::DoNothing());
  host_ = frame_host;
  if (background_sync_restorer_) {
    background_sync_restorer_->SetStoragePartition(storage_partition_);
  }
}

Response NetworkHandler::Enable(
    std::optional<int> max_total_size,
    std::optional<int> max_resource_size,
    std::optional<int> max_post_data_size,
    std::optional<bool> report_direct_socket_traffic,
    std::optional<bool> enable_durable_messages) {
  // Durable Messages require a maxTotalBufferSize to be set, for enabling
  // collection.
  durable_message_max_total_size_ = max_total_size.value_or(0);
  if (enable_durable_messages.value_or(false) &&
      !durable_message_max_total_size_) {
    return Response::InvalidParams(
        "maxTotalBufferSize is required with enableDurableMessages");
  }
  enable_durable_messages_ = enable_durable_messages.value_or(false);
  enabled_ = true;
  if (enable_durable_messages_) {
    // MaybeEnableDurableMessages will asynchronously enable durable messages
    // collection if possible, if used with enable(). This will be deprecated,
    // in favor of enableDurableMessages in the future.
    MaybeEnableDurableMessages(base::DoNothing());
  }
  if (enable_durable_messages.has_value() &&
      enable_durable_messages.value() == false) {
    // If an explicit `false` is passed, any active collector should be
    // disabled for this profile.
    DisableDurableMessages();
  }
  return Response::FallThrough();
}

DispatchResponse NetworkHandler::Disable() {
  enabled_ = false;
  url_loader_interceptor_.reset();
  SetNetworkConditions({}, /*offline=*/false);
  extra_headers_.clear();
  ClearAcceptedEncodingsOverride();
  enable_third_party_cookie_restriction_ = false;
#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
  device_bound_session_receiver_.reset();
#endif  // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
  DisableDurableMessages();
  return Response::FallThrough();
}

#if BUILDFLAG(ENABLE_REPORTING)

namespace {

String BuildReportStatus(const net::ReportingReport::Status status) {
  switch (status) {
    case net::ReportingReport::Status::QUEUED:
      return protocol::Network::ReportStatusEnum::Queued;
    case net::ReportingReport::Status::PENDING:
      return protocol::Network::ReportStatusEnum::Pending;
    case net::ReportingReport::Status::DOOMED:
      return protocol::Network::ReportStatusEnum::MarkedForRemoval;
    case net::ReportingReport::Status::SUCCESS:
      return protocol::Network::ReportStatusEnum::Success;
  }
}

std::vector<GURL> ComputeReportingURLs(RenderFrameHostImpl* frame_host) {
  std::vector<GURL> urls;
  frame_host->ForEachRenderFrameHostImplWithAction(
      [frame_host, &urls](content::RenderFrameHostImpl* rfh) {
        if (rfh != frame_host && (rfh->is_local_root_subframe() ||
                                  &rfh->GetPage() != &frame_host->GetPage())) {
          return content::RenderFrameHost::FrameIterationAction::kSkipChildren;
        }
        urls.push_back(frame_host->GetLastCommittedURL());
        return content::RenderFrameHost::FrameIterationAction::kContinue;
      });
  return urls;
}

}  // namespace

std::unique_ptr<protocol::Network::ReportingApiReport>
NetworkHandler::BuildProtocolReport(const net::ReportingReport& report) {
  if (!host_) {
    return nullptr;
  }
  std::vector<GURL> reporting_filter_urls = ComputeReportingURLs(host_);
  if (std::ranges::contains(reporting_filter_urls, report.url)) {
    return protocol::Network::ReportingApiReport::Create()
        .SetId(report.id.ToString())
        .SetInitiatorUrl(report.url.spec())
        .SetDestination(report.group)
        .SetType(report.type)
        .SetTimestamp(
            (report.queued - base::TimeTicks::UnixEpoch()).InSecondsF())
        .SetDepth(report.depth)
        .SetCompletedAttempts(report.attempts)
        .SetBody(std::make_unique<base::DictValue>(report.body.Clone()))
        .SetStatus(BuildReportStatus(report.status))
        .Build();
  }
  return nullptr;
}

void NetworkHandler::OnReportAdded(const net::ReportingReport& report) {
  auto protocol_report = BuildProtocolReport(report);
  if (protocol_report) {
    frontend_->ReportingApiReportAdded(std::move(protocol_report));
  }
}

void NetworkHandler::OnReportUpdated(const net::ReportingReport& report) {
  auto protocol_report = BuildProtocolReport(report);
  if (protocol_report) {
    frontend_->ReportingApiReportUpdated(std::move(protocol_report));
  }
}

std::unique_ptr<protocol::Network::ReportingApiEndpoint>
NetworkHandler::BuildProtocolEndpoint(const net::ReportingEndpoint& endpoint) {
  return protocol::Network::ReportingApiEndpoint::Create()
      .SetUrl(endpoint.info.url.spec())
      .SetGroupName(endpoint.group_key.group_name)
      .Build();
}

void NetworkHandler::OnEndpointsUpdatedForOrigin(
    const std::vector<::net::ReportingEndpoint>& endpoints) {
  if (!host_ || endpoints.empty()) {
    return;
  }
  // Endpoint should have an origin.
  DCHECK(endpoints[0].group_key.origin.has_value());
  url::Origin origin = endpoints[0].group_key.origin.value();
  DCHECK(std::ranges::all_of(endpoints, [&](auto const& endpoint) {
    // Endpoint should have an origin.
    DCHECK(endpoint.group_key.origin.has_value());
    return endpoint.group_key.origin.value() == origin;
  }));
  std::vector<GURL> reporting_filter_urls = ComputeReportingURLs(host_);

  // Only send protocol event if the origin of the updated endpoints matches
  // an origin in the local frame tree.
  if (std::ranges::any_of(reporting_filter_urls, [&](auto const& url) {
        return url::Origin::Create(url) == origin;
      })) {
    auto protocol_endpoints = std::make_unique<
        protocol::Array<protocol::Network::ReportingApiEndpoint>>();
    protocol_endpoints->reserve(endpoints.size());
    for (const auto& endpoint : endpoints) {
      protocol_endpoints->push_back(BuildProtocolEndpoint(endpoint));
    }
    frontend_->ReportingApiEndpointsChangedForOrigin(
        origin.Serialize(), std::move(protocol_endpoints));
  }
}

Response NetworkHandler::EnableReportingApi(const bool enable) {
  if (!storage_partition_ || !host_) {
    return Response::InternalError();
  }

  if (enable) {
    if (!reporting_receiver_.is_bound()) {
      mojo::PendingRemote<network::mojom::ReportingApiObserver> observer;
      reporting_receiver_.Bind(observer.InitWithNewPipeAndPassReceiver());
      storage_partition_->GetNetworkContext()->AddReportingApiObserver(
          std::move(observer));
    }
  } else {
    reporting_receiver_.reset();
  }
  return Response::Success();
}

#else
Response NetworkHandler::EnableReportingApi(const bool enable) {
  return Response::InternalError();
}
#endif  // BUILDFLAG(ENABLE_REPORTING)

#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)

namespace {
String BuildProtocolDeviceBoundSessionUrlRuleType(
    net::device_bound_sessions::InclusionResult rule_type) {
  switch (rule_type) {
    case net::device_bound_sessions::InclusionResult::kExclude:
      return protocol::Network::DeviceBoundSessionUrlRule::RuleTypeEnum::
          Exclude;
    case net::device_bound_sessions::InclusionResult::kInclude:
      return protocol::Network::DeviceBoundSessionUrlRule::RuleTypeEnum::
          Include;
  }
}

std::unique_ptr<protocol::Network::DeviceBoundSessionUrlRule>
BuildProtocolDeviceBoundSessionUrlRule(
    const net::device_bound_sessions::UrlRuleDisplay& rule) {
  return protocol::Network::DeviceBoundSessionUrlRule::Create()
      .SetRuleType(BuildProtocolDeviceBoundSessionUrlRuleType(rule.rule_type))
      .SetHostPattern(rule.host_pattern)
      .SetPathPrefix(rule.path_prefix)
      .Build();
}

std::unique_ptr<protocol::Network::DeviceBoundSessionInclusionRules>
BuildProtocolDeviceBoundDeviceBoundSessionInclusionRules(
    const net::device_bound_sessions::SessionInclusionRulesDisplay& rules) {
  auto protocol_rules = std::make_unique<
      protocol::Array<protocol::Network::DeviceBoundSessionUrlRule>>();
  protocol_rules->reserve(rules.url_rules.size());
  for (const auto& rule : rules.url_rules) {
    protocol_rules->emplace_back(BuildProtocolDeviceBoundSessionUrlRule(rule));
  }
  return protocol::Network::DeviceBoundSessionInclusionRules::Create()
      .SetOrigin(rules.origin)
      .SetIncludeSite(rules.include_site)
      .SetUrlRules(std::move(protocol_rules))
      .Build();
}

std::unique_ptr<protocol::Network::DeviceBoundSessionCookieCraving>
BuildProtocolDeviceBoundDeviceBoundSessionCookieCraving(
    const net::device_bound_sessions::CookieCravingDisplay& craving) {
  auto protocol_craving =
      protocol::Network::DeviceBoundSessionCookieCraving::Create()
          .SetName(craving.name)
          .SetDomain(craving.domain)
          .SetPath(craving.path)
          .SetSecure(craving.secure)
          .SetHttpOnly(craving.http_only)
          .Build();
  std::optional<Network::CookieSameSite> same_site =
      BuildCookieSameSite(craving.same_site);
  if (same_site.has_value()) {
    protocol_craving->SetSameSite(same_site.value());
  }
  return protocol_craving;
}

std::unique_ptr<protocol::Network::DeviceBoundSession>
BuildProtocolDeviceBoundSession(
    const net::device_bound_sessions::SessionDisplay& session) {
  auto protocol_cravings = std::make_unique<
      protocol::Array<protocol::Network::DeviceBoundSessionCookieCraving>>();
  protocol_cravings->reserve(session.cookie_cravings.size());
  for (const auto& craving : session.cookie_cravings) {
    protocol_cravings->emplace_back(
        BuildProtocolDeviceBoundDeviceBoundSessionCookieCraving(craving));
  }
  auto protocol_initiators = std::make_unique<protocol::Array<std::string>>();
  protocol_initiators->reserve(session.allowed_refresh_initiators.size());
  for (const auto& initiator : session.allowed_refresh_initiators) {
    protocol_initiators->emplace_back(initiator);
  }

  auto protocol_session =
      protocol::Network::DeviceBoundSession::Create()
          .SetKey(BuildProtocolDeviceBoundSessionKey(session.key))
          .SetRefreshUrl(session.refresh_url.spec())
          .SetInclusionRules(
              BuildProtocolDeviceBoundDeviceBoundSessionInclusionRules(
                  session.inclusion_rules))
          .SetCookieCravings(std::move(protocol_cravings))
          .SetExpiryDate(session.expiry_date.InSecondsFSinceUnixEpoch())
          .SetAllowedRefreshInitiators(std::move(protocol_initiators))
          .Build();
  if (session.cached_challenge) {
    protocol_session->SetCachedChallenge(session.cached_challenge.value());
  }
  return protocol_session;
}

std::unique_ptr<protocol::Network::DeviceBoundSessionFailedRequest>
BuildProtocolDeviceBoundSessionFailedRequest(
    const net::device_bound_sessions::FailedRequest& failed_request) {
  auto protocol_failed_request =
      protocol::Network::DeviceBoundSessionFailedRequest::Create()
          .SetRequestUrl(failed_request.request_url.spec())
          .Build();
  if (failed_request.net_error.has_value()) {
    protocol_failed_request->SetNetError(
        net::ErrorToString(failed_request.net_error.value()));
  }
  if (failed_request.response_error.has_value()) {
    protocol_failed_request->SetResponseError(
        failed_request.response_error.value());
  }
  if (failed_request.response_error_body.has_value()) {
    protocol_failed_request->SetResponseErrorBody(
        failed_request.response_error_body.value());
  }
  return protocol_failed_request;
}

String BuildProtocolDeviceBoundSessionFetchResult(
    net::device_bound_sessions::SessionError::ErrorType type) {
  switch (type) {
    case net::device_bound_sessions::SessionError::ErrorType::kSuccess:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::Success;
    case net::device_bound_sessions::SessionError::ErrorType::kKeyError:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::KeyError;
    case net::device_bound_sessions::SessionError::ErrorType::kSigningError:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::SigningError;
    case net::device_bound_sessions::SessionError::ErrorType::
        kServerRequestedTermination:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          ServerRequestedTermination;
    case net::device_bound_sessions::SessionError::ErrorType::kInvalidSessionId:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidSessionId;
    case net::device_bound_sessions::SessionError::ErrorType::kInvalidChallenge:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidChallenge;
    case net::device_bound_sessions::SessionError::ErrorType::
        kTooManyChallenges:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          TooManyChallenges;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidFetcherUrl:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidFetcherUrl;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidRefreshUrl:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidRefreshUrl;
    case net::device_bound_sessions::SessionError::ErrorType::
        kTransientHttpError:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          TransientHttpError;
    case net::device_bound_sessions::SessionError::ErrorType::
        kScopeOriginSameSiteMismatch:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          ScopeOriginSameSiteMismatch;
    case net::device_bound_sessions::SessionError::ErrorType::
        kRefreshUrlSameSiteMismatch:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          RefreshUrlSameSiteMismatch;
    case net::device_bound_sessions::SessionError::ErrorType::
        kMismatchedSessionId:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          MismatchedSessionId;
    case net::device_bound_sessions::SessionError::ErrorType::kMissingScope:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::MissingScope;
    case net::device_bound_sessions::SessionError::ErrorType::kNoCredentials:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          NoCredentials;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSubdomainRegistrationWellKnownUnavailable:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SubdomainRegistrationWellKnownUnavailable;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSubdomainRegistrationUnauthorized:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SubdomainRegistrationUnauthorized;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSubdomainRegistrationWellKnownMalformed:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SubdomainRegistrationWellKnownMalformed;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSessionProviderWellKnownUnavailable:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SessionProviderWellKnownUnavailable;
    case net::device_bound_sessions::SessionError::ErrorType::
        kFederatedKeyThumbprintMismatch:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          FederatedKeyThumbprintMismatch;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidFederatedSessionUrl:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidFederatedSessionUrl;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidFederatedKey:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidFederatedKey;
    case net::device_bound_sessions::SessionError::ErrorType::
        kTooManyRelyingOriginLabels:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          TooManyRelyingOriginLabels;
    case net::device_bound_sessions::SessionError::ErrorType::
        kBoundCookieSetForbidden:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          BoundCookieSetForbidden;
    case net::device_bound_sessions::SessionError::ErrorType::kNetError:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::NetError;
    case net::device_bound_sessions::SessionError::ErrorType::kProxyError:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::ProxyError;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidConfigJson:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidConfigJson;
    case net::device_bound_sessions::SessionError::ErrorType::
        kEmptySessionConfig:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          EmptySessionConfig;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsConfig:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsConfig;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsType:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsType;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsEmptyName:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsEmptyName;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsCookie:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsCookie;
    case net::device_bound_sessions::SessionError::ErrorType::
        kPersistentHttpError:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          PersistentHttpError;
    case net::device_bound_sessions::SessionError::ErrorType::
        kRegistrationAttemptedChallenge:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          RegistrationAttemptedChallenge;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidScopeOrigin:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidScopeOrigin;
    case net::device_bound_sessions::SessionError::ErrorType::
        kScopeOriginContainsPath:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          ScopeOriginContainsPath;
    case net::device_bound_sessions::SessionError::ErrorType::
        kRefreshInitiatorNotString:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          RefreshInitiatorNotString;
    case net::device_bound_sessions::SessionError::ErrorType::
        kRefreshInitiatorInvalidHostPattern:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          RefreshInitiatorInvalidHostPattern;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidScopeSpecification:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidScopeSpecification;
    case net::device_bound_sessions::SessionError::ErrorType::
        kMissingScopeSpecificationType:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          MissingScopeSpecificationType;
    case net::device_bound_sessions::SessionError::ErrorType::
        kEmptyScopeSpecificationDomain:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          EmptyScopeSpecificationDomain;
    case net::device_bound_sessions::SessionError::ErrorType::
        kEmptyScopeSpecificationPath:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          EmptyScopeSpecificationPath;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidScopeSpecificationType:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidScopeSpecificationType;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidScopeIncludeSite:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidScopeIncludeSite;
    case net::device_bound_sessions::SessionError::ErrorType::
        kMissingScopeIncludeSite:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          MissingScopeIncludeSite;
    case net::device_bound_sessions::SessionError::ErrorType::
        kFederatedNotAuthorizedByProvider:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          FederatedNotAuthorizedByProvider;
    case net::device_bound_sessions::SessionError::ErrorType::
        kFederatedNotAuthorizedByRelyingParty:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          FederatedNotAuthorizedByRelyingParty;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSessionProviderWellKnownMalformed:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SessionProviderWellKnownMalformed;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSessionProviderWellKnownHasProviderOrigin:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SessionProviderWellKnownHasProviderOrigin;
    case net::device_bound_sessions::SessionError::ErrorType::
        kRelyingPartyWellKnownMalformed:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          RelyingPartyWellKnownMalformed;
    case net::device_bound_sessions::SessionError::ErrorType::
        kRelyingPartyWellKnownHasRelyingOrigins:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          RelyingPartyWellKnownHasRelyingOrigins;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidFederatedSessionProviderSessionMissing:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidFederatedSessionProviderSessionMissing;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidFederatedSessionWrongProviderOrigin:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidFederatedSessionWrongProviderOrigin;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsCookieCreationTime:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsCookieCreationTime;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsCookieName:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsCookieName;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsCookieParsing:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsCookieParsing;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsCookieUnpermittedAttribute:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsCookieUnpermittedAttribute;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsCookieInvalidDomain:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsCookieInvalidDomain;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidCredentialsCookiePrefix:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidCredentialsCookiePrefix;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidScopeRulePath:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidScopeRulePath;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidScopeRuleHostPattern:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidScopeRuleHostPattern;
    case net::device_bound_sessions::SessionError::ErrorType::
        kScopeRuleOriginScopedHostPatternMismatch:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          ScopeRuleOriginScopedHostPatternMismatch;
    case net::device_bound_sessions::SessionError::ErrorType::
        kScopeRuleSiteScopedHostPatternMismatch:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          ScopeRuleSiteScopedHostPatternMismatch;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSigningQuotaExceeded:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SigningQuotaExceeded;
    case net::device_bound_sessions::SessionError::ErrorType::
        kRelyingPartyWellKnownUnavailable:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          RelyingPartyWellKnownUnavailable;
    case net::device_bound_sessions::SessionError::ErrorType::
        kInvalidFederatedSessionProviderFailedToRestoreKey:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          InvalidFederatedSessionProviderFailedToRestoreKey;
    case net::device_bound_sessions::SessionError::ErrorType::
        kFailedToUnwrapKey:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          FailedToUnwrapKey;
    case net::device_bound_sessions::SessionError::ErrorType::
        kSessionDeletedDuringRefresh:
      return protocol::Network::DeviceBoundSessionFetchResultEnum::
          SessionDeletedDuringRefresh;
  }
}

String BuildProtocolDeviceBoundSessionRefreshResult(
    net::device_bound_sessions::RefreshResult result) {
  switch (result) {
    case net::device_bound_sessions::RefreshResult::kRefreshed:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          Refreshed;
    case net::device_bound_sessions::RefreshResult::kRefreshedAsWaiter:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          RefreshedAsWaiter;
    case net::device_bound_sessions::RefreshResult::kInitializedService:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          InitializedService;
    case net::device_bound_sessions::RefreshResult::kUnreachable:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          Unreachable;
    case net::device_bound_sessions::RefreshResult::kServerError:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          ServerError;
    case net::device_bound_sessions::RefreshResult::kRefreshQuotaExceeded:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          RefreshQuotaExceeded;
    case net::device_bound_sessions::RefreshResult::kFatalError:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          FatalError;
    case net::device_bound_sessions::RefreshResult::kSigningQuotaExceeded:
      return protocol::Network::RefreshEventDetails::RefreshResultEnum::
          SigningQuotaExceeded;
  }
}

String BuildProtocolDeviceBoundSessionChallengeResult(
    net::device_bound_sessions::ChallengeResult result) {
  switch (result) {
    case net::device_bound_sessions::ChallengeResult::kSuccess:
      return protocol::Network::ChallengeEventDetails::ChallengeResultEnum::
          Success;
    case net::device_bound_sessions::ChallengeResult::kNoSessionId:
      return protocol::Network::ChallengeEventDetails::ChallengeResultEnum::
          NoSessionId;
    case net::device_bound_sessions::ChallengeResult::kNoSessionMatch:
      return protocol::Network::ChallengeEventDetails::ChallengeResultEnum::
          NoSessionMatch;
    case net::device_bound_sessions::ChallengeResult::kCantSetBoundCookie:
      return protocol::Network::ChallengeEventDetails::ChallengeResultEnum::
          CantSetBoundCookie;
  }
}

String BuildProtocolDeviceBoundSessionDeletionReason(
    net::device_bound_sessions::DeletionReason reason) {
  switch (reason) {
    case net::device_bound_sessions::DeletionReason::kExpired:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          Expired;
    case net::device_bound_sessions::DeletionReason::kFailedToRestoreKey:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          FailedToRestoreKey;
    case net::device_bound_sessions::DeletionReason::kFailedToUnwrapKey:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          FailedToUnwrapKey;
    case net::device_bound_sessions::DeletionReason::kStoragePartitionCleared:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          StoragePartitionCleared;
    case net::device_bound_sessions::DeletionReason::kClearBrowsingData:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          ClearBrowsingData;
    case net::device_bound_sessions::DeletionReason::kServerRequested:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          ServerRequested;
    case net::device_bound_sessions::DeletionReason::kInvalidSessionParams:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          InvalidSessionParams;
    case net::device_bound_sessions::DeletionReason::kRefreshFatalError:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          RefreshFatalError;
    case net::device_bound_sessions::DeletionReason::kDevTools:
      return protocol::Network::TerminationEventDetails::DeletionReasonEnum::
          DevTools;
  }
}

}  // namespace

void NetworkHandler::AddDeviceBoundSessionDisplays(
    const std::vector<::net::device_bound_sessions::SessionDisplay>& sessions) {
  auto protocol_sessions = std::make_unique<
      protocol::Array<protocol::Network::DeviceBoundSession>>();
  protocol_sessions->reserve(sessions.size());
  for (const auto& session : sessions) {
    protocol_sessions->emplace_back(BuildProtocolDeviceBoundSession(session));
  }
  frontend_->DeviceBoundSessionsAdded(std::move(protocol_sessions));
}

void NetworkHandler::OnDeviceBoundSessionEventReceived(
    const net::device_bound_sessions::SessionEvent& event) {
  std::unique_ptr<protocol::Network::CreationEventDetails> creationEventDetails;
  std::unique_ptr<protocol::Network::RefreshEventDetails> refreshEventDetails;
  std::unique_ptr<protocol::Network::TerminationEventDetails>
      terminationEventDetails;
  std::unique_ptr<protocol::Network::ChallengeEventDetails>
      challengeEventDetails;
  std::visit(
      absl::Overload{
          [&creationEventDetails](
              const net::device_bound_sessions::CreationEventDetails& details) {
            creationEventDetails =
                protocol::Network::CreationEventDetails::Create()
                    .SetFetchResult(BuildProtocolDeviceBoundSessionFetchResult(
                        details.fetch_error))
                    .Build();
            if (details.new_session_display.has_value()) {
              creationEventDetails->SetNewSession(
                  BuildProtocolDeviceBoundSession(
                      details.new_session_display.value()));
            }
            if (details.failed_request.has_value()) {
              creationEventDetails->SetFailedRequest(
                  BuildProtocolDeviceBoundSessionFailedRequest(
                      details.failed_request.value()));
            }
          },
          [&refreshEventDetails](
              const net::device_bound_sessions::RefreshEventDetails& details) {
            refreshEventDetails =
                protocol::Network::RefreshEventDetails::Create()
                    .SetRefreshResult(
                        BuildProtocolDeviceBoundSessionRefreshResult(
                            details.refresh_result))
                    .SetWasFullyProactiveRefresh(
                        details.was_fully_proactive_refresh)
                    .Build();
            if (details.fetch_error.has_value()) {
              refreshEventDetails->SetFetchResult(
                  BuildProtocolDeviceBoundSessionFetchResult(
                      details.fetch_error.value()));
            }
            if (details.new_session_display.has_value()) {
              refreshEventDetails->SetNewSession(
                  BuildProtocolDeviceBoundSession(
                      details.new_session_display.value()));
            }
            if (details.failed_request.has_value()) {
              refreshEventDetails->SetFailedRequest(
                  BuildProtocolDeviceBoundSessionFailedRequest(
                      details.failed_request.value()));
            }
          },
          [&terminationEventDetails](
              const net::device_bound_sessions::TerminationEventDetails&
                  details) {
            terminationEventDetails =
                protocol::Network::TerminationEventDetails::Create()
                    .SetDeletionReason(
                        BuildProtocolDeviceBoundSessionDeletionReason(
                            details.deletion_reason))
                    .Build();
          },
          [&challengeEventDetails](
              const net::device_bound_sessions::ChallengeEventDetails&
                  details) {
            challengeEventDetails =
                protocol::Network::ChallengeEventDetails::Create()
                    .SetChallengeResult(
                        BuildProtocolDeviceBoundSessionChallengeResult(
                            details.challenge_result))
                    .SetChallenge(details.challenge)
                    .Build();
          }},
      event.event_type_details);

  frontend_->DeviceBoundSessionEventOccurred(
      event.event_id.ToString(), event.site.Serialize(), event.succeeded,
      event.session_id, std::move(creationEventDetails),
      std::move(refreshEventDetails), std::move(terminationEventDetails),
      std::move(challengeEventDetails));
}

Response NetworkHandler::EnableDeviceBoundSessions(bool enable) {
  if (!storage_partition_ || !host_ ||
      !base::FeatureList::IsEnabled(features::kDeviceBoundSessionsDevTools)) {
    return Response::InternalError();
  }

  if (enable) {
    if (!device_bound_session_receiver_.is_bound()) {
      mojo::Remote<network::mojom::DeviceBoundSessionManager> manager;
      storage_partition_->GetNetworkContext()->GetDeviceBoundSessionManager(
          manager.BindNewPipeAndPassReceiver());
      mojo::PendingRemote<network::mojom::DeviceBoundSessionEventObserver>
          observer;
      device_bound_session_receiver_.Bind(
          observer.InitWithNewPipeAndPassReceiver());
      manager->AddEventObserver(std::move(observer));
    }
  } else {
    device_bound_session_receiver_.reset();
  }

  return Response::Success();
}

Response NetworkHandler::DeleteDeviceBoundSession(
    std::unique_ptr<protocol::Network::DeviceBoundSessionKey> key) {
  if (!storage_partition_ || !host_ ||
      !base::FeatureList::IsEnabled(features::kDeviceBoundSessionsDevTools)) {
    return Response::InternalError();
  }

  GURL site_url(key->GetSite());
  if (!site_url.is_valid()) {
    return Response::InvalidParams("Invalid site URL");
  }

  if (!client_->MayAttachToURL(site_url, host_->web_ui())) {
    return Response::InvalidParams("Cannot access session for this site");
  }

  mojo::Remote<network::mojom::DeviceBoundSessionManager> manager;
  storage_partition_->GetNetworkContext()->GetDeviceBoundSessionManager(
      manager.BindNewPipeAndPassReceiver());

  net::device_bound_sessions::SessionKey session_key(
      net::SchemefulSite(site_url),
      net::device_bound_sessions::Session::Id(key->GetId()));

  manager->DeleteSession(net::device_bound_sessions::DeletionReason::kDevTools,
                         session_key);

  return Response::Success();
}

Response NetworkHandler::FetchSchemefulSite(const std::string& origin,
                                            std::string* schemeful_site) {
  *schemeful_site = net::SchemefulSite(GURL(origin)).Serialize();
  return Response::Success();
}
#else
Response NetworkHandler::EnableDeviceBoundSessions(bool enable) {
  return Response::MethodNotFound("not implemented");
}

Response NetworkHandler::DeleteDeviceBoundSession(
    std::unique_ptr<protocol::Network::DeviceBoundSessionKey> key) {
  return Response::MethodNotFound("not implemented");
}

Response NetworkHandler::FetchSchemefulSite(const std::string& origin,
                                            std::string* schemeful_site) {
  return Response::MethodNotFound("not implemented");
}

#endif  // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)

Response NetworkHandler::SetCacheDisabled(bool cache_disabled) {
  cache_disabled_ = cache_disabled;
  return Response::FallThrough();
}

Response NetworkHandler::SetAcceptedEncodings(
    std::unique_ptr<Array<Network::ContentEncoding>> encodings) {
  std::set<net::SourceStreamType> accepted_stream_types;
  for (auto encoding : *encodings) {
    auto type = SourceTypeFromProtocol(encoding);
    if (!type) {
      return Response::InvalidParams("Unknown encoding type: " + encoding);
    }
    accepted_stream_types.insert(type.value());
  }
  accepted_stream_types_ = std::move(accepted_stream_types);

  return Response::FallThrough();
}

Response NetworkHandler::ClearAcceptedEncodingsOverride() {
  accepted_stream_types_ = std::nullopt;
  return Response::FallThrough();
}

class DevtoolsClearCacheObserver
    : public content::BrowsingDataRemover::Observer {
 public:
  explicit DevtoolsClearCacheObserver(
      content::BrowsingDataRemover* remover,
      std::unique_ptr<NetworkHandler::ClearBrowserCacheCallback> callback)
      : remover_(remover), callback_(std::move(callback)) {
    remover_->AddObserver(this);
  }

  ~DevtoolsClearCacheObserver() override { remover_->RemoveObserver(this); }
  void OnBrowsingDataRemoverDone(uint64_t failed_data_types) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    callback_->sendSuccess();
    delete this;
  }

 private:
  raw_ptr<content::BrowsingDataRemover> remover_;
  std::unique_ptr<NetworkHandler::ClearBrowserCacheCallback> callback_;
};

void NetworkHandler::ClearBrowserCache(
    std::unique_ptr<ClearBrowserCacheCallback> callback) {
  if (!browser_context_) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  content::BrowsingDataRemover* remover =
      browser_context_->GetBrowsingDataRemover();
  remover->RemoveAndReply(
      base::Time(), base::Time::Max(),
      content::BrowsingDataRemover::DATA_TYPE_CACHE,
      content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
      new DevtoolsClearCacheObserver(remover, std::move(callback)));
}

void NetworkHandler::ClearBrowserCookies(
    std::unique_ptr<ClearBrowserCookiesCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  NetworkHandler::ClearCookies(
      storage_partition_, CHECK_DEREF(client_.get()),
      base::BindRepeating(
          [](base::WeakPtr<NetworkHandler> handler,
             const net::CanonicalCookie& cookie) {
            return handler && handler->CanAccessCookie(cookie);
          },
          weak_factory_.GetWeakPtr()),
      base::BindOnce(&ClearBrowserCookiesCallback::sendSuccess,
                     std::move(callback)));
}

// static
void NetworkHandler::ClearCookies(
    StoragePartition* storage_partition,
    DevToolsAgentHostClient& client,
    base::RepeatingCallback<bool(const net::CanonicalCookie&)> filter,
    base::OnceClosure callback) {
  auto* cookie_manager = storage_partition->GetCookieManagerForBrowserProcess();

  if (client.MayAccessAllCookies()) {
    // Unrestricted clients can clear all cookies atomically.
    cookie_manager->DeleteCookies(
        network::mojom::CookieDeletionFilter::New(),
        base::BindOnce(base::IgnoreArgs<uint32_t>(std::move(callback))));
  } else {
    // Restricted clients must filter by URL permissions before deletion.
    cookie_manager->GetAllCookies(
        base::BindOnce(&DeleteFilteredCookies, base::Unretained(cookie_manager),
                       /*name=*/std::nullopt,
                       /*normalized_domain=*/std::nullopt,
                       /*path=*/std::nullopt, /*partition_key=*/nullptr,
                       /*filter_by_partition_key=*/false, std::move(filter),
                       std::move(callback)));
  }
}

bool NetworkHandler::CanAccessCookie(const net::CanonicalCookie& cookie) const {
  return CanAccessCookie(CHECK_DEREF(client_.get()), host_ && host_->web_ui(),
                         cookie);
}

// static
bool NetworkHandler::CanAccessCookie(DevToolsAgentHostClient& client,
                                     bool is_webui,
                                     const net::CanonicalCookie& cookie) {
  return client.MayAttachToURL(GURL(base::StrCat({url::kHttpsScheme,
                                                  url::kStandardSchemeSeparator,
                                                  cookie.DomainWithoutDot()})),
                               is_webui) &&
         client.MayAttachToURL(
             GURL(base::StrCat({url::kHttpScheme, url::kStandardSchemeSeparator,
                                cookie.DomainWithoutDot()})),
             is_webui);
}

void NetworkHandler::GetCookies(std::unique_ptr<Array<String>> protocol_urls,
                                std::unique_ptr<GetCookiesCallback> callback) {
  if (!host_ || !storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  std::vector<GURL> urls = ComputeCookieURLs(host_, protocol_urls);
  bool is_webui = host_ && host_->web_ui();

  std::erase_if(urls, [=, this](const GURL& url) {
    return !client_->MayAttachToURL(url, is_webui);
  });

  CookieRetrieverNetworkService::Retrieve(
      storage_partition_->GetCookieManagerForBrowserProcess(), urls,
      host_->GetNetworkIsolationKey(), host_->ComputeSiteForCookies(),
      std::move(callback));
}

void NetworkHandler::GetAllCookies(
    std::unique_ptr<GetAllCookiesCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  storage_partition_->GetCookieManagerForBrowserProcess()->GetAllCookies(
      base::BindOnce(&NetworkHandler::GotAllCookies, weak_factory_.GetWeakPtr(),
                     std::move(callback)));
}

void NetworkHandler::GotAllCookies(
    std::unique_ptr<GetAllCookiesCallback> callback,
    const std::vector<net::CanonicalCookie>& cookies) {
  bool is_webui = host_ && host_->web_ui();
  std::vector<net::CanonicalCookie> filtered_cookies;
  for (const auto& cookie : cookies) {
    if (NetworkHandler::CanAccessCookie(CHECK_DEREF(client_.get()), is_webui,
                                        cookie)) {
      filtered_cookies.emplace_back(std::move(cookie));
    }
  }
  callback->sendSuccess(NetworkHandler::BuildCookieArray(filtered_cookies));
}

void NetworkHandler::SetCookie(
    const std::string& name,
    const std::string& value,
    std::optional<std::string> url,
    std::optional<std::string> domain,
    std::optional<std::string> path,
    std::optional<bool> secure,
    std::optional<bool> http_only,
    std::optional<std::string> same_site,
    std::optional<double> expires,
    std::optional<std::string> priority,
    std::optional<std::string> source_scheme,
    std::optional<int> source_port,
    std::unique_ptr<Network::CookiePartitionKey> partition_key,
    std::unique_ptr<SetCookieCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  auto cookie_or_error = MakeCookieFromProtocolValues(
      name, value, url.value_or(""), domain.value_or(""), path.value_or(""),
      secure.value_or(false), http_only.value_or(false), same_site.value_or(""),
      expires.value_or(-1), priority.value_or(""), source_scheme, source_port,
      partition_key.get());

  if (std::holds_alternative<Response>(cookie_or_error)) {
    callback->sendFailure(std::get<Response>(std::move(cookie_or_error)));
    return;
  }
  std::unique_ptr<net::CanonicalCookie> cookie =
      std::get<std::unique_ptr<net::CanonicalCookie>>(
          std::move(cookie_or_error));

  if (!NetworkHandler::CanAccessCookie(CHECK_DEREF(client_.get()),
                                       host_ && host_->web_ui(), *cookie)) {
    callback->sendFailure(Response::ServerError("Permission denied"));
    return;
  }

  net::CookieOptions options;
  // Permit it to set a SameSite cookie if it wants to.
  options.set_same_site_cookie_context(
      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
  options.set_include_httponly();
  storage_partition_->GetCookieManagerForBrowserProcess()->SetCanonicalCookie(
      *cookie, net::cookie_util::SimulatedCookieSource(*cookie, "https"),
      options,
      base::BindOnce(net::cookie_util::IsCookieAccessResultInclude)
          .Then(base::BindOnce(&SetCookieCallback::sendSuccess,
                               std::move(callback))));
}

// static
void NetworkHandler::SetCookies(
    StoragePartition* storage_partition,
    std::unique_ptr<protocol::Array<Network::CookieParam>> cookies,
    DevToolsAgentHostClient& client,
    bool is_webui,
    base::OnceCallback<void(bool)> callback) {
  std::vector<std::unique_ptr<net::CanonicalCookie>> net_cookies;
  for (const std::unique_ptr<Network::CookieParam>& cookie : *cookies) {
    // We need to pass std::optional<> to the function below, but we can't
    // directly get to the `cookie`'s std::optional<> so instead we recreate
    // them.
    const std::optional<std::string> source_scheme =
        cookie->HasSourceScheme()
            ? std::optional<std::string>(cookie->GetSourceScheme(""))
            : std::nullopt;
    const std::optional<int> source_port =
        cookie->HasSourcePort() ? std::optional<int>(cookie->GetSourcePort(0))
                                : std::nullopt;

    std::unique_ptr<Network::CookiePartitionKey> partition_key;
    if (cookie->HasPartitionKey()) {
      protocol::Network::CookiePartitionKey* key =
          cookie->GetPartitionKey(nullptr);
      if (key) {
        std::string site = key->GetTopLevelSite();
        if (!site.empty()) {
          partition_key =
              BuildCookiePartitionKey(site, key->GetHasCrossSiteAncestor());
        }
      }
    }

    auto net_cookie_or_error = MakeCookieFromProtocolValues(
        cookie->GetName(), cookie->GetValue(), cookie->GetUrl(""),
        cookie->GetDomain(""), cookie->GetPath(""), cookie->GetSecure(false),
        cookie->GetHttpOnly(false), cookie->GetSameSite(""),
        cookie->GetExpires(-1), cookie->GetPriority(""), source_scheme,
        source_port, partition_key.get());
    if (std::holds_alternative<Response>(net_cookie_or_error)) {
      // TODO: Investiage whether we can report the error as a protocol error
      // (this might be a breaking CDP change).
      std::move(callback).Run(false);
      return;
    }
    auto net_cookie = std::get<std::unique_ptr<net::CanonicalCookie>>(
        std::move(net_cookie_or_error));
    if (!NetworkHandler::CanAccessCookie(client, is_webui, *net_cookie)) {
      std::move(callback).Run(false);
      return;
    }
    net_cookies.push_back(std::move(net_cookie));
  }

  base::RepeatingClosure barrier_closure = base::BarrierClosure(
      net_cookies.size(), base::BindOnce(std::move(callback), true));

  auto* cookie_manager = storage_partition->GetCookieManagerForBrowserProcess();
  net::CookieOptions options;
  options.set_include_httponly();
  // Permit it to set a SameSite cookie if it wants to.
  options.set_same_site_cookie_context(
      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
  for (const auto& cookie : net_cookies) {
    cookie_manager->SetCanonicalCookie(
        *cookie, net::cookie_util::SimulatedCookieSource(*cookie, "https"),
        options,
        base::BindOnce([](base::RepeatingClosure callback,
                          net::CookieAccessResult) { callback.Run(); },
                       barrier_closure));
  }
}

void NetworkHandler::SetCookies(
    std::unique_ptr<protocol::Array<Network::CookieParam>> cookies,
    std::unique_ptr<SetCookiesCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  CHECK(host_);

  NetworkHandler::SetCookies(
      storage_partition_, std::move(cookies), CHECK_DEREF(client_.get()),
      host_->web_ui(),
      base::BindOnce(
          [](std::unique_ptr<SetCookiesCallback> callback, bool success) {
            if (success) {
              callback->sendSuccess();
            } else {
              callback->sendFailure(
                  Response::InvalidParams(kInvalidCookieFields));
            }
          },
          std::move(callback)));
}

void NetworkHandler::DeleteCookies(
    const std::string& name,
    std::optional<std::string> url_spec,
    std::optional<std::string> domain,
    std::optional<std::string> path,
    std::unique_ptr<Network::CookiePartitionKey> partition_key,
    std::unique_ptr<DeleteCookiesCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  if (!url_spec.has_value() && !domain.has_value()) {
    callback->sendFailure(Response::InvalidParams(
        "At least one of the url and domain needs to be specified"));
  }

  std::string normalized_domain = domain.value_or("");
  if (normalized_domain.empty()) {
    GURL url(url_spec.value_or(""));
    if (!url.SchemeIsHTTPOrHTTPS()) {
      callback->sendFailure(Response::InvalidParams(
          "An http or https url URL must be specified"));
      return;
    }
    normalized_domain = url.GetHost();
  }

  auto* cookie_manager =
      storage_partition_->GetCookieManagerForBrowserProcess();

  cookie_manager->GetAllCookies(
      base::BindOnce(&DeleteFilteredCookies, base::Unretained(cookie_manager),
                     name, normalized_domain, path.value_or(""),
                     base::Owned(partition_key.release()),
                     /*filter_by_partition_key=*/true,
                     base::BindRepeating(
                         [](base::WeakPtr<NetworkHandler> handler,
                            const net::CanonicalCookie& cookie) {
                           return handler && handler->CanAccessCookie(cookie);
                         },
                         weak_factory_.GetWeakPtr()),
                     base::BindOnce(&DeleteCookiesCallback::sendSuccess,
                                    std::move(callback))));
}

Response NetworkHandler::SetExtraHTTPHeaders(
    std::unique_ptr<protocol::Network::Headers> headers) {
  std::vector<std::pair<std::string, std::string>> new_headers;
  for (const auto entry : *headers) {
    if (!entry.second.is_string()) {
      return Response::InvalidParams("Invalid header value, string expected");
    }
    if (!net::HttpUtil::IsValidHeaderName(entry.first)) {
      return Response::InvalidParams("Invalid header name");
    }
    const std::string& value = entry.second.GetString();
    if (!net::HttpUtil::IsValidHeaderValue(value)) {
      return Response::InvalidParams("Invalid header value");
    }
    new_headers.emplace_back(entry.first, value);
  }
  extra_headers_.swap(new_headers);
  return Response::FallThrough();
}

Response NetworkHandler::CanEmulateNetworkConditions(bool* result) {
  *result = true;
  return Response::Success();
}

Response NetworkHandler::EmulateNetworkConditions(
    bool offline,
    double latency,
    double download_throughput,
    double upload_throughput,
    std::optional<protocol::Network::ConnectionType>,
    std::optional<double> packet_loss,
    std::optional<int> packet_queue_length,
    std::optional<bool> packet_reordering) {
  std::vector<network::mojom::MatchedNetworkConditionsPtr> network_conditions;
  bool throttling_enabled = offline || latency > 0 || download_throughput > 0 ||
                            upload_throughput > 0;
  if (throttling_enabled) {
    network_conditions.push_back(
        network::mojom::MatchedNetworkConditions::New());
    network_conditions.back()->conditions =
        network::mojom::NetworkConditions::New();
    network_conditions.back()->conditions->offline = offline;
    network_conditions.back()->conditions->latency =
        base::Milliseconds(latency);
    network_conditions.back()->conditions->download_throughput =
        download_throughput;
    network_conditions.back()->conditions->upload_throughput =
        upload_throughput;
    network_conditions.back()->conditions->packet_loss =
        packet_loss.value_or(0.);
    network_conditions.back()->conditions->packet_queue_length =
        packet_queue_length.value_or(0);
    network_conditions.back()->conditions->packet_reordering =
        packet_reordering.value_or(false);
  }
  SetNetworkConditions(std::move(network_conditions), offline);
  return Response::FallThrough();
}

Response NetworkHandler::EmulateNetworkConditionsByRule(
    std::optional<bool> offline,
    std::optional<bool> emulate_offline_service_worker,
    std::unique_ptr<protocol::Array<protocol::Network::NetworkConditions>>
        matched_network_conditions,
    std::unique_ptr<protocol::Array<String>>* rule_ids_result) {
  std::vector<network::mojom::MatchedNetworkConditionsPtr> matched_conditions;
  *rule_ids_result = std::make_unique<protocol::Array<String>>();
  for (auto& matched_condition : *matched_network_conditions) {
    auto rule_id = base::UnguessableToken::Create();
    network::mojom::MatchedNetworkConditionsPtr conditions =
        network::mojom::MatchedNetworkConditions::New();
    conditions->pattern = matched_condition->GetUrlPattern();
    conditions->conditions = network::mojom::NetworkConditions::New();
    conditions->conditions->offline =
        offline.has_value() ? offline.value()
                            : matched_condition->GetOffline(false);
    conditions->conditions->latency =
        base::Milliseconds(matched_condition->GetLatency());
    conditions->conditions->download_throughput =
        matched_condition->GetDownloadThroughput();
    conditions->conditions->upload_throughput =
        matched_condition->GetUploadThroughput();
    conditions->conditions->packet_loss = matched_condition->GetPacketLoss(0.);
    conditions->conditions->packet_queue_length =
        matched_condition->GetPacketQueueLength(0);
    conditions->conditions->packet_reordering =
        matched_condition->GetPacketReordering(false);
    conditions->conditions->rule_id = rule_id;
    rule_ids_result->get()->push_back(rule_id.ToString());
    matched_conditions.emplace_back(std::move(conditions));
  }
  SetNetworkConditions(
      std::move(matched_conditions),
      emulate_offline_service_worker.value_or(offline.value_or(false)));
  return Response::Success();
}

Response NetworkHandler::SetBypassServiceWorker(bool bypass) {
  bypass_service_worker_ = bypass;
  return Response::FallThrough();
}

namespace {

std::unique_ptr<protocol::Network::SecurityDetails> BuildSecurityDetails(
    const net::SSLInfo& ssl_info) {
  // This function should be kept in sync with the corresponding function in
  // inspector_network_agent.cc in //third_party/blink.
  if (!ssl_info.cert) {
    return nullptr;
  }
  auto signed_certificate_timestamp_list =
      std::make_unique<protocol::Array<Network::SignedCertificateTimestamp>>();
  for (auto const& sct : ssl_info.signed_certificate_timestamps) {
    std::unique_ptr<protocol::Network::SignedCertificateTimestamp>
        signed_certificate_timestamp =
            Network::SignedCertificateTimestamp::Create()
                .SetStatus(net::ct::StatusToString(sct.status))
                .SetOrigin(net::ct::OriginToString(sct.sct->origin))
                .SetLogDescription(sct.sct->log_description)
                .SetLogId(base::HexEncode(sct.sct->log_id))
                .SetTimestamp((sct.sct->timestamp - base::Time::UnixEpoch())
                                  .InMillisecondsF())
                .SetHashAlgorithm(net::ct::HashAlgorithmToString(
                    sct.sct->signature.hash_algorithm))
                .SetSignatureAlgorithm(net::ct::SignatureAlgorithmToString(
                    sct.sct->signature.signature_algorithm))
                .SetSignatureData(
                    base::HexEncode(sct.sct->signature.signature_data))
                .Build();
    signed_certificate_timestamp_list->emplace_back(
        std::move(signed_certificate_timestamp));
  }
  std::vector<std::string> san_dns;
  std::vector<std::string> san_ip;
  ssl_info.cert->GetSubjectAltName(&san_dns, &san_ip);
  auto san_list = std::make_unique<protocol::Array<String>>(std::move(san_dns));
  for (const std::string& san : san_ip) {
    san_list->emplace_back(net::IPAddress(base::as_byte_span(san)).ToString());
  }

  const char* protocol = "";
  const char* key_exchange = "";
  const char* cipher = "";
  const char* mac = nullptr;

  int ssl_version =
      net::SSLConnectionStatusToVersion(ssl_info.connection_status);

  if (ssl_info.connection_status) {
    net::SSLVersionToString(&protocol, ssl_version);

    bool is_aead;
    bool is_tls13;
    uint16_t cipher_suite =
        net::SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
    net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead,
                                 &is_tls13, cipher_suite);
    if (key_exchange == nullptr) {
      DCHECK(is_tls13);
      key_exchange = "";
    }
  }

  std::unique_ptr<protocol::Network::SecurityDetails> security_details =
      protocol::Network::SecurityDetails::Create()
          .SetProtocol(protocol)
          .SetKeyExchange(key_exchange)
          .SetCipher(cipher)
          .SetSubjectName(ssl_info.cert->subject().common_name)
          .SetSanList(std::move(san_list))
          .SetIssuer(ssl_info.cert->issuer().common_name)
          .SetValidFrom(ssl_info.cert->valid_start().InSecondsFSinceUnixEpoch())
          .SetValidTo(ssl_info.cert->valid_expiry().InSecondsFSinceUnixEpoch())
          .SetCertificateId(0)  // Keep this in protocol for compatibility.
          .SetSignedCertificateTimestampList(
              std::move(signed_certificate_timestamp_list))
          .SetCertificateTransparencyCompliance(
              SerializeCTPolicyCompliance(ssl_info.ct_policy_compliance))
          .SetEncryptedClientHello(ssl_info.encrypted_client_hello)
          .Build();

  if (ssl_info.key_exchange_group != 0) {
    const char* key_exchange_group =
        SSL_get_curve_name(ssl_info.key_exchange_group);
    if (key_exchange_group) {
      security_details->SetKeyExchangeGroup(key_exchange_group);
    }
  }
  if (mac) {
    security_details->SetMac(mac);
  }
  if (ssl_info.peer_signature_algorithm != 0) {
    security_details->SetServerSignatureAlgorithm(
        ssl_info.peer_signature_algorithm);
  }

  return security_details;
}

std::unique_ptr<base::DictValue> BuildResponseHeaders(
    const net::HttpResponseHeaders* headers) {
  auto headers_dict = std::make_unique<base::DictValue>();
  if (!headers) {
    return headers_dict;
  }
  size_t iterator = 0;
  std::string name;
  std::string value;
  while (headers->EnumerateHeaderLines(&iterator, &name, &value)) {
    base::Value* header_value = headers_dict->Find(name);
    if (header_value) {
      *header_value = base::Value(header_value->GetString() + '\n' + value);
    } else {
      headers_dict->Set(name, value);
    }
  }
  return headers_dict;
}

std::unique_ptr<base::DictValue> BuildRequestHeaders(
    const net::HttpRequestHeaders& headers,
    const GURL& referrer) {
  auto headers_dict = std::make_unique<base::DictValue>();
  for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) {
    headers_dict->Set(it.name(), it.value());
  }

  // This is normally added down the stack, so we have to fake it here.
  if (!referrer.is_empty()) {
    headers_dict->Set(net::HttpRequestHeaders::kReferer, referrer.spec());
  }

  return headers_dict;
}

String BuildServiceWorkerResponseSource(
    const network::mojom::URLResponseHeadDevToolsInfo& info) {
  switch (info.service_worker_response_source) {
    case network::mojom::FetchResponseSource::kCacheStorage:
      return protocol::Network::ServiceWorkerResponseSourceEnum::CacheStorage;
    case network::mojom::FetchResponseSource::kHttpCache:
      return protocol::Network::ServiceWorkerResponseSourceEnum::HttpCache;
    case network::mojom::FetchResponseSource::kNetwork:
      return protocol::Network::ServiceWorkerResponseSourceEnum::Network;
    case network::mojom::FetchResponseSource::kUnspecified:
      return protocol::Network::ServiceWorkerResponseSourceEnum::FallbackCode;
  }
}

String BuildServiceWorkerRouterSourceType(
    const network::mojom::ServiceWorkerRouterSourceType& type) {
  switch (type) {
    case network::mojom::ServiceWorkerRouterSourceType::kNetwork:
      return protocol::Network::ServiceWorkerRouterSourceEnum::Network;
    case network::mojom::ServiceWorkerRouterSourceType::
        kRaceNetworkAndFetchEvent:
      return protocol::Network::ServiceWorkerRouterSourceEnum::
          RaceNetworkAndFetchHandler;
    case network::mojom::ServiceWorkerRouterSourceType::kFetchEvent:
      return protocol::Network::ServiceWorkerRouterSourceEnum::FetchEvent;
    case network::mojom::ServiceWorkerRouterSourceType::kCache:
      return protocol::Network::ServiceWorkerRouterSourceEnum::Cache;
    case network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache:
      return protocol::Network::ServiceWorkerRouterSourceEnum::
          RaceNetworkAndCache;
  }
}

String AlternateProtocolUsageToString(
    net::AlternateProtocolUsage alternate_protocol_usage) {
  switch (alternate_protocol_usage) {
    case net::AlternateProtocolUsage::ALTERNATE_PROTOCOL_USAGE_NO_RACE:
      return protocol::Network::AlternateProtocolUsageEnum::
          AlternativeJobWonWithoutRace;
    case net::AlternateProtocolUsage::ALTERNATE_PROTOCOL_USAGE_WON_RACE:
      return protocol::Network::AlternateProtocolUsageEnum::
          AlternativeJobWonRace;
    case net::AlternateProtocolUsage::
        ALTERNATE_PROTOCOL_USAGE_MAIN_JOB_WON_RACE:
      return protocol::Network::AlternateProtocolUsageEnum::MainJobWonRace;
    case net::AlternateProtocolUsage::ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING:
      return protocol::Network::AlternateProtocolUsageEnum::MappingMissing;
    case net::AlternateProtocolUsage::ALTERNATE_PROTOCOL_USAGE_BROKEN:
      return protocol::Network::AlternateProtocolUsageEnum::Broken;
    case net::AlternateProtocolUsage::
        ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_WITHOUT_RACE:
      return protocol::Network::AlternateProtocolUsageEnum::
          DnsAlpnH3JobWonWithoutRace;
    case net::AlternateProtocolUsage::
        ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_RACE:
      return protocol::Network::AlternateProtocolUsageEnum::DnsAlpnH3JobWonRace;
    case net::AlternateProtocolUsage::
        ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON:
      return protocol::Network::AlternateProtocolUsageEnum::UnspecifiedReason;
    case net::AlternateProtocolUsage::ALTERNATE_PROTOCOL_USAGE_MAX:
      return protocol::Network::AlternateProtocolUsageEnum::UnspecifiedReason;
  }
  return protocol::Network::AlternateProtocolUsageEnum::UnspecifiedReason;
}

std::unique_ptr<Network::Response> BuildResponse(
    const GURL& url,
    const network::mojom::URLResponseHeadDevToolsInfo& info) {
  int status = 0;
  std::string status_text;
  if (info.headers) {
    status = info.headers->response_code();
    status_text = info.headers->GetStatusText();
  } else if (url.SchemeIs(url::kDataScheme)) {
    status = net::HTTP_OK;
    status_text = "OK";
  }

  const bool was_cached =
      !info.load_timing.request_start_time.is_null() &&
      info.response_time < info.load_timing.request_start_time;

  std::string url_fragment;
  auto response =
      Network::Response::Create()
          .SetUrl(NetworkHandler::ExtractFragment(url, &url_fragment))
          .SetStatus(status)
          .SetStatusText(status_text)
          .SetHeaders(BuildResponseHeaders(info.headers.get()))
          .SetMimeType(info.mime_type)
          .SetCharset(info.charset)
          .SetConnectionReused(info.load_timing.socket_reused)
          .SetConnectionId(info.load_timing.socket_log_id)
          .SetSecurityState(securityState(url, info.cert_status))
          .SetEncodedDataLength(info.encoded_data_length)
          .SetTiming(GetTiming(info.load_timing))
          .SetFromDiskCache(was_cached)
          .Build();
  response->SetFromServiceWorker(info.was_fetched_via_service_worker);
  if (info.was_fetched_via_service_worker) {
    response->SetServiceWorkerResponseSource(
        BuildServiceWorkerResponseSource(info));
  }
  response->SetFromPrefetchCache(info.was_in_prefetch_cache);
  if (!info.response_time.is_null()) {
    response->SetResponseTime(
        info.response_time.InMillisecondsFSinceUnixEpochIgnoringNull());
  }
  if (!info.cache_storage_cache_name.empty()) {
    response->SetCacheStorageCacheName(info.cache_storage_cache_name);
  }
  if (!info.service_worker_router_info.is_null()) {
    auto service_worker_router_info =
        protocol::Network::ServiceWorkerRouterInfo::Create().Build();
    if (info.service_worker_router_info->rule_id_matched) {
      service_worker_router_info->SetRuleIdMatched(
          *info.service_worker_router_info->rule_id_matched);
    }

    if (info.service_worker_router_info->matched_source_type) {
      service_worker_router_info->SetMatchedSourceType(
          BuildServiceWorkerRouterSourceType(
              *info.service_worker_router_info->matched_source_type));
    }

    if (info.service_worker_router_info->actual_source_type) {
      service_worker_router_info->SetActualSourceType(
          BuildServiceWorkerRouterSourceType(
              *info.service_worker_router_info->actual_source_type));
    }

    response->SetServiceWorkerRouterInfo(std::move(service_worker_router_info));
  }

  response->SetProtocol(GetProtocol(url, info));
  if (info.alternate_protocol_usage !=
      net::AlternateProtocolUsage::
          ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON) {
    response->SetAlternateProtocolUsage(
        AlternateProtocolUsageToString(info.alternate_protocol_usage));
  }
  response->SetRemoteIPAddress(
      net::HostPortPair::FromIPEndPoint(info.remote_endpoint).HostForURL());
  response->SetRemotePort(info.remote_endpoint.port());
  if (info.ssl_info.has_value()) {
    response->SetSecurityDetails(BuildSecurityDetails(*info.ssl_info));
  }

  return response;
}

std::unique_ptr<Network::Response> BuildRedirectResponse(
    std::optional<std::pair<const GURL&,
                            const network::mojom::URLResponseHeadDevToolsInfo&>>
        redirect_info,
    bool& redirect_emitted_extra_info) {
  std::unique_ptr<Network::Response> redirect_response;
  if (redirect_info) {
    const auto& [previous_url, head] = *redirect_info;
    redirect_emitted_extra_info = head.emitted_extra_info;
    redirect_response = BuildResponse(previous_url, head);
  }
  return redirect_response;
}

String blockedReason(blink::ResourceRequestBlockedReason reason) {
  switch (reason) {
    case blink::ResourceRequestBlockedReason::kCSP:
      return protocol::Network::BlockedReasonEnum::Csp;
    case blink::ResourceRequestBlockedReason::kMixedContent:
      return protocol::Network::BlockedReasonEnum::MixedContent;
    case blink::ResourceRequestBlockedReason::kOrigin:
      return protocol::Network::BlockedReasonEnum::Origin;
    case blink::ResourceRequestBlockedReason::kInspector:
      return protocol::Network::BlockedReasonEnum::Inspector;
    case blink::ResourceRequestBlockedReason::kIntegrity:
      return protocol::Network::BlockedReasonEnum::Integrity;
    case blink::ResourceRequestBlockedReason::kSubresourceFilter:
      return protocol::Network::BlockedReasonEnum::SubresourceFilter;
    case blink::ResourceRequestBlockedReason::kContentType:
      return protocol::Network::BlockedReasonEnum::ContentType;
    case blink::ResourceRequestBlockedReason::kOther:
      return protocol::Network::BlockedReasonEnum::Other;
    case blink::ResourceRequestBlockedReason::kCoepFrameResourceNeedsCoepHeader:
      return protocol::Network::BlockedReasonEnum::
          CoepFrameResourceNeedsCoepHeader;
    case blink::ResourceRequestBlockedReason::
        kCoopSandboxedIFrameCannotNavigateToCoopPage:
      return protocol::Network::BlockedReasonEnum::
          CoopSandboxedIframeCannotNavigateToCoopPage;
    case blink::ResourceRequestBlockedReason::kCorpNotSameOrigin:
      return protocol::Network::BlockedReasonEnum::CorpNotSameOrigin;
    case blink::ResourceRequestBlockedReason::
        kCorpNotSameOriginAfterDefaultedToSameOriginByCoep:
      return protocol::Network::BlockedReasonEnum::
          CorpNotSameOriginAfterDefaultedToSameOriginByCoep;
    case blink::ResourceRequestBlockedReason::
        kCorpNotSameOriginAfterDefaultedToSameOriginByDip:
      return protocol::Network::BlockedReasonEnum::
          CorpNotSameOriginAfterDefaultedToSameOriginByDip;
    case blink::ResourceRequestBlockedReason::
        kCorpNotSameOriginAfterDefaultedToSameOriginByCoepAndDip:
      return protocol::Network::BlockedReasonEnum::
          CorpNotSameOriginAfterDefaultedToSameOriginByCoep;
    case blink::ResourceRequestBlockedReason::kCorpNotSameSite:
      return protocol::Network::BlockedReasonEnum::CorpNotSameSite;
    case blink::ResourceRequestBlockedReason::kSRIMessageSignatureMismatch:
      return protocol::Network::BlockedReasonEnum::SriMessageSignatureMismatch;
    case blink::ResourceRequestBlockedReason::kConversionRequest:
      // This is actually never reached, as the conversion request
      // is marked as successful and no blocking reason is reported.
      NOTREACHED();
  }
  NOTREACHED();
}

std::optional<String> GetBlockedReasonFor(
    const network::URLLoaderCompletionStatus& status) {
  if (status.blocked_by_response_reason) {
    switch (*status.blocked_by_response_reason) {
      case network::mojom::BlockedByResponseReason::
          kCoepFrameResourceNeedsCoepHeader:
        return {protocol::Network::BlockedReasonEnum::
                    CoepFrameResourceNeedsCoepHeader};
      case network::mojom::BlockedByResponseReason::
          kCoopSandboxedIFrameCannotNavigateToCoopPage:
        return {protocol::Network::BlockedReasonEnum::
                    CoopSandboxedIframeCannotNavigateToCoopPage};
      case network::mojom::BlockedByResponseReason::
          kCorpNotSameOriginAfterDefaultedToSameOriginByCoep:
        return {protocol::Network::BlockedReasonEnum::
                    CorpNotSameOriginAfterDefaultedToSameOriginByCoep};
      case network::mojom::BlockedByResponseReason::
          kCorpNotSameOriginAfterDefaultedToSameOriginByDip:
        return {protocol::Network::BlockedReasonEnum::
                    CorpNotSameOriginAfterDefaultedToSameOriginByDip};
      case network::mojom::BlockedByResponseReason::
          kCorpNotSameOriginAfterDefaultedToSameOriginByCoepAndDip:
        return {protocol::Network::BlockedReasonEnum::
                    CorpNotSameOriginAfterDefaultedToSameOriginByCoepAndDip};
      case network::mojom::BlockedByResponseReason::kCorpNotSameOrigin:
        return {protocol::Network::BlockedReasonEnum::CorpNotSameOrigin};
      case network::mojom::BlockedByResponseReason::kCorpNotSameSite:
        return {protocol::Network::BlockedReasonEnum::CorpNotSameSite};
      case network::mojom::BlockedByResponseReason::
          kSRIMessageSignatureMismatch:
        return {
            protocol::Network::BlockedReasonEnum::SriMessageSignatureMismatch};
    }
    NOTREACHED();
  }
  if (status.error_code != net::ERR_BLOCKED_BY_CLIENT &&
      status.error_code != net::ERR_BLOCKED_BY_RESPONSE) {
    return std::nullopt;
  }

  if (status.extended_error_code <=
      static_cast<int>(blink::ResourceRequestBlockedReason::kMax)) {
    return blockedReason(static_cast<blink::ResourceRequestBlockedReason>(
        status.extended_error_code));
  }

  // TODO(karandeepb): Embedder would know how to interpret the
  // `status.extended_error_code` in this case. For now just return Other.
  return {protocol::Network::BlockedReasonEnum::Other};
}

String GetTrustTokenOperationType(
    network::mojom::TrustTokenOperationType operation) {
  switch (operation) {
    case network::mojom::TrustTokenOperationType::kIssuance:
      return protocol::Network::TrustTokenOperationTypeEnum::Issuance;
    case network::mojom::TrustTokenOperationType::kRedemption:
      return protocol::Network::TrustTokenOperationTypeEnum::Redemption;
    case network::mojom::TrustTokenOperationType::kSigning:
      return protocol::Network::TrustTokenOperationTypeEnum::Signing;
  }
}

String GetTrustTokenRefreshPolicy(
    network::mojom::TrustTokenRefreshPolicy policy) {
  switch (policy) {
    case network::mojom::TrustTokenRefreshPolicy::kUseCached:
      return protocol::Network::TrustTokenParams::RefreshPolicyEnum::UseCached;
    case network::mojom::TrustTokenRefreshPolicy::kRefresh:
      return protocol::Network::TrustTokenParams::RefreshPolicyEnum::Refresh;
  }
}

std::unique_ptr<protocol::Network::TrustTokenParams> BuildTrustTokenParams(
    const network::mojom::TrustTokenParams& params) {
  auto protocol_params =
      protocol::Network::TrustTokenParams::Create()
          .SetOperation(GetTrustTokenOperationType(params.operation))
          .SetRefreshPolicy(GetTrustTokenRefreshPolicy(params.refresh_policy))
          .Build();

  if (!params.issuers.empty()) {
    auto issuers = std::make_unique<protocol::Array<protocol::String>>();
    for (const auto& issuer : params.issuers) {
      issuers->push_back(issuer.Serialize());
    }
    protocol_params->SetIssuers(std::move(issuers));
  }

  return protocol_params;
}

}  // namespace

void NetworkHandler::PrefetchRequestWillBeSent(
    const std::string& request_id,
    const network::ResourceRequest& request,
    const GURL& initiator_url,
    std::optional<std::string> frame_token,
    base::TimeTicks timestamp,
    std::optional<std::pair<const GURL&,
                            const network::mojom::URLResponseHeadDevToolsInfo&>>
        redirect_info) {
  if (!enabled_) {
    return;
  }

  std::string url = request.url.is_valid() ? request.url.spec() : "";
  double current_ticks = timestamp.since_origin().InSecondsF();
  double current_wall_time = base::Time::Now().InSecondsFSinceUnixEpoch();
  auto initiator =
      Network::Initiator::Create()
          .SetType(Network::Initiator::TypeEnum::Script)
          .SetUrl(initiator_url.is_valid() ? initiator_url.spec() : "")
          .Build();

  bool redirect_emitted_extra_info = false;
  std::unique_ptr<Network::Response> redirect_response =
      BuildRedirectResponse(redirect_info, redirect_emitted_extra_info);

  auto request_info =
      Network::Request::Create()
          .SetUrl(url)
          .SetMethod(request.method)
          .SetHeaders(BuildRequestHeaders(request.headers, request.referrer))
          .SetInitialPriority(resourcePriority(request.priority))
          .SetReferrerPolicy(referrerPolicy(request.referrer_policy))
          .Build();

  if (request.is_ad_tagged) {
    request_info->SetIsAdRelated(true);
  }

  frontend_->RequestWillBeSent(
      request_id, request_id, url, std::move(request_info), current_ticks,
      current_wall_time, std::move(initiator), redirect_emitted_extra_info,
      std::move(redirect_response),
      std::string(Network::ResourceTypeEnum::Prefetch), std::move(frame_token),
      request.has_user_gesture);
}

void NetworkHandler::NavigationRequestWillBeSent(
    const NavigationRequest& nav_request,
    base::TimeTicks timestamp) {
  if (!enabled_) {
    return;
  }

  const blink::mojom::CommonNavigationParams& common_params =
      nav_request.common_params();
  net::HttpRequestHeaders headers;
  headers.AddHeadersFromString(nav_request.begin_params().headers);

  std::unique_ptr<Network::Response> redirect_response;
  const blink::mojom::CommitNavigationParams& commit_params =
      nav_request.commit_params();
  bool redirect_emitted_extra_info = false;
  if (!commit_params.redirect_response.empty()) {
    const network::mojom::URLResponseHead& head =
        *commit_params.redirect_response.back();
    network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
        network::ExtractDevToolsInfo(head);
    redirect_response =
        BuildResponse(commit_params.redirects.back(), *head_info);
    redirect_emitted_extra_info = head_info->emitted_extra_info;
  }
  std::string url_fragment;
  std::string url_without_fragment =
      ExtractFragment(common_params.url, &url_fragment);
  auto request =
      Network::Request::Create()
          .SetUrl(url_without_fragment)
          .SetMethod(common_params.method)
          .SetHeaders(BuildRequestHeaders(headers, common_params.referrer->url))
          .SetInitialPriority(resourcePriority(net::HIGHEST))
          .SetReferrerPolicy(referrerPolicy(common_params.referrer->policy))
          .Build();

  if (!url_fragment.empty()) {
    request->SetUrlFragment(url_fragment);
  }

  if (common_params.post_data) {
    request->SetHasPostData(true);
    std::string post_data;
    auto data_entries =
        std::make_unique<protocol::Array<protocol::Network::PostDataEntry>>();
    if (GetPostData(*common_params.post_data, data_entries.get(), &post_data)) {
      if (!post_data.empty()) {
        request->SetPostData(post_data);
      }
      if (data_entries->size()) {
        request->SetPostDataEntries(std::move(data_entries));
      }
    }
  }
  // TODO(caseq): report potentially blockable types
  request->SetMixedContentType(Security::MixedContentTypeEnum::None);

  std::unique_ptr<Network::Initiator> initiator;
  const std::optional<base::DictValue>& initiator_optional =
      nav_request.begin_params().devtools_initiator;
  if (initiator_optional.has_value()) {
    crdtp::ConvertProtocolValue(initiator_optional.value(), &initiator);
  }
  if (!initiator) {
    initiator = Network::Initiator::Create()
                    .SetType(Network::Initiator::TypeEnum::Other)
                    .Build();
  }
  std::string id = nav_request.devtools_navigation_token().ToString();
  double current_ticks = timestamp.since_origin().InSecondsF();
  double current_wall_time = base::Time::Now().InSecondsFSinceUnixEpoch();
  std::string frame_token = nav_request.frame_tree_node()
                                ->current_frame_host()
                                ->devtools_frame_token()
                                .ToString();

  const blink::mojom::BeginNavigationParams& begin_params =
      nav_request.begin_params();
  if (begin_params.trust_token_params) {
    request->SetTrustTokenParams(
        BuildTrustTokenParams(*begin_params.trust_token_params));
  }

  if (host_) {
    if (nav_request.frame_tree_node()->IsOutermostMainFrame()) {
      request->SetIsSameSite(true);
    } else {
      request->SetIsSameSite(
          host_->ComputeSiteForCookies().IsFirstParty(common_params.url));
    }
  }

  if (nav_request.is_ad_tagged()) {
    request->SetIsAdRelated(true);
  }

  frontend_->RequestWillBeSent(
      id, id, url_without_fragment, std::move(request), current_ticks,
      current_wall_time, std::move(initiator), redirect_emitted_extra_info,
      std::move(redirect_response),
      std::string(Network::ResourceTypeEnum::Document), std::move(frame_token),
      common_params.has_possibly_filtered_user_gesture);
}

void NetworkHandler::FencedFrameReportRequestSent(
    const std::string& request_id,
    const network::ResourceRequest& request,
    const std::string& event_data,
    base::TimeTicks timestamp) {
  if (!enabled_) {
    return;
  }

  CHECK(request.url.is_valid());
  double current_ticks = timestamp.since_origin().InSecondsF();
  double current_wall_time = base::Time::Now().InSecondsFSinceUnixEpoch();
  auto initiator = Network::Initiator::Create()
                       .SetType(Network::Initiator::TypeEnum::Other)
                       .SetRequestId(request_id)
                       .Build();

  auto request_info =
      Network::Request::Create()
          .SetUrl(request.url.spec())
          .SetMethod(request.method)
          .SetHeaders(BuildRequestHeaders(request.headers, request.referrer))
          .SetInitialPriority(resourcePriority(request.priority))
          .SetReferrerPolicy(referrerPolicy(request.referrer_policy))
          .Build();

  if (!event_data.empty()) {
    request_info->SetHasPostData(true);
    request_info->SetPostData(event_data);
  }

  if (request.is_ad_tagged) {
    request_info->SetIsAdRelated(true);
  }

  frontend_->RequestWillBeSent(
      request_id, request_id, request.url.spec(), std::move(request_info),
      current_ticks, current_wall_time, std::move(initiator),
      /*redirectHasExtraInfo=*/false, std::unique_ptr<Network::Response>(),
      std::string(Network::ResourceTypeEnum::Other),
      std::nullopt /* frame_id */, request.has_user_gesture);
}

void NetworkHandler::RequestSent(
    const std::string& request_id,
    const std::string& loader_id,
    const net::HttpRequestHeaders& request_headers,
    const network::mojom::URLRequestDevToolsInfo& request_info,
    const char* initiator_type,
    const std::optional<GURL>& initiator_url,
    const std::string& initiator_devtools_request_id,
    std::optional<base::UnguessableToken> frame_token,
    base::TimeTicks timestamp) {
  if (!enabled_) {
    return;
  }
  std::unique_ptr<Network::Initiator> initiator =
      Network::Initiator::Create().SetType(initiator_type).Build();
  if (initiator_url) {
    initiator->SetUrl(initiator_url->spec());
  }
  if (initiator_devtools_request_id.size()) {
    initiator->SetRequestId(initiator_devtools_request_id);
  }
  std::string url_fragment;
  std::string url_without_fragment =
      ExtractFragment(request_info.url, &url_fragment);
  auto request_object =
      Network::Request::Create()
          .SetUrl(url_without_fragment)
          .SetMethod(request_info.method)
          .SetHeaders(BuildRequestHeaders(request_headers, GURL()))
          .SetInitialPriority(resourcePriority(request_info.priority))
          .SetReferrerPolicy(referrerPolicy(request_info.referrer_policy))
          .Build();
  if (!url_fragment.empty()) {
    request_object->SetUrlFragment(url_fragment);
  }
  if (request_info.trust_token_params) {
    request_object->SetTrustTokenParams(
        BuildTrustTokenParams(*request_info.trust_token_params));
  }

  if (request_info.is_ad_related) {
    request_object->SetIsAdRelated(true);
  }

  std::string resource_type = Network::ResourceTypeEnum::Other;
  if (request_info.resource_type ==
          static_cast<int>(blink::mojom::ResourceType::kWorker) ||
      request_info.resource_type ==
          static_cast<int>(blink::mojom::ResourceType::kSharedWorker) ||
      request_info.resource_type ==
          static_cast<int>(blink::mojom::ResourceType::kServiceWorker)) {
    resource_type = Network::ResourceTypeEnum::Script;
  }

  std::optional<std::string> frame_id;
  if (frame_token.has_value()) {
    frame_id = frame_token->ToString();
  }

  // TODO(crbug.com/40798984): Populate redirectHasExtraInfo instead of
  // just returning false.
  frontend_->RequestWillBeSent(
      request_id, loader_id, url_without_fragment, std::move(request_object),
      timestamp.since_origin().InSecondsF(),
      base::Time::Now().InSecondsFSinceUnixEpoch(), std::move(initiator),
      /*redirectHasExtraInfo=*/false, std::unique_ptr<Network::Response>(),
      resource_type, std::move(frame_id), request_info.has_user_gesture);
}

namespace {
String BuildCorsError(network::mojom::CorsError cors_error) {
  switch (cors_error) {
    case network::mojom::CorsError::kDisallowedByMode:
      return protocol::Network::CorsErrorEnum::DisallowedByMode;

    case network::mojom::CorsError::kInvalidResponse:
      return protocol::Network::CorsErrorEnum::InvalidResponse;

    case network::mojom::CorsError::kWildcardOriginNotAllowed:
      return protocol::Network::CorsErrorEnum::WildcardOriginNotAllowed;

    case network::mojom::CorsError::kMissingAllowOriginHeader:
      return protocol::Network::CorsErrorEnum::MissingAllowOriginHeader;

    case network::mojom::CorsError::kMultipleAllowOriginValues:
      return protocol::Network::CorsErrorEnum::MultipleAllowOriginValues;

    case network::mojom::CorsError::kInvalidAllowOriginValue:
      return protocol::Network::CorsErrorEnum::InvalidAllowOriginValue;

    case network::mojom::CorsError::kAllowOriginMismatch:
      return protocol::Network::CorsErrorEnum::AllowOriginMismatch;

    case network::mojom::CorsError::kInvalidAllowCredentials:
      return protocol::Network::CorsErrorEnum::InvalidAllowCredentials;

    case network::mojom::CorsError::kCorsDisabledScheme:
      return protocol::Network::CorsErrorEnum::CorsDisabledScheme;

    case network::mojom::CorsError::kPreflightInvalidStatus:
      return protocol::Network::CorsErrorEnum::PreflightInvalidStatus;

    case network::mojom::CorsError::kPreflightDisallowedRedirect:
      return protocol::Network::CorsErrorEnum::PreflightDisallowedRedirect;

    case network::mojom::CorsError::kPreflightWildcardOriginNotAllowed:
      return protocol::Network::CorsErrorEnum::
          PreflightWildcardOriginNotAllowed;

    case network::mojom::CorsError::kPreflightMissingAllowOriginHeader:
      return protocol::Network::CorsErrorEnum::
          PreflightMissingAllowOriginHeader;

    case network::mojom::CorsError::kPreflightMultipleAllowOriginValues:
      return protocol::Network::CorsErrorEnum::
          PreflightMultipleAllowOriginValues;

    case network::mojom::CorsError::kPreflightInvalidAllowOriginValue:
      return protocol::Network::CorsErrorEnum::PreflightInvalidAllowOriginValue;

    case network::mojom::CorsError::kPreflightAllowOriginMismatch:
      return protocol::Network::CorsErrorEnum::PreflightAllowOriginMismatch;

    case network::mojom::CorsError::kPreflightInvalidAllowCredentials:
      return protocol::Network::CorsErrorEnum::PreflightInvalidAllowCredentials;

    case network::mojom::CorsError::kInvalidAllowMethodsPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          InvalidAllowMethodsPreflightResponse;

    case network::mojom::CorsError::kInvalidAllowHeadersPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          InvalidAllowHeadersPreflightResponse;

    case network::mojom::CorsError::kMethodDisallowedByPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          MethodDisallowedByPreflightResponse;

    case network::mojom::CorsError::kHeaderDisallowedByPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          HeaderDisallowedByPreflightResponse;

    case network::mojom::CorsError::kRedirectContainsCredentials:
      return protocol::Network::CorsErrorEnum::RedirectContainsCredentials;

    case network::mojom::CorsError::kInsecureLocalNetwork:
      return protocol::Network::CorsErrorEnum::InsecureLocalNetwork;

    case network::mojom::CorsError::kInvalidLocalNetworkAccess:
      return protocol::Network::CorsErrorEnum::InvalidLocalNetworkAccess;

    case network::mojom::CorsError::kLocalNetworkAccessPermissionDenied:
      return protocol::Network::CorsErrorEnum::
          LocalNetworkAccessPermissionDenied;
  }
}
}  // namespace

void NetworkHandler::ResponseReceived(
    const std::string& request_id,
    const std::string& loader_id,
    const GURL& url,
    const char* resource_type,
    const network::mojom::URLResponseHeadDevToolsInfo& head,
    std::optional<std::string> frame_id) {
  if (!enabled_) {
    return;
  }
  std::unique_ptr<Network::Response> response(BuildResponse(url, head));
  frontend_->ResponseReceived(
      request_id, loader_id,
      base::TimeTicks::Now().ToInternalValue() /
          static_cast<double>(base::Time::kMicrosecondsPerSecond),
      resource_type, std::move(response), head.emitted_extra_info,
      std::move(frame_id));
}

void NetworkHandler::LoadingComplete(
    const std::string& request_id,
    const char* resource_type,
    const network::URLLoaderCompletionStatus& status) {
  if (!enabled_) {
    return;
  }
  if (status.error_code != net::OK) {
    frontend_->LoadingFailed(
        request_id,
        base::TimeTicks::Now().ToInternalValue() /
            static_cast<double>(base::Time::kMicrosecondsPerSecond),
        resource_type, net::ErrorToString(status.error_code),
        status.error_code == net::Error::ERR_ABORTED,
        GetBlockedReasonFor(status),
        status.cors_error_status
            ? BuildCorsErrorStatus(*status.cors_error_status)
            : nullptr);
    return;
  }
  frontend_->LoadingFinished(
      request_id,
      status.completion_time.ToInternalValue() /
          static_cast<double>(base::Time::kMicrosecondsPerSecond),
      status.encoded_data_length);
}

void NetworkHandler::FetchKeepAliveRequestWillBeSent(
    const std::string& request_id,
    const network::ResourceRequest& request,
    const GURL& initiator_url,
    std::optional<std::string> frame_token,
    base::TimeTicks timestamp,
    std::optional<std::pair<const GURL&,
                            const network::mojom::URLResponseHeadDevToolsInfo&>>
        redirect_info) {
  if (!enabled_) {
    return;
  }

  std::string url = request.url.is_valid() ? request.url.spec() : "";
  double current_ticks = timestamp.since_origin().InSecondsF();
  double current_wall_time = base::Time::Now().InSecondsFSinceUnixEpoch();
  auto initiator =
      Network::Initiator::Create()
          .SetType(Network::Initiator::TypeEnum::Script)
          .SetUrl(initiator_url.is_valid() ? initiator_url.spec() : "")
          .Build();

  bool redirect_emitted_extra_info = false;
  std::unique_ptr<Network::Response> redirect_response =
      BuildRedirectResponse(redirect_info, redirect_emitted_extra_info);

  auto request_info =
      Network::Request::Create()
          .SetUrl(url)
          .SetMethod(request.method)
          .SetHeaders(BuildRequestHeaders(request.headers, request.referrer))
          .SetInitialPriority(resourcePriority(request.priority))
          .SetReferrerPolicy(referrerPolicy(request.referrer_policy))
          // A fetch keepalive request is categorized as blockable.
          // https://www.w3.org/TR/mixed-content/#category-blockable
          .SetMixedContentType(Security::MixedContentTypeEnum::Blockable)
          .Build();

  if (request.request_body) {
    request_info->SetHasPostData(true);
    std::string post_data;
    auto data_entries =
        std::make_unique<protocol::Array<protocol::Network::PostDataEntry>>();
    if (GetPostData(*request.request_body, data_entries.get(), &post_data)) {
      if (!post_data.empty()) {
        request_info->SetPostData(post_data);
      }
      if (data_entries->size()) {
        request_info->SetPostDataEntries(std::move(data_entries));
      }
    }
  }

  if (request.is_ad_tagged) {
    request_info->SetIsAdRelated(true);
  }

  frontend_->RequestWillBeSent(
      request_id, request_id, url, std::move(request_info), current_ticks,
      current_wall_time, std::move(initiator), redirect_emitted_extra_info,
      std::move(redirect_response),
      std::string(Network::ResourceTypeEnum::Fetch), std::move(frame_token),
      request.has_user_gesture);
}

void NetworkHandler::OnSignedExchangeReceived(
    std::optional<const base::UnguessableToken> devtools_navigation_token,
    const GURL& outer_request_url,
    const network::mojom::URLResponseHead& outer_response,
    const std::optional<SignedExchangeEnvelope>& envelope,
    const scoped_refptr<net::X509Certificate>& certificate,
    const std::optional<net::SSLInfo>& ssl_info,
    const std::vector<SignedExchangeError>& errors) {
  if (!enabled_) {
    return;
  }
  network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
      network::ExtractDevToolsInfo(outer_response);
  std::unique_ptr<Network::SignedExchangeInfo> signed_exchange_info =
      Network::SignedExchangeInfo::Create()
          .SetOuterResponse(BuildResponse(outer_request_url, *head_info))
          .SetHasExtraInfo(outer_response.emitted_extra_info)
          .Build();

  if (envelope) {
    auto headers_dict = std::make_unique<base::DictValue>();
    for (const auto& it : envelope->response_headers()) {
      headers_dict->Set(it.first, it.second);
    }

    const SignedExchangeSignatureHeaderField::Signature& sig =
        envelope->signature();
    auto signatures =
        std::make_unique<protocol::Array<Network::SignedExchangeSignature>>();
    std::unique_ptr<Network::SignedExchangeSignature> signature =
        Network::SignedExchangeSignature::Create()
            .SetLabel(sig.label)
            .SetSignature(base::HexEncode(sig.sig))
            .SetIntegrity(sig.integrity)
            .SetCertUrl(sig.cert_url.spec())
            .SetValidityUrl(sig.validity_url.url.spec())
            .SetDate(sig.date)
            .SetExpires(sig.expires)
            .Build();
    if (sig.cert_sha256) {
      signature->SetCertSha256(base::HexEncode(*sig.cert_sha256));
    }
    if (certificate) {
      auto encoded_certificates = std::make_unique<protocol::Array<String>>();
      for (const auto& cert : certificate->cert_buffers()) {
        encoded_certificates->emplace_back(base::Base64Encode(
            net::x509_util::CryptoBufferAsStringPiece(cert.get())));
      }
      signature->SetCertificates(std::move(encoded_certificates));
    }
    signatures->emplace_back(std::move(signature));

    signed_exchange_info->SetHeader(
        Network::SignedExchangeHeader::Create()
            .SetRequestUrl(envelope->request_url().url.spec())
            .SetResponseCode(envelope->response_code())
            .SetResponseHeaders(std::move(headers_dict))
            .SetSignatures(std::move(signatures))
            .SetHeaderIntegrity(
                signed_exchange_utils::CreateHeaderIntegrityHashString(
                    envelope->ComputeHeaderIntegrity()))
            .Build());
  }
  if (ssl_info) {
    signed_exchange_info->SetSecurityDetails(BuildSecurityDetails(*ssl_info));
  }
  if (errors.size()) {
    signed_exchange_info->SetErrors(BuildSignedExchangeErrors(errors));
  }

  frontend_->SignedExchangeReceived(
      devtools_navigation_token ? devtools_navigation_token->ToString() : "",
      std::move(signed_exchange_info));
}

DispatchResponse NetworkHandler::SetRequestInterception(
    std::unique_ptr<protocol::Array<protocol::Network::RequestPattern>>
        patterns) {
  if (patterns->empty()) {
    if (url_loader_interceptor_) {
      url_loader_interceptor_.reset();
      update_loader_factories_callback_.Run();
    }
    return Response::Success();
  }

  std::vector<DevToolsURLLoaderInterceptor::Pattern> interceptor_patterns;
  for (const std::unique_ptr<protocol::Network::RequestPattern>& pattern :
       *patterns) {
    base::flat_set<blink::mojom::ResourceType> resource_types;
    std::string resource_type = pattern->GetResourceType("");
    if (!resource_type.empty()) {
      if (!AddInterceptedResourceType(resource_type, &resource_types)) {
        return Response::InvalidParams(base::StringPrintf(
            "Cannot intercept resources of type '%s'", resource_type.c_str()));
      }
    }
    auto interception_stage = pattern->GetInterceptionStage(
        protocol::Network::InterceptionStageEnum::Request);
    auto stage = ToInterceptorStage(interception_stage);
    if (!stage.has_value()) {
      return Response::InvalidParams(base::StringPrintf(
          "Unsupported interception stage '%s'", interception_stage.c_str()));
    }
    interceptor_patterns.emplace_back(pattern->GetUrlPattern("*"),
                                      std::move(resource_types), stage.value());
  }

  if (!host_) {
    return Response::InternalError();
  }

  if (!url_loader_interceptor_) {
    url_loader_interceptor_ =
        std::make_unique<DevToolsURLLoaderInterceptor>(base::BindRepeating(
            &NetworkHandler::RequestIntercepted, weak_factory_.GetWeakPtr()));
    url_loader_interceptor_->SetPatterns(interceptor_patterns, true);
    update_loader_factories_callback_.Run();
  } else {
    url_loader_interceptor_->SetPatterns(interceptor_patterns, true);
  }
  return Response::Success();
}

void NetworkHandler::ContinueInterceptedRequest(
    const std::string& interception_id,
    std::optional<std::string> error_reason,
    std::optional<protocol::Binary> raw_response,
    std::optional<std::string> url,
    std::optional<std::string> method,
    std::optional<std::string> post_data,
    std::unique_ptr<protocol::Network::Headers> opt_headers,
    std::unique_ptr<protocol::Network::AuthChallengeResponse>
        auth_challenge_response,
    std::unique_ptr<ContinueInterceptedRequestCallback> callback) {
  scoped_refptr<net::HttpResponseHeaders> response_headers;
  scoped_refptr<base::RefCountedMemory> response_body;
  size_t body_offset = 0;

  if (raw_response.has_value()) {
    const protocol::Binary& raw = raw_response.value();

    std::string raw_headers;
    size_t header_size = net::HttpUtil::LocateEndOfHeaders(raw);
    if (header_size == std::string::npos) {
      LOG(WARNING) << "Can't find headers in raw response";
      header_size = 0;
    } else {
      raw_headers = net::HttpUtil::AssembleRawHeaders(std::string_view(
          reinterpret_cast<const char*>(raw.data()), header_size));
    }
    CHECK_LE(header_size, raw.size());
    response_headers =
        base::MakeRefCounted<net::HttpResponseHeaders>(std::move(raw_headers));
    response_body = raw.bytes();
    body_offset = header_size;
  }

  std::optional<net::Error> error;
  if (error_reason.has_value()) {
    bool ok;
    error = NetErrorFromString(error_reason.value(), &ok);
    if (!ok) {
      callback->sendFailure(Response::InvalidParams("Invalid errorReason."));
      return;
    }
  }

  std::unique_ptr<DevToolsURLLoaderInterceptor::Modifications::HeadersVector>
      override_headers;
  if (opt_headers) {
    const base::DictValue& headers = *opt_headers;
    override_headers = std::make_unique<
        DevToolsURLLoaderInterceptor::Modifications::HeadersVector>();
    for (const auto entry : headers) {
      std::string value;
      if (!entry.second.is_string()) {
        callback->sendFailure(Response::InvalidParams("Invalid header value"));
        return;
      }
      override_headers->emplace_back(entry.first, entry.second.GetString());
    }
  }
  using AuthChallengeResponse =
      DevToolsURLLoaderInterceptor::AuthChallengeResponse;
  std::unique_ptr<AuthChallengeResponse> override_auth;
  if (auth_challenge_response) {
    std::string type = auth_challenge_response->GetResponse();
    if (type == Network::AuthChallengeResponse::ResponseEnum::Default) {
      override_auth = std::make_unique<AuthChallengeResponse>(
          AuthChallengeResponse::kDefault);
    } else if (type ==
               Network::AuthChallengeResponse::ResponseEnum::CancelAuth) {
      override_auth = std::make_unique<AuthChallengeResponse>(
          AuthChallengeResponse::kCancelAuth);
    } else if (type == Network::AuthChallengeResponse::ResponseEnum::
                           ProvideCredentials) {
      override_auth = std::make_unique<AuthChallengeResponse>(
          base::UTF8ToUTF16(auth_challenge_response->GetUsername("")),
          base::UTF8ToUTF16(auth_challenge_response->GetPassword("")));
    } else {
      callback->sendFailure(
          Response::InvalidParams("Unrecognized authChallengeResponse."));
      return;
    }
  }

  std::optional<protocol::Binary> post_data_bytes;
  if (post_data.has_value()) {
    post_data_bytes = protocol::Binary::fromString(post_data.value());
  }

  auto modifications =
      std::make_unique<DevToolsURLLoaderInterceptor::Modifications>(
          std::move(error), std::move(response_headers),
          std::move(response_body), body_offset, std::move(url),
          std::move(method), std::move(post_data_bytes),
          std::move(override_headers), std::move(override_auth));

  if (!url_loader_interceptor_) {
    return;
  }

  did_modifications_ = true;
  url_loader_interceptor_->ContinueInterceptedRequest(
      interception_id, std::move(modifications), std::move(callback));
}

void NetworkHandler::GetResponseBodyForInterception(
    const String& interception_id,
    std::unique_ptr<GetResponseBodyForInterceptionCallback> callback) {
  if (!url_loader_interceptor_) {
    return;
  }

  url_loader_interceptor_->GetResponseBody(interception_id,
                                           std::move(callback));
}

void NetworkHandler::BodyDataReceived(const String& request_id,
                                      const String& body,
                                      bool is_base64_encoded) {
  network::mojom::DurableMessageCollector* collector =
      root_session_->MaybeGetDurableMessageCollector();
  if (collector) {
    // When Durable Message is enabled, we don't need to store the body data
    // in the NetworkHandler, to avoid doubling the memory usage.
    return;
  }
  received_body_data_[request_id] = {body, is_base64_encoded};
}

void NetworkHandler::FedCmRequestWillBeSent(
    const std::string& request_id,
    const std::string& loader_id,
    const network::ResourceRequest& request,
    const std::optional<std::string>& request_body,
    const GURL& initiator_url,
    const std::optional<base::UnguessableToken>& frame_token,
    base::TimeTicks timestamp) {
  if (!enabled_) {
    return;
  }

  double current_wall_time = base::Time::Now().InSecondsFSinceUnixEpoch();
  double current_ticks = timestamp.since_origin().InSecondsF();

  std::vector<base::expected<std::vector<uint8_t>, std::string>>
      request_body_bytes;
  if (request_body.has_value() && !request_body->empty()) {
    request_body_bytes.emplace_back(
        std::vector<uint8_t>(request_body->begin(), request_body->end()));
  }

  std::unique_ptr<protocol::Network::Request> request_info =
      CreateRequestFromResourceRequest(request, "",
                                       std::move(request_body_bytes));

  auto initiator = protocol::Network::Initiator::Create()
                       .SetType(protocol::Network::Initiator::TypeEnum::FedCM)
                       .Build();
  if (!initiator_url.is_empty()) {
    initiator->SetUrl(initiator_url.spec());
  }

  std::string frame_token_str =
      frame_token.has_value() ? frame_token.value().ToString() : "";

  frontend_->RequestWillBeSent(
      request_id, loader_id, request.url.spec(), std::move(request_info),
      current_ticks, current_wall_time, std::move(initiator),
      /*redirectHasExtraInfo=*/false, /*redirectResponse=*/nullptr,
      std::string(Network::ResourceTypeEnum::FedCM), frame_token_str,
      /*hasUserGesture=*/false);
}

void NetworkHandler::ProcessDurableMessageOrGetLocalData(
    const String& request_id,
    std::unique_ptr<GetResponseBodyCallback> callback,
    std::optional<mojo_base::BigBuffer> durable_message) {
  if (durable_message.has_value()) {
    std::string_view data_view =
        base::as_string_view(base::span(*durable_message));
    if (base::IsStringUTF8(data_view)) {
      callback->sendSuccess(std::string(data_view), false);
    } else {
      callback->sendSuccess(base::Base64Encode(data_view), true);
    }
    return;
  }

  auto it = received_body_data_.find(request_id);
  if (it != received_body_data_.end()) {
    callback->sendSuccess(it->second.first, it->second.second);
  } else {
    callback->fallThrough();
  }
}

void NetworkHandler::GetResponseBody(
    const String& request_id,
    std::unique_ptr<GetResponseBodyCallback> callback) {
  CHECK(storage_partition_);
  CHECK(devtools_token_);
  network::mojom::DurableMessageCollector* collector =
      root_session_->MaybeGetDurableMessageCollector();
  if (collector) {
    collector->Retrieve(
        request_id,
        base::BindOnce(&NetworkHandler::ProcessDurableMessageOrGetLocalData,
                       weak_factory_.GetWeakPtr(), request_id,
                       std::move(callback)));
    return;
  }
  ProcessDurableMessageOrGetLocalData(request_id, std::move(callback),
                                      std::nullopt);
}

void NetworkHandler::TakeResponseBodyForInterceptionAsStream(
    const String& interception_id,
    std::unique_ptr<TakeResponseBodyForInterceptionAsStreamCallback> callback) {
  if (url_loader_interceptor_) {
    url_loader_interceptor_->TakeResponseBodyPipe(
        interception_id,
        base::BindOnce(&NetworkHandler::OnResponseBodyPipeTaken,
                       weak_factory_.GetWeakPtr(), std::move(callback)));
    return;
  }
  callback->sendFailure(Response::ServerError(
      "Network.takeResponseBodyForInterceptionAsStream is only "
      "currently supported with --enable-features=NetworkService"));
}

void NetworkHandler::OnResponseBodyPipeTaken(
    std::unique_ptr<TakeResponseBodyForInterceptionAsStreamCallback> callback,
    Response response,
    mojo::ScopedDataPipeConsumerHandle pipe,
    const std::string& mime_type) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_EQ(response.IsSuccess(), pipe.is_valid());
  if (!response.IsSuccess()) {
    callback->sendFailure(std::move(response));
    return;
  }
  // The pipe stream is owned only by io_context after we return.
  auto stream = DevToolsStreamPipe::Create(io_context_, std::move(pipe));
  callback->sendSuccess(stream->handle());
}

// static
std::string NetworkHandler::ExtractFragment(const GURL& url,
                                            std::string* fragment) {
  if (!url.has_ref()) {
    *fragment = std::string();
    return url.spec();
  }
  *fragment = "#" + url.GetRef();
  GURL::Replacements replacements;
  replacements.ClearRef();
  return url.ReplaceComponents(replacements).spec();
}

// static
std::unique_ptr<Network::Request>
NetworkHandler::CreateRequestFromResourceRequest(
    const network::ResourceRequest& request,
    const std::string& cookie_line,
    std::vector<base::expected<std::vector<uint8_t>, std::string>>
        request_bodies) {
  std::unique_ptr<base::DictValue> headers_dict =
      BuildRequestHeaders(request.headers, request.referrer);
  if (!cookie_line.empty()) {
    headers_dict->Set(net::HttpRequestHeaders::kCookie, cookie_line);
  }

  std::string url_fragment;
  std::unique_ptr<protocol::Network::Request> request_object =
      Network::Request::Create()
          .SetUrl(ExtractFragment(request.url, &url_fragment))
          .SetMethod(request.method)
          .SetHeaders(std::move(headers_dict))
          .SetInitialPriority(resourcePriority(request.priority))
          .SetReferrerPolicy(referrerPolicy(request.referrer_policy))
          .Build();
  if (!url_fragment.empty()) {
    request_object->SetUrlFragment(url_fragment);
  }
  if (!request_bodies.empty()) {
    std::string post_data;
    auto data_entries =
        std::make_unique<protocol::Array<protocol::Network::PostDataEntry>>();

    for (auto& body : request_bodies) {
      // TODO(caseq): post_data is deprecated, remove.
      auto entry = protocol::Network::PostDataEntry::Create().Build();
      if (body.has_value()) {
        post_data.append(reinterpret_cast<const char*>(body->data()),
                         body->size());
        entry->SetBytes(protocol::Binary::fromVector(*std::move(body)));
      }
      data_entries->push_back(std::move(entry));
    }
    if (!post_data.empty()) {
      request_object->SetPostData(std::move(post_data));
    }
    request_object->SetPostDataEntries(std::move(data_entries));
    request_object->SetHasPostData(true);
  }
  if (request.is_ad_tagged) {
    request_object->SetIsAdRelated(true);
  }
  return request_object;
}

bool NetworkHandler::MaybeCreateProxyForInterception(
    int process_id,
    StoragePartition* storage_partition,
    const base::UnguessableToken& frame_token,
    bool is_navigation,
    bool is_download,
    network::mojom::URLLoaderFactoryOverride* intercepting_factory,
    mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
        header_client) {
  return url_loader_interceptor_ &&
         url_loader_interceptor_->CreateProxyForInterception(
             process_id, storage_partition, frame_token, is_navigation,
             is_download, intercepting_factory, header_client);
}

void NetworkHandler::ApplyOverrides(
    net::HttpRequestHeaders* headers,
    bool* skip_service_worker,
    bool* disable_cache,
    std::optional<std::vector<net::SourceStreamType>>* accepted_stream_types,
    GURL* referrer_override) {
  for (auto& entry : extra_headers_) {
    if (referrer_override &&
        base::EqualsCaseInsensitiveASCII(entry.first,
                                         net::HttpRequestHeaders::kReferer)) {
      GURL referrer_override_(entry.second);
      if (referrer_override_.is_valid()) {
        // If extra header `Referer` is set and is a valid URL, use it as the
        // referrer.
        *referrer_override = referrer_override_;
      }
    }
    headers->SetHeader(entry.first, entry.second);
  }
  *skip_service_worker |= bypass_service_worker_;
  *disable_cache |= cache_disabled_;
  if (!accepted_stream_types_) {
    return;
  }
  if (!*accepted_stream_types) {
    *accepted_stream_types = std::vector<net::SourceStreamType>();
  }
  (*accepted_stream_types)
      ->insert((*accepted_stream_types)->end(), accepted_stream_types_->begin(),
               accepted_stream_types_->end());
}

void NetworkHandler::ApplyCookieControlsOverrides(
    net::CookieSettingOverrides& overrides) {
  if (enable_third_party_cookie_restriction_) {
    overrides.Put(net::CookieSettingOverride::kForceDisableThirdPartyCookies);
  }
}

void NetworkHandler::RequestIntercepted(
    std::unique_ptr<InterceptedRequestInfo> info) {
  std::optional<protocol::Network::ErrorReason> error_reason;
  if (info->response_error_code < 0) {
    error_reason = NetErrorToString(info->response_error_code);
  }

  std::optional<int> status_code;
  std::unique_ptr<protocol::Network::Headers> response_headers;
  if (info->response_headers) {
    status_code = info->response_headers->response_code();
    response_headers = BuildResponseHeaders(info->response_headers.get());
  }

  std::unique_ptr<protocol::Network::AuthChallenge> auth_challenge;
  if (info->auth_challenge) {
    auth_challenge =
        protocol::Network::AuthChallenge::Create()
            .SetSource(info->auth_challenge->is_proxy
                           ? Network::AuthChallenge::SourceEnum::Proxy
                           : Network::AuthChallenge::SourceEnum::Server)
            .SetOrigin(info->auth_challenge->challenger.Serialize())
            .SetScheme(info->auth_challenge->scheme)
            .SetRealm(info->auth_challenge->realm)
            .Build();
  }

  frontend_->RequestIntercepted(
      info->interception_id, std::move(info->network_request),
      info->frame_id.ToString(), ResourceTypeToString(info->resource_type),
      info->is_navigation, std::move(info->is_download),
      std::move(info->redirect_url), std::move(auth_challenge),
      std::move(error_reason), std::move(status_code),
      std::move(response_headers), std::move(info->renderer_request_id));
}

void NetworkHandler::SetNetworkConditions(
    std::vector<network::mojom::MatchedNetworkConditionsPtr> matched_conditions,
    bool offline) {
  if (!storage_partition_) {
    return;
  }
  network::mojom::NetworkContext* context =
      storage_partition_->GetNetworkContext();

  if (!devtools_token_.is_empty()) {
    context->SetNetworkConditions(devtools_token_, throttling_client_id_,
                                  std::move(matched_conditions));
  }

  if (offline == !!background_sync_restorer_) {
    return;
  }
  background_sync_restorer_.reset(
      offline ? new BackgroundSyncRestorer(host_id_, storage_partition_)
              : nullptr);
}

namespace {
protocol::Network::CrossOriginOpenerPolicyValue
makeCrossOriginOpenerPolicyValue(
    network::mojom::CrossOriginOpenerPolicyValue value) {
  switch (value) {
    case network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin:
      return protocol::Network::CrossOriginOpenerPolicyValueEnum::SameOrigin;
    case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups:
      return protocol::Network::CrossOriginOpenerPolicyValueEnum::
          SameOriginAllowPopups;
    case network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone:
      return protocol::Network::CrossOriginOpenerPolicyValueEnum::UnsafeNone;
    case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep:
      return protocol::Network::CrossOriginOpenerPolicyValueEnum::
          SameOriginPlusCoep;
    case network::mojom::CrossOriginOpenerPolicyValue::kNoopenerAllowPopups:
      return protocol::Network::CrossOriginOpenerPolicyValueEnum::
          NoopenerAllowPopups;
  }
}
protocol::Network::CrossOriginEmbedderPolicyValue
makeCrossOriginEmbedderPolicyValue(
    network::mojom::CrossOriginEmbedderPolicyValue value) {
  switch (value) {
    case network::mojom::CrossOriginEmbedderPolicyValue::kNone:
      return protocol::Network::CrossOriginEmbedderPolicyValueEnum::None;
    case network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless:
      return protocol::Network::CrossOriginEmbedderPolicyValueEnum::
          Credentialless;
    case network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp:
      return protocol::Network::CrossOriginEmbedderPolicyValueEnum::RequireCorp;
  }
}
protocol::Network::ContentSecurityPolicySource makeContentSecurityPolicySource(
    network::mojom::ContentSecurityPolicySource source) {
  switch (source) {
    case network::mojom::ContentSecurityPolicySource::kHTTP:
      return protocol::Network::ContentSecurityPolicySourceEnum::HTTP;
    case network::mojom::ContentSecurityPolicySource::kMeta:
      return protocol::Network::ContentSecurityPolicySourceEnum::Meta;
  }
}
std::unique_ptr<protocol::Network::CrossOriginOpenerPolicyStatus>
makeCrossOriginOpenerPolicyStatus(
    const network::CrossOriginOpenerPolicy& coop) {
  auto protocol_coop =
      protocol::Network::CrossOriginOpenerPolicyStatus::Create()
          .SetValue(makeCrossOriginOpenerPolicyValue(coop.value))
          .SetReportOnlyValue(
              makeCrossOriginOpenerPolicyValue(coop.report_only_value))
          .Build();

  if (coop.reporting_endpoint) {
    protocol_coop->SetReportingEndpoint(*coop.reporting_endpoint);
  }
  if (coop.report_only_reporting_endpoint) {
    protocol_coop->SetReportOnlyReportingEndpoint(
        *coop.report_only_reporting_endpoint);
  }
  return protocol_coop;
}
std::unique_ptr<protocol::Network::CrossOriginEmbedderPolicyStatus>
makeCrossOriginEmbedderPolicyStatus(
    const network::CrossOriginEmbedderPolicy& coep) {
  auto protocol_coep =
      protocol::Network::CrossOriginEmbedderPolicyStatus::Create()
          .SetValue(makeCrossOriginEmbedderPolicyValue(coep.value))
          .SetReportOnlyValue(
              makeCrossOriginEmbedderPolicyValue(coep.report_only_value))
          .Build();

  if (coep.reporting_endpoint) {
    protocol_coep->SetReportingEndpoint(*coep.reporting_endpoint);
  }
  if (coep.report_only_reporting_endpoint) {
    protocol_coep->SetReportOnlyReportingEndpoint(
        *coep.report_only_reporting_endpoint);
  }
  return protocol_coep;
}
std::unique_ptr<protocol::Array<protocol::Network::ContentSecurityPolicyStatus>>
makeContentSecurityPolicyStatus(
    const std::vector<network::mojom::ContentSecurityPolicyHeader>&
        csp_headers) {
  auto csp_status = std::make_unique<
      protocol::Array<protocol::Network::ContentSecurityPolicyStatus>>();
  for (const auto& csp_header : csp_headers) {
    auto csp_status_component =
        protocol::Network::ContentSecurityPolicyStatus::Create()
            .SetEffectiveDirectives(csp_header.header_value)
            .SetIsEnforced(csp_header.type ==
                           network::mojom::ContentSecurityPolicyType::kEnforce)
            .SetSource(makeContentSecurityPolicySource(csp_header.source))
            .Build();
    csp_status->emplace_back(std::move(csp_status_component));
  }
  return csp_status;
}
}  // namespace

DispatchResponse NetworkHandler::GetSecurityIsolationStatus(
    std::optional<String> frame_id,
    std::unique_ptr<protocol::Network::SecurityIsolationStatus>* out_info) {
  scoped_refptr<DevToolsAgentHostImpl> host =
      DevToolsAgentHostImpl::GetForId(host_id_);
  std::string id = frame_id.value_or("");
  auto maybe_coep = host->cross_origin_embedder_policy(id);
  auto maybe_coop = host->cross_origin_opener_policy(id);
  auto maybe_csp = host->content_security_policy(id);
  auto status = protocol::Network::SecurityIsolationStatus::Create().Build();
  if (maybe_coep) {
    status->SetCoep(makeCrossOriginEmbedderPolicyStatus(*maybe_coep));
  }
  if (maybe_coop) {
    status->SetCoop(makeCrossOriginOpenerPolicyStatus(*maybe_coop));
  }
  if (maybe_csp) {
    status->SetCsp(makeContentSecurityPolicyStatus(*maybe_csp));
  }
  *out_info = std::move(status);
  return Response::Success();
}

void NetworkHandler::OnRequestWillBeSentExtraInfo(
    const std::string& devtools_request_id,
    const net::CookieAccessResultList& request_cookie_list,
    const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers,
    const base::TimeTicks timestamp,
    const std::vector<network::mojom::DeviceBoundSessionWithUsagePtr>&
        device_bound_session_usages,
    const network::mojom::ClientSecurityStatePtr& security_state,
    const network::mojom::OtherPartitionInfoPtr& other_partition_info,
    std::optional<base::UnguessableToken> applied_network_conditions_id) {
  if (!enabled_) {
    return;
  }

  frontend_->RequestWillBeSentExtraInfo(
      devtools_request_id, BuildProtocolAssociatedCookies(request_cookie_list),
      GetRawHeaders(request_headers), GetConnectTiming(timestamp),
      BuildProtocolDeviceBoundSessionUsages(device_bound_session_usages),
      MaybeBuildClientSecurityState(security_state),
      other_partition_info
          ? std::optional<bool>(
                other_partition_info->site_has_cookie_in_other_partition)
          : std::nullopt,
      applied_network_conditions_id.has_value()
          ? std::optional<String>(applied_network_conditions_id->ToString())
          : std::nullopt);
}

void NetworkHandler::OnResponseReceivedExtraInfo(
    const std::string& devtools_request_id,
    const net::CookieAndLineAccessResultList& response_cookie_list,
    const std::vector<network::mojom::HttpRawHeaderPairPtr>& response_headers,
    const std::optional<std::string>& response_headers_text,
    network::mojom::IPAddressSpace resource_address_space,
    int32_t http_status_code,
    const std::optional<net::CookiePartitionKey>& cookie_partition_key) {
  if (!enabled_) {
    return;
  }

  std::unique_ptr<Network::CookiePartitionKey> frontend_partition_key;

  if (cookie_partition_key) {
    base::expected<net::CookiePartitionKey::SerializedCookiePartitionKey,
                   std::string>
        serialized_result =
            net::CookiePartitionKey::Serialize(cookie_partition_key);
    if (serialized_result.has_value()) {
      frontend_partition_key =
          BuildCookiePartitionKey(serialized_result->TopLevelSite(),
                                  serialized_result->has_cross_site_ancestor());
    }
  }

  frontend_->ResponseReceivedExtraInfo(
      devtools_request_id, BuildProtocolBlockedSetCookies(response_cookie_list),
      GetRawHeaders(response_headers),
      BuildIpAddressSpace(resource_address_space), http_status_code,
      response_headers_text, std::move(frontend_partition_key),
      cookie_partition_key
          ? std::optional<bool>(!cookie_partition_key->IsSerializeable())
          : std::nullopt,
      BuildProtocolExemptedSetCookies(response_cookie_list));
}

void NetworkHandler::OnResponseReceivedEarlyHints(
    const std::string& devtools_request_id,
    const std::vector<network::mojom::HttpRawHeaderPairPtr>& response_headers) {
  if (!enabled_) {
    return;
  }

  frontend_->ResponseReceivedEarlyHints(devtools_request_id,
                                        GetRawHeaders(response_headers));
}

void NetworkHandler::OnLoadNetworkResourceFinished(
    DevToolsNetworkResourceLoader* loader,
    const net::HttpResponseHeaders* rh,
    bool success,
    int net_error,
    std::string content) {
  auto it = loaders_.find(loader);
  CHECK(it != loaders_.end());
  auto callback = std::move(it->second);
  auto result = Network::LoadNetworkResourcePageResult::Create()
                    .SetSuccess(success)
                    .Build();

  if (net_error != net::OK) {
    result->SetNetError(net_error);
    result->SetNetErrorName(net::ErrorToString(net_error));
  }

  if (success) {
    bool is_binary = !base::IsStringUTF8(content);
    // TODO(sigurds): Use the data-pipe from the network loader.
    scoped_refptr<DevToolsStreamFile> stream =
        DevToolsStreamFile::Create(io_context_, is_binary);
    stream->Append(std::make_unique<std::string>(std::move(content)));
    result->SetStream(stream->handle());
  }

  if (rh) {
    result->SetHttpStatusCode(rh->response_code());
    result->SetHeaders(BuildResponseHeaders(rh));
  }

  callback->sendSuccess(std::move(result));
  loaders_.erase(it);
}

namespace {

mojo::PendingRemote<network::mojom::URLLoaderFactory>
CreateNetworkFactoryForDevTools(
    std::string_view scheme,
    RenderProcessHost* host,
    int routing_id,
    const url::Origin& origin,
    network::mojom::URLLoaderFactoryParamsPtr params) {
  if (!host || !params) {
    // Return an invalid remote by default.
    return {};
  }

  // Don't allow trust token redemption.
  params->trust_token_redemption_policy =
      network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
  // Don't allow trust token issuance.
  params->trust_token_issuance_policy =
      network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
  // Let DevTools fetch resources without CORS and ORB. Source maps are valid
  // JSON and would otherwise require a CORS fetch + correct response headers.
  // See BUG(chromium:1076435) for more context.
  params->is_orb_enabled = false;

  if (scheme == url::kHttpScheme || scheme == url::kHttpsScheme) {
    return url_loader_factory::CreatePendingRemote(
        ContentBrowserClient::URLLoaderFactoryType::kDevTools,
        url_loader_factory::TerminalParams::ForNetworkContext(
            host->GetStoragePartition()->GetNetworkContext(),
            std::move(params)));
  }

  if (scheme != url::kFileScheme) {
    ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
    GetContentClient()
        ->browser()
        ->RegisterNonNetworkSubresourceURLLoaderFactories(
            host->GetDeprecatedID(), routing_id, origin, &factories);
    auto i = factories.find(std::string(scheme));
    if (i == factories.end()) {
      return {};
    }
    return std::move(i->second);
  }
  return {};
}
}  // namespace

void NetworkHandler::LoadNetworkResource(
    std::optional<protocol::String> maybe_frame_id,
    const String& url,
    std::unique_ptr<protocol::Network::LoadNetworkResourceOptions> options,
    std::unique_ptr<LoadNetworkResourceCallback> callback) {
  GURL gurl(url);
  const bool is_gurl_valid = gurl.is_valid();
  if (!is_gurl_valid) {
    callback->sendFailure(Response::InvalidParams("The url must be valid"));
    return;
  }

  if (gurl.SchemeIs(url::kFileScheme) && !client_->MayReadLocalFiles()) {
    callback->sendFailure(Response::InvalidParams("Unsupported URL scheme"));
    return;
  }

  const DevToolsNetworkResourceLoader::Caching caching =
      options->GetDisableCache()
          ? DevToolsNetworkResourceLoader::Caching::kBypass
          : DevToolsNetworkResourceLoader::Caching::kDefault;
  const DevToolsNetworkResourceLoader::Credentials include_credentials =
      options->GetIncludeCredentials()
          ? DevToolsNetworkResourceLoader::Credentials::kInclude
          : DevToolsNetworkResourceLoader::Credentials::kSameSite;
  DevToolsNetworkResourceLoader::CompletionCallback complete_callback =
      base::BindOnce(&NetworkHandler::OnLoadNetworkResourceFinished,
                     base::Unretained(this));

  mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory;
  if (host_) {
    if (!maybe_frame_id.has_value()) {
      callback->sendFailure(Response::InvalidParams(
          "Parameter frameId must be provided for frame targets"));
      return;
    }
    FrameTreeNode* node = FrameTreeNodeFromDevToolsFrameToken(
        host_->frame_tree_node(), maybe_frame_id.value());
    RenderFrameHostImpl* frame = node ? node->current_frame_host() : nullptr;
    if (!frame) {
      callback->sendFailure(Response::InvalidParams("Frame not found"));
      return;
    }
    // Don't allow fetching resources for frames goverened by different
    // DevToolsAgentHosts.
    if (GetFrameTreeNodeAncestor(node) !=
        GetFrameTreeNodeAncestor(host_->frame_tree_node())) {
      callback->sendFailure(
          Response::InvalidParams("Frame not under control of agent host"));
      return;
    }

    RenderFrameHostCSPContext csp_context(frame);

    network::CSPCheckResult result = csp_context.IsAllowedByCsp(
        frame->policy_container_host()->policies().content_security_policies,
        network::mojom::CSPDirectiveName::ConnectSrc, gurl, gurl,
        /*has_followed_redirect=*/false, /*source_location=*/nullptr,
        network::CSPContext::CHECK_ENFORCED_CSP,
        /*is_opaque_fenced_frame=*/false);
    if (!result.IsAllowed()) {
      callback->sendFailure(Response::ServerError("CSP violation"));
      return;
    }

    auto params = URLLoaderFactoryParamsHelper::CreateForFrame(
        frame, frame->GetLastCommittedOrigin(),
        frame->GetIsolationInfoForSubresources(),
        frame->BuildClientSecurityState(),
        /*coep_reporter=*/mojo::NullRemote(),
        /*dip_reporter=*/mojo::NullRemote(), frame->GetProcess(),
        network::mojom::TrustTokenOperationPolicyVerdict::kForbid,
        network::mojom::TrustTokenOperationPolicyVerdict::kForbid,
        frame->GetCookieSettingOverrides(),
        /*network_restrictions_id=*/std::nullopt,
        "NetworkHandler::LoadNetworkResource");

    auto factory = CreateNetworkFactoryForDevTools(
        gurl.GetScheme(), frame->GetProcess(), frame->GetRoutingID(),
        frame->GetLastCommittedOrigin(), std::move(params));
    if (!factory.is_valid()) {
      callback->sendFailure(Response::InvalidParams("Unsupported URL scheme"));
      return;
    }

    url_loader_factory.Bind(std::move(factory));
    auto loader = DevToolsNetworkResourceLoader::Create(
        std::move(url_loader_factory), std::move(gurl),
        frame->GetLastCommittedOrigin(), frame->ComputeSiteForCookies(),
        caching, include_credentials, std::move(complete_callback));
    loaders_.emplace(std::move(loader), std::move(callback));
    return;
  }
  scoped_refptr<DevToolsAgentHostImpl> host =
      DevToolsAgentHostImpl::GetForId(host_id_);
  if (host) {
    // TODO(sigurds): Support dedicated workers.
    // TODO(mkwst): Check CSP for non-frame targets.
    auto info = host->CreateNetworkFactoryParamsForDevTools();
    auto factory = CreateNetworkFactoryForDevTools(
        gurl.GetScheme(), host->GetProcessHost(), IPC::mojom::kRoutingIdNone,
        info.origin, std::move(info.factory_params));
    if (factory.is_valid()) {
      url_loader_factory.Bind(std::move(factory));
      auto loader = DevToolsNetworkResourceLoader::Create(
          std::move(url_loader_factory), std::move(gurl),
          std::move(info.origin), std::move(info.site_for_cookies), caching,
          include_credentials, std::move(complete_callback));
      loaders_.emplace(std::move(loader), std::move(callback));
      return;
    }
  }
  callback->sendFailure(Response::ServerError("Target not supported"));
}

DispatchResponse NetworkHandler::SetCookieControls(
    bool enable_third_party_cookie_restriction) {
  enable_third_party_cookie_restriction_ =
      enable_third_party_cookie_restriction;

  return Response::Success();
}

namespace {

String GetTrustTokenOperationStatus(
    network::mojom::TrustTokenOperationStatus status) {
  switch (status) {
    case network::mojom::TrustTokenOperationStatus::kOk:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::Ok;
    case network::mojom::TrustTokenOperationStatus::kInvalidArgument:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          InvalidArgument;
    case network::mojom::TrustTokenOperationStatus::kMissingIssuerKeys:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          MissingIssuerKeys;
    case network::mojom::TrustTokenOperationStatus::kFailedPrecondition:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          FailedPrecondition;
    case network::mojom::TrustTokenOperationStatus::kResourceExhausted:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          ResourceExhausted;
    case network::mojom::TrustTokenOperationStatus::kAlreadyExists:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          AlreadyExists;
    case network::mojom::TrustTokenOperationStatus::kResourceLimited:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          ResourceLimited;
    case network::mojom::TrustTokenOperationStatus::kUnauthorized:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          Unauthorized;
    case network::mojom::TrustTokenOperationStatus::kBadResponse:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          BadResponse;
    case network::mojom::TrustTokenOperationStatus::kInternalError:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          InternalError;
    case network::mojom::TrustTokenOperationStatus::kUnknownError:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          UnknownError;
    case network::mojom::TrustTokenOperationStatus::
        kOperationSuccessfullyFulfilledLocally:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          FulfilledLocally;
    case network::mojom::TrustTokenOperationStatus::kSiteIssuerLimit:
      return protocol::Network::TrustTokenOperationDone::StatusEnum::
          SiteIssuerLimit;
  }
}

}  // namespace

void NetworkHandler::OnTrustTokenOperationDone(
    const std::string& devtools_request_id,
    const network::mojom::TrustTokenOperationResult& result) {
  if (!enabled_) {
    return;
  }

  std::optional<String> top_level_origin;
  if (result.top_level_origin) {
    top_level_origin = result.top_level_origin->Serialize();
  }
  std::optional<String> issuer;
  if (result.issuer) {
    issuer = result.issuer->Serialize();
  }

  frontend()->TrustTokenOperationDone(
      GetTrustTokenOperationStatus(result.status),
      GetTrustTokenOperationType(result.operation), devtools_request_id,
      std::move(top_level_origin), std::move(issuer),
      result.issued_token_count);
}

void NetworkHandler::OnPolicyContainerHostUpdated() {
  if (!enabled_) {
    return;
  }
  frontend()->PolicyUpdated();
}

String NetworkHandler::BuildLocalNetworkAccessRequestPolicy(
    network::mojom::LocalNetworkAccessRequestPolicy policy) {
  switch (policy) {
    case network::mojom::LocalNetworkAccessRequestPolicy::kAllow:
      return protocol::Network::LocalNetworkAccessRequestPolicyEnum::Allow;
    case network::mojom::LocalNetworkAccessRequestPolicy::kBlock:
      // TODO(crbug.com/40154414): Fix this.
      return protocol::Network::LocalNetworkAccessRequestPolicyEnum::
          BlockFromInsecureToMorePrivate;
    case network::mojom::LocalNetworkAccessRequestPolicy::kWarn:
      // TODO(crbug.com/40154414): Fix this.
      return protocol::Network::LocalNetworkAccessRequestPolicyEnum::
          WarnFromInsecureToMorePrivate;
    case network::mojom::LocalNetworkAccessRequestPolicy::kPermissionBlock:
      return protocol::Network::LocalNetworkAccessRequestPolicyEnum::
          PermissionBlock;
    case network::mojom::LocalNetworkAccessRequestPolicy::kPermissionWarn:
      return protocol::Network::LocalNetworkAccessRequestPolicyEnum::
          PermissionWarn;
  }
}

String NetworkHandler::BuildIpAddressSpace(
    network::mojom::IPAddressSpace space) {
  switch (space) {
    case network::mojom::IPAddressSpace::kLoopback:
      return protocol::Network::IPAddressSpaceEnum::Loopback;
    case network::mojom::IPAddressSpace::kLocal:
      return protocol::Network::IPAddressSpaceEnum::Local;
    case network::mojom::IPAddressSpace::kPublic:
      return protocol::Network::IPAddressSpaceEnum::Public;
    case network::mojom::IPAddressSpace::kUnknown:
      return protocol::Network::IPAddressSpaceEnum::Unknown;
  }
}

std::unique_ptr<protocol::Network::ClientSecurityState>
NetworkHandler::MaybeBuildClientSecurityState(
    const network::mojom::ClientSecurityStatePtr& state) {
  return state ? protocol::Network::ClientSecurityState::Create()
                     .SetLocalNetworkAccessRequestPolicy(
                         BuildLocalNetworkAccessRequestPolicy(
                             state->local_network_access_request_policy))
                     .SetInitiatorIPAddressSpace(
                         BuildIpAddressSpace(state->ip_address_space))
                     .SetInitiatorIsSecureContext(state->is_web_secure_context)
                     .Build()
               : nullptr;
}

std::unique_ptr<protocol::Network::CorsErrorStatus>
NetworkHandler::BuildCorsErrorStatus(const network::CorsErrorStatus& status) {
  return protocol::Network::CorsErrorStatus::Create()
      .SetCorsError(BuildCorsError(status.cors_error))
      .SetFailedParameter(status.failed_parameter)
      .Build();
}

void NetworkHandler::MaybeEnableDurableMessages(base::OnceClosure callback) {
  if (!enable_durable_messages_ || devtools_token_.is_empty()) {
    std::move(callback).Run();
    return;
  }
  network::mojom::NetworkDurableMessageConfigPtr durable_messages_config;
  durable_messages_config = network::mojom::NetworkDurableMessageConfig::New();
  durable_messages_config->http_storage_max_size =
      durable_message_max_total_size_;
  root_session_->EnableDurableMessageCollector(
      devtools_token_, std::move(durable_messages_config), std::move(callback));
}

void NetworkHandler::DisableDurableMessages(base::OnceClosure callback) {
  enable_durable_messages_ = false;
  root_session_->DisableDurableMessageCollectorForProfile(devtools_token_,
                                                          std::move(callback));
}

void NetworkHandler::ConfigureDurableMessages(
    std::optional<int> max_total_size,
    std::optional<int> max_resource_size,
    std::unique_ptr<ConfigureDurableMessagesCallback> callback) {
  if (!max_total_size.has_value() || max_total_size.value() == 0) {
    DisableDurableMessages(base::BindOnce(
        &ConfigureDurableMessagesCallback::sendSuccess, std::move(callback)));
    return;
  }
  durable_message_max_total_size_ = max_total_size.value();
  enable_durable_messages_ = true;
  MaybeEnableDurableMessages(base::BindOnce(
      &ConfigureDurableMessagesCallback::sendSuccess, std::move(callback)));
}

}  // namespace protocol
}  // namespace content
