// Copyright 2018 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/devtools_instrumentation.h"

#include "base/containers/adapters.h"
#include "base/feature_list.h"
#include "base/notreached.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/traced_value.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_url_parameters.h"
#include "content/browser/devtools/browser_devtools_agent_host.h"
#include "content/browser/devtools/dedicated_worker_devtools_agent_host.h"
#include "content/browser/devtools/devtools_issue_storage.h"
#include "content/browser/devtools/devtools_preload_storage.h"
#include "content/browser/devtools/protocol/audits.h"
#include "content/browser/devtools/protocol/audits_handler.h"
#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/device_access_handler.h"
#include "content/browser/devtools/protocol/emulation_handler.h"
#include "content/browser/devtools/protocol/fedcm_handler.h"
#include "content/browser/devtools/protocol/fetch_handler.h"
#include "content/browser/devtools/protocol/input_handler.h"
#include "content/browser/devtools/protocol/log_handler.h"
#include "content/browser/devtools/protocol/network.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/protocol/page_handler.h"
#include "content/browser/devtools/protocol/preload_handler.h"
#include "content/browser/devtools/protocol/security_handler.h"
#include "content/browser/devtools/protocol/storage_handler.h"
#include "content/browser/devtools/protocol/target_handler.h"
#include "content/browser/devtools/protocol/tracing_handler.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/shared_worker_devtools_agent_host.h"
#include "content/browser/devtools/web_contents_devtools_agent_host.h"
#include "content/browser/devtools/worker_devtools_manager.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/preloading/prerender/prerender_metrics.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_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_package/signed_exchange_envelope.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/cookie_insight_list_data.h"
#include "content/public/browser/cookie_insight_list_handler.h"
#include "devtools_agent_host_impl.h"
#include "devtools_instrumentation.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/features.h"
#include "net/base/load_flags.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/filter/source_stream_type.h"
#include "net/http/http_request_headers.h"
#include "net/quic/web_transport_error.h"
#include "net/ssl/ssl_info.h"
#include "services/network/public/cpp/devtools_observer_util.h"
#include "services/network/public/cpp/url_loader_factory_builder.h"
#include "services/network/public/mojom/devtools_observer.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"

namespace content {
namespace devtools_instrumentation {

namespace {

namespace AttributionReportingIssueTypeEnum =
    protocol::Audits::AttributionReportingIssueTypeEnum;

const char kPrivacySandboxExtensionsAPI[] = "PrivacySandboxExtensionsAPI";

template <typename Handler, typename... MethodArgs, typename... Args>
void DispatchToAgents(DevToolsAgentHostImpl* host,
                      void (Handler::*method)(MethodArgs...),
                      Args&&... args) {
  if (!host) {
    return;
  }
  for (auto* h : Handler::ForAgentHost(host)) {
    (h->*method)(std::forward<Args>(args)...);
  }
}

template <typename Handler, typename... MethodArgs, typename... Args>
void DispatchToAgents(FrameTreeNode* frame_tree_node,
                      void (Handler::*method)(MethodArgs...),
                      Args&&... args) {
  DevToolsAgentHostImpl* agent_host =
      RenderFrameDevToolsAgentHost::GetFor(frame_tree_node);
  DispatchToAgents(agent_host, method, std::forward<Args>(args)...);
}

template <typename Handler, typename... MethodArgs, typename... Args>
void DispatchToAgents(FrameTreeNodeId frame_tree_node_id,
                      void (Handler::*method)(MethodArgs...),
                      Args&&... args) {
  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (ftn) {
    DispatchToAgents(ftn, method, std::forward<Args>(args)...);
  }
}

template <typename Handler, typename... MethodArgs, typename... Args>
void DispatchToAgents(WebContents* web_contents,
                      void (Handler::*method)(MethodArgs...),
                      Args&&... args) {
  auto agent_host = DevToolsAgentHost::GetForTab(web_contents);
  if (agent_host) {
    DispatchToAgents(static_cast<DevToolsAgentHostImpl*>(agent_host.get()),
                     method, std::forward<Args>(args)...);
  }
  if (DevToolsAgentHost::HasFor(web_contents)) {
    DispatchToAgents(
        static_cast<DevToolsAgentHostImpl*>(
            DevToolsAgentHost::GetOrCreateFor(web_contents).get()),
        method, std::forward<Args>(args)...);
  }
}

std::unique_ptr<protocol::Audits::InspectorIssue> BuildHeavyAdIssue(
    const blink::mojom::HeavyAdIssueDetailsPtr& issue_details) {
  protocol::String status =
      (issue_details->resolution ==
       blink::mojom::HeavyAdResolutionStatus::kHeavyAdBlocked)
          ? protocol::Audits::HeavyAdResolutionStatusEnum::HeavyAdBlocked
          : protocol::Audits::HeavyAdResolutionStatusEnum::HeavyAdWarning;
  protocol::String reason_string;
  switch (issue_details->reason) {
    case blink::mojom::HeavyAdReason::kNetworkTotalLimit:
      reason_string = protocol::Audits::HeavyAdReasonEnum::NetworkTotalLimit;
      break;
    case blink::mojom::HeavyAdReason::kCpuTotalLimit:
      reason_string = protocol::Audits::HeavyAdReasonEnum::CpuTotalLimit;
      break;
    case blink::mojom::HeavyAdReason::kCpuPeakLimit:
      reason_string = protocol::Audits::HeavyAdReasonEnum::CpuPeakLimit;
      break;
  }
  auto heavy_ad_details =
      protocol::Audits::HeavyAdIssueDetails::Create()
          .SetReason(reason_string)
          .SetResolution(status)
          .SetFrame(protocol::Audits::AffectedFrame::Create()
                        .SetFrameId(issue_details->frame->frame_id)
                        .Build())
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetHeavyAdIssueDetails(std::move(heavy_ad_details))
          .Build();
  auto issue =
      protocol::Audits::InspectorIssue::Create()
          .SetCode(protocol::Audits::InspectorIssueCodeEnum::HeavyAdIssue)
          .SetDetails(std::move(protocol_issue_details))
          .Build();
  return issue;
}

protocol::Audits::AttributionReportingIssueType
BuildAttributionReportingIssueViolationType(
    blink::mojom::AttributionReportingIssueType type) {
  switch (type) {
    case blink::mojom::AttributionReportingIssueType::kPermissionPolicyDisabled:
      return AttributionReportingIssueTypeEnum::PermissionPolicyDisabled;
    case blink::mojom::AttributionReportingIssueType::
        kUntrustworthyReportingOrigin:
      return AttributionReportingIssueTypeEnum::UntrustworthyReportingOrigin;
    case blink::mojom::AttributionReportingIssueType::kInsecureContext:
      return AttributionReportingIssueTypeEnum::InsecureContext;
    case blink::mojom::AttributionReportingIssueType::
        kInvalidRegisterSourceHeader:
      return AttributionReportingIssueTypeEnum::InvalidHeader;
    case blink::mojom::AttributionReportingIssueType::
        kInvalidRegisterTriggerHeader:
      return AttributionReportingIssueTypeEnum::InvalidRegisterTriggerHeader;
    case blink::mojom::AttributionReportingIssueType::kSourceAndTriggerHeaders:
      return AttributionReportingIssueTypeEnum::SourceAndTriggerHeaders;
    case blink::mojom::AttributionReportingIssueType::kSourceIgnored:
      return AttributionReportingIssueTypeEnum::SourceIgnored;
    case blink::mojom::AttributionReportingIssueType::kTriggerIgnored:
      return AttributionReportingIssueTypeEnum::TriggerIgnored;
    case blink::mojom::AttributionReportingIssueType::kOsSourceIgnored:
      return AttributionReportingIssueTypeEnum::OsSourceIgnored;
    case blink::mojom::AttributionReportingIssueType::kOsTriggerIgnored:
      return AttributionReportingIssueTypeEnum::OsTriggerIgnored;
    case blink::mojom::AttributionReportingIssueType::
        kInvalidRegisterOsSourceHeader:
      return AttributionReportingIssueTypeEnum::InvalidRegisterOsSourceHeader;
    case blink::mojom::AttributionReportingIssueType::
        kInvalidRegisterOsTriggerHeader:
      return AttributionReportingIssueTypeEnum::InvalidRegisterOsTriggerHeader;
    case blink::mojom::AttributionReportingIssueType::kWebAndOsHeaders:
      return AttributionReportingIssueTypeEnum::WebAndOsHeaders;
    case blink::mojom::AttributionReportingIssueType::kNoWebOrOsSupport:
      return AttributionReportingIssueTypeEnum::NoWebOrOsSupport;
    case blink::mojom::AttributionReportingIssueType::
        kNavigationRegistrationWithoutTransientUserActivation:
      // This issue is not reported from the browser.
      NOTREACHED();
    case blink::mojom::AttributionReportingIssueType::kInvalidInfoHeader:
      return AttributionReportingIssueTypeEnum::InvalidInfoHeader;
    case blink::mojom::AttributionReportingIssueType::kNoRegisterSourceHeader:
      return AttributionReportingIssueTypeEnum::NoRegisterSourceHeader;
    case blink::mojom::AttributionReportingIssueType::kNoRegisterTriggerHeader:
      return AttributionReportingIssueTypeEnum::NoRegisterTriggerHeader;
    case blink::mojom::AttributionReportingIssueType::kNoRegisterOsSourceHeader:
      return AttributionReportingIssueTypeEnum::NoRegisterOsSourceHeader;
    case blink::mojom::AttributionReportingIssueType::
        kNoRegisterOsTriggerHeader:
      return AttributionReportingIssueTypeEnum::NoRegisterOsTriggerHeader;
    case blink::mojom::AttributionReportingIssueType::
        kNavigationRegistrationUniqueScopeAlreadySet:
      return AttributionReportingIssueTypeEnum::
          NavigationRegistrationUniqueScopeAlreadySet;
  }
}

std::unique_ptr<protocol::Audits::InspectorIssue>
BuildAttributionReportingIssue(
    const blink::mojom::AttributionReportingIssueDetailsPtr& issue_details) {
  protocol::String violation_type = BuildAttributionReportingIssueViolationType(
      issue_details->violation_type);

  auto request = protocol::Audits::AffectedRequest::Create()
                     .SetUrl(issue_details->request->url)
                     .Build();
  if (issue_details->request->request_id.has_value()) {
    request->SetRequestId(issue_details->request->request_id.value());
  }
  auto attribution_reporting_issue_details =
      protocol::Audits::AttributionReportingIssueDetails::Create()
          .SetViolationType(violation_type)
          .SetRequest(std::move(request))
          .Build();
  if (issue_details->invalid_parameter.has_value()) {
    attribution_reporting_issue_details->SetInvalidParameter(
        issue_details->invalid_parameter.value());
  }

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetAttributionReportingIssueDetails(
              std::move(attribution_reporting_issue_details))
          .Build();

  auto issue = protocol::Audits::InspectorIssue::Create()
                   .SetCode(protocol::Audits::InspectorIssueCodeEnum::
                                AttributionReportingIssue)
                   .SetDetails(std::move(protocol_issue_details))
                   .Build();
  return issue;
}

protocol::Audits::FederatedAuthRequestIssueReason
FederatedAuthRequestResultToProtocol(
    blink::mojom::FederatedAuthRequestResult result) {
  using blink::mojom::FederatedAuthRequestResult;
  namespace FederatedAuthRequestIssueReasonEnum =
      protocol::Audits::FederatedAuthRequestIssueReasonEnum;
  switch (result) {
    case FederatedAuthRequestResult::kShouldEmbargo: {
      return FederatedAuthRequestIssueReasonEnum::ShouldEmbargo;
    }
    case FederatedAuthRequestResult::kDisabledInSettings: {
      return FederatedAuthRequestIssueReasonEnum::DisabledInSettings;
    }
    case FederatedAuthRequestResult::kDisabledInFlags: {
      return FederatedAuthRequestIssueReasonEnum::DisabledInFlags;
    }
    case FederatedAuthRequestResult::kIdpNotPotentiallyTrustworthy: {
      return FederatedAuthRequestIssueReasonEnum::IdpNotPotentiallyTrustworthy;
    }
    case FederatedAuthRequestResult::kTooManyRequests: {
      return FederatedAuthRequestIssueReasonEnum::TooManyRequests;
    }
    case FederatedAuthRequestResult::kWellKnownHttpNotFound: {
      return FederatedAuthRequestIssueReasonEnum::WellKnownHttpNotFound;
    }
    case FederatedAuthRequestResult::kWellKnownNoResponse: {
      return FederatedAuthRequestIssueReasonEnum::WellKnownNoResponse;
    }
    case FederatedAuthRequestResult::kWellKnownInvalidResponse: {
      return FederatedAuthRequestIssueReasonEnum::WellKnownInvalidResponse;
    }
    case FederatedAuthRequestResult::kWellKnownListEmpty: {
      return FederatedAuthRequestIssueReasonEnum::WellKnownListEmpty;
    }
    case FederatedAuthRequestResult::kWellKnownInvalidContentType: {
      return FederatedAuthRequestIssueReasonEnum::WellKnownInvalidContentType;
    }
    case FederatedAuthRequestResult::kConfigNotInWellKnown: {
      return FederatedAuthRequestIssueReasonEnum::ConfigNotInWellKnown;
    }
    case FederatedAuthRequestResult::kWellKnownTooBig: {
      return FederatedAuthRequestIssueReasonEnum::WellKnownTooBig;
    }
    case FederatedAuthRequestResult::kConfigHttpNotFound: {
      return FederatedAuthRequestIssueReasonEnum::ConfigHttpNotFound;
    }
    case FederatedAuthRequestResult::kConfigNoResponse: {
      return FederatedAuthRequestIssueReasonEnum::ConfigNoResponse;
    }
    case FederatedAuthRequestResult::kConfigInvalidResponse: {
      return FederatedAuthRequestIssueReasonEnum::ConfigInvalidResponse;
    }
    case FederatedAuthRequestResult::kConfigInvalidContentType: {
      return FederatedAuthRequestIssueReasonEnum::ConfigInvalidContentType;
    }
    case FederatedAuthRequestResult::kClientMetadataHttpNotFound: {
      return FederatedAuthRequestIssueReasonEnum::ClientMetadataHttpNotFound;
    }
    case FederatedAuthRequestResult::kClientMetadataNoResponse: {
      return FederatedAuthRequestIssueReasonEnum::ClientMetadataNoResponse;
    }
    case FederatedAuthRequestResult::kClientMetadataInvalidResponse: {
      return FederatedAuthRequestIssueReasonEnum::ClientMetadataInvalidResponse;
    }
    case FederatedAuthRequestResult::kClientMetadataInvalidContentType: {
      return FederatedAuthRequestIssueReasonEnum::
          ClientMetadataInvalidContentType;
    }
    case FederatedAuthRequestResult::kAccountsHttpNotFound: {
      return FederatedAuthRequestIssueReasonEnum::AccountsHttpNotFound;
    }
    case FederatedAuthRequestResult::kAccountsNoResponse: {
      return FederatedAuthRequestIssueReasonEnum::AccountsNoResponse;
    }
    case FederatedAuthRequestResult::kAccountsInvalidResponse: {
      return FederatedAuthRequestIssueReasonEnum::AccountsInvalidResponse;
    }
    case FederatedAuthRequestResult::kAccountsListEmpty: {
      return FederatedAuthRequestIssueReasonEnum::AccountsListEmpty;
    }
    case FederatedAuthRequestResult::kAccountsInvalidContentType: {
      return FederatedAuthRequestIssueReasonEnum::AccountsInvalidContentType;
    }
    case FederatedAuthRequestResult::kIdTokenHttpNotFound: {
      return FederatedAuthRequestIssueReasonEnum::IdTokenHttpNotFound;
    }
    case FederatedAuthRequestResult::kIdTokenNoResponse: {
      return FederatedAuthRequestIssueReasonEnum::IdTokenNoResponse;
    }
    case FederatedAuthRequestResult::kIdTokenInvalidResponse: {
      return FederatedAuthRequestIssueReasonEnum::IdTokenInvalidResponse;
    }
    case FederatedAuthRequestResult::kIdTokenIdpErrorResponse: {
      return FederatedAuthRequestIssueReasonEnum::IdTokenIdpErrorResponse;
    }
    case FederatedAuthRequestResult::kIdTokenCrossSiteIdpErrorResponse: {
      return FederatedAuthRequestIssueReasonEnum::
          IdTokenCrossSiteIdpErrorResponse;
    }
    case FederatedAuthRequestResult::kIdTokenInvalidContentType: {
      return FederatedAuthRequestIssueReasonEnum::IdTokenInvalidContentType;
    }
    case FederatedAuthRequestResult::kCanceled: {
      return FederatedAuthRequestIssueReasonEnum::Canceled;
    }
    case FederatedAuthRequestResult::kRpPageNotVisible:
      return FederatedAuthRequestIssueReasonEnum::RpPageNotVisible;
    case FederatedAuthRequestResult::kError: {
      return FederatedAuthRequestIssueReasonEnum::ErrorIdToken;
    }
    case FederatedAuthRequestResult::kSilentMediationFailure: {
      return FederatedAuthRequestIssueReasonEnum::SilentMediationFailure;
    }
    case FederatedAuthRequestResult::kThirdPartyCookiesBlocked: {
      return FederatedAuthRequestIssueReasonEnum::ThirdPartyCookiesBlocked;
    }
    case FederatedAuthRequestResult::kNotSignedInWithIdp: {
      return FederatedAuthRequestIssueReasonEnum::NotSignedInWithIdp;
    }
    case FederatedAuthRequestResult::kMissingTransientUserActivation: {
      return FederatedAuthRequestIssueReasonEnum::
          MissingTransientUserActivation;
    }
    case FederatedAuthRequestResult::kReplacedByActiveMode: {
      return FederatedAuthRequestIssueReasonEnum::ReplacedByActiveMode;
    }
    case FederatedAuthRequestResult::kInvalidFieldsSpecified: {
      return FederatedAuthRequestIssueReasonEnum::InvalidFieldsSpecified;
    }
    case FederatedAuthRequestResult::kRelyingPartyOriginIsOpaque: {
      return FederatedAuthRequestIssueReasonEnum::RelyingPartyOriginIsOpaque;
    }
    case FederatedAuthRequestResult::kTypeNotMatching: {
      return FederatedAuthRequestIssueReasonEnum::TypeNotMatching;
    }
    case FederatedAuthRequestResult::kUiDismissedNoEmbargo: {
      return FederatedAuthRequestIssueReasonEnum::UiDismissedNoEmbargo;
    }
    case FederatedAuthRequestResult::kCorsError: {
      return FederatedAuthRequestIssueReasonEnum::CorsError;
    }
    case FederatedAuthRequestResult::kSuppressedBySegmentationPlatform: {
      return FederatedAuthRequestIssueReasonEnum::
          SuppressedBySegmentationPlatform;
    }
    case FederatedAuthRequestResult::kSuccess: {
      NOTREACHED();
    }
  }
}

std::unique_ptr<protocol::Audits::InspectorIssue>
BuildFederatedAuthRequestIssue(
    const blink::mojom::FederatedAuthRequestIssueDetailsPtr& issue_details) {
  auto federated_auth_request_details =
      protocol::Audits::FederatedAuthRequestIssueDetails::Create()
          .SetFederatedAuthRequestIssueReason(
              FederatedAuthRequestResultToProtocol(issue_details->status))
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetFederatedAuthRequestIssueDetails(
              std::move(federated_auth_request_details))
          .Build();

  auto issue = protocol::Audits::InspectorIssue::Create()
                   .SetCode(protocol::Audits::InspectorIssueCodeEnum::
                                FederatedAuthRequestIssue)
                   .SetDetails(std::move(protocol_issue_details))
                   .Build();
  return issue;
}

protocol::Audits::FederatedAuthUserInfoRequestIssueReason
FederatedAuthUserInfoRequestResultToProtocol(
    blink::mojom::FederatedAuthUserInfoRequestResult result) {
  using blink::mojom::FederatedAuthUserInfoRequestResult;
  namespace FederatedAuthUserInfoRequestIssueReasonEnum =
      protocol::Audits::FederatedAuthUserInfoRequestIssueReasonEnum;
  switch (result) {
    case FederatedAuthUserInfoRequestResult::kNotSameOrigin: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::NotSameOrigin;
    }
    case FederatedAuthUserInfoRequestResult::kNotIframe: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::NotIframe;
    }
    case FederatedAuthUserInfoRequestResult::kNotPotentiallyTrustworthy: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::
          NotPotentiallyTrustworthy;
    }
    case FederatedAuthUserInfoRequestResult::kNoApiPermission: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::NoApiPermission;
    }
    case FederatedAuthUserInfoRequestResult::kNotSignedInWithIdp: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::NotSignedInWithIdp;
    }
    case FederatedAuthUserInfoRequestResult::kNoAccountSharingPermission: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::
          NoAccountSharingPermission;
    }
    case FederatedAuthUserInfoRequestResult::kInvalidConfigOrWellKnown: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::
          InvalidConfigOrWellKnown;
    }
    case FederatedAuthUserInfoRequestResult::kInvalidAccountsResponse: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::
          InvalidAccountsResponse;
    }
    case FederatedAuthUserInfoRequestResult::
        kNoReturningUserFromFetchedAccounts: {
      return FederatedAuthUserInfoRequestIssueReasonEnum::
          NoReturningUserFromFetchedAccounts;
    }
    case FederatedAuthUserInfoRequestResult::kSuccess:
    case FederatedAuthUserInfoRequestResult::kUnhandledRequest: {
      NOTREACHED();
    }
  }
}

std::unique_ptr<protocol::Audits::InspectorIssue>
BuildFederatedAuthUserInfoRequestIssue(
    const blink::mojom::FederatedAuthUserInfoRequestIssueDetailsPtr&
        issue_details) {
  auto federated_auth_user_info_request_details =
      protocol::Audits::FederatedAuthUserInfoRequestIssueDetails::Create()
          .SetFederatedAuthUserInfoRequestIssueReason(
              FederatedAuthUserInfoRequestResultToProtocol(
                  issue_details->status))
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetFederatedAuthUserInfoRequestIssueDetails(
              std::move(federated_auth_user_info_request_details))
          .Build();

  auto issue = protocol::Audits::InspectorIssue::Create()
                   .SetCode(protocol::Audits::InspectorIssueCodeEnum::
                                FederatedAuthUserInfoRequestIssue)
                   .SetDetails(std::move(protocol_issue_details))
                   .Build();
  return issue;
}

const char* DeprecationIssueTypeToProtocol(
    blink::mojom::DeprecationIssueType error_type) {
  switch (error_type) {
    case blink::mojom::DeprecationIssueType::kPrivacySandboxExtensionsAPI:
      return kPrivacySandboxExtensionsAPI;
  }
}

std::unique_ptr<protocol::Audits::InspectorIssue> BuildDeprecationIssue(
    const blink::mojom::DeprecationIssueDetailsPtr& issue_details) {
  std::unique_ptr<protocol::Audits::SourceCodeLocation> source_code_location =
      protocol::Audits::SourceCodeLocation::Create()
          .SetUrl(issue_details->affected_location->url.value())
          .SetLineNumber(issue_details->affected_location->line)
          .SetColumnNumber(issue_details->affected_location->column)
          .Build();

  if (issue_details->affected_location->script_id.has_value()) {
    source_code_location->SetScriptId(
        issue_details->affected_location->script_id.value());
  }

  auto deprecation_issue_details =
      protocol::Audits::DeprecationIssueDetails::Create()
          .SetSourceCodeLocation(std::move(source_code_location))
          .SetType(DeprecationIssueTypeToProtocol(issue_details->type))
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetDeprecationIssueDetails(std::move(deprecation_issue_details))
          .Build();

  auto deprecation_issue =
      protocol::Audits::InspectorIssue::Create()
          .SetCode(protocol::Audits::InspectorIssueCodeEnum::DeprecationIssue)
          .SetDetails(std::move(protocol_issue_details))
          .Build();

  return deprecation_issue;
}

std::unique_ptr<protocol::Audits::InspectorIssue> BuildBounceTrackingIssue(
    const blink::mojom::BounceTrackingIssueDetailsPtr& issue_details) {
  auto bounce_tracking_issue_details =
      protocol::Audits::BounceTrackingIssueDetails::Create()
          .SetTrackingSites(std::make_unique<protocol::Array<protocol::String>>(
              issue_details->tracking_sites))
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetBounceTrackingIssueDetails(
              std::move(bounce_tracking_issue_details))
          .Build();

  auto issue =
      protocol::Audits::InspectorIssue::Create()
          .SetCode(
              protocol::Audits::InspectorIssueCodeEnum::BounceTrackingIssue)
          .SetDetails(std::move(protocol_issue_details))
          .Build();

  return issue;
}

std::unique_ptr<protocol::Audits::InspectorIssue> BuildPartitioningBlobURLIssue(
    const blink::mojom::PartitioningBlobURLIssueDetailsPtr& issue_details) {
  protocol::String partitioning_blob_url_info_string;
  switch (issue_details->partitioning_blob_url_info) {
    case blink::mojom::PartitioningBlobURLInfo::kBlockedCrossPartitionFetching:
      partitioning_blob_url_info_string = protocol::Audits::
          PartitioningBlobURLInfoEnum::BlockedCrossPartitionFetching;
      break;
    case blink::mojom::PartitioningBlobURLInfo::kEnforceNoopenerForNavigation:
      partitioning_blob_url_info_string = protocol::Audits::
          PartitioningBlobURLInfoEnum::EnforceNoopenerForNavigation;
      break;
    default:
      partitioning_blob_url_info_string = "Unknown";
      break;
  }

  auto partitioning_blob_url_issue_details =
      protocol::Audits::PartitioningBlobURLIssueDetails::Create()
          .SetUrl(issue_details->url.spec())
          .SetPartitioningBlobURLInfo(partitioning_blob_url_info_string)
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetPartitioningBlobURLIssueDetails(
              std::move(partitioning_blob_url_issue_details))
          .Build();

  auto issue = protocol::Audits::InspectorIssue::Create()
                   .SetCode(protocol::Audits::InspectorIssueCodeEnum::
                                PartitioningBlobURLIssue)
                   .SetDetails(std::move(protocol_issue_details))
                   .Build();

  return issue;
}

void UpdateChildFrameTrees(FrameTreeNode* ftn, bool update_target_info) {
  if (auto* agent_host = WebContentsDevToolsAgentHost::GetFor(
          WebContentsImpl::FromFrameTreeNode(ftn))) {
    agent_host->UpdateChildFrameTrees(update_target_info);
  }
}

}  // namespace

void OnResetNavigationRequest(NavigationRequest* navigation_request) {
  // Traverse frame chain all the way to the top and report to all
  // page handlers that the navigation completed.
  for (FrameTreeNode* node = navigation_request->frame_tree_node(); node;
       node = FrameTreeNode::From(node->parent())) {
    DispatchToAgents(node, &protocol::PageHandler::NavigationReset,
                     navigation_request);
  }
}

void OnNavigationResponseReceived(const NavigationRequest& nav_request,
                                  const network::mojom::URLResponseHead& head) {
  // This response is artificial (see CachedNavigationURLLoader), so we don't
  // want to report it.
  if (nav_request.IsPageActivation()) {
    return;
  }

  FrameTreeNode* ftn = nav_request.frame_tree_node();
  std::string id = nav_request.devtools_navigation_token().ToString();
  std::string frame_id =
      ftn->current_frame_host()->devtools_frame_token().ToString();
  GURL url = nav_request.common_params().url;

  network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
      network::ExtractDevToolsInfo(head);
  DispatchToAgents(ftn, &protocol::NetworkHandler::ResponseReceived, id, id,
                   url, protocol::Network::ResourceTypeEnum::Document,
                   *head_info, frame_id);
}

void OnFetchKeepAliveRequestWillBeSent(
    FrameTreeNode* frame_tree_node,
    const std::string& request_id,
    const network::ResourceRequest& request,
    std::optional<std::pair<const GURL&,
                            const network::mojom::URLResponseHeadDevToolsInfo&>>
        redirect_info) {
  CHECK(frame_tree_node);

  auto timestamp = base::TimeTicks::Now();
  std::string frame_token =
      frame_tree_node->current_frame_host()->devtools_frame_token().ToString();
  GURL initiator_url;
  if (request.request_initiator.has_value()) {
    initiator_url = request.request_initiator->GetURL();
  }
  DispatchToAgents(frame_tree_node,
                   &protocol::NetworkHandler::FetchKeepAliveRequestWillBeSent,
                   request_id, request, initiator_url, frame_token, timestamp,
                   redirect_info);
}

void OnFetchKeepAliveResponseReceived(
    FrameTreeNode* frame_tree_node,
    const std::string& request_id,
    const GURL& url,
    const network::mojom::URLResponseHead& head) {
  CHECK(frame_tree_node);

  std::string frame_token =
      frame_tree_node->current_frame_host()->devtools_frame_token().ToString();
  network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
      network::ExtractDevToolsInfo(head);
  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::ResponseReceived,
                   request_id, request_id, url,
                   protocol::Network::ResourceTypeEnum::Fetch, *head_info,
                   frame_token);
}

void OnFetchKeepAliveRequestComplete(
    FrameTreeNode* frame_tree_node,
    const std::string& request_id,
    const network::URLLoaderCompletionStatus& status) {
  CHECK(frame_tree_node);

  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::LoadingComplete,
                   request_id, protocol::Network::ResourceTypeEnum::Fetch,
                   status);
}

void BackForwardCacheNotUsed(
    const NavigationRequest* nav_request,
    const BackForwardCacheCanStoreDocumentResult* result,
    const BackForwardCacheCanStoreTreeResult* tree_result) {
  DCHECK(nav_request);
  FrameTreeNode* ftn = nav_request->frame_tree_node();
  DispatchToAgents(ftn, &protocol::PageHandler::BackForwardCacheNotUsed,
                   nav_request, result, tree_result);
}

void WillSwapFrameTreeNode(FrameTreeNode& old_node, FrameTreeNode& new_node) {
  auto* host = static_cast<RenderFrameDevToolsAgentHost*>(
      RenderFrameDevToolsAgentHost::GetFor(&old_node));
  if (!host || host->HasSessionsWithoutTabTargetSupport()) {
    return;
  }
  // The new node may have a previous host associated, disconnect it first.
  scoped_refptr<RenderFrameDevToolsAgentHost> previous_host =
      static_cast<RenderFrameDevToolsAgentHost*>(
          RenderFrameDevToolsAgentHost::GetFor(&new_node));
  // Disconnect old host entirely, so it detaches from renderer and does not
  // cause problem if renderer comes back from the BFCache.
  previous_host->DisconnectWebContents();
  host->SetFrameTreeNode(&new_node);
}

void OnFrameTreeNodeDestroyed(FrameTreeNode& frame_tree_node) {
  // If the child frame is an OOPIF, we emit Page.frameDetached event which
  // otherwise might be lost because the OOPIF target is being destroyed.
  RenderFrameHostImpl* parent = frame_tree_node.parent();
  if (!parent) {
    return;
  }
  if (RenderFrameDevToolsAgentHost::GetFor(&frame_tree_node) !=
      RenderFrameDevToolsAgentHost::GetFor(parent)) {
    DispatchToAgents(
        RenderFrameDevToolsAgentHost::GetFor(parent),
        &protocol::PageHandler::OnFrameDetached,
        frame_tree_node.current_frame_host()->devtools_frame_token());
  }
}

void DidUpdatePolicyContainerHost(FrameTreeNode* ftn) {
  if (!ftn) {
    return;
  }

  DispatchToAgents(ftn,
                   &protocol::NetworkHandler::OnPolicyContainerHostUpdated);
}

void DidUpdateSpeculationCandidates(
    RenderFrameHost& rfh,
    const std::vector<blink::mojom::SpeculationCandidatePtr>& candidates) {
  if (auto* storage = DevToolsPreloadStorage::GetForCurrentDocument(&rfh)) {
    storage->SpeculationCandidatesUpdated(candidates);
  }
}

void DidUpdatePrefetchStatus(
    FrameTreeNode* ftn,
    const base::UnguessableToken& initiator_devtools_navigation_token,
    const GURL& prefetch_url,
    const base::UnguessableToken& preload_pipeline_id,
    PreloadingTriggeringOutcome status,
    PrefetchStatus prefetch_status,
    const std::string& request_id) {
  if (!ftn) {
    return;
  }

  // See a comment in `PreloadingDecider::ctor()`.
  auto* devtools_preload_storage =
      DevToolsPreloadStorage::GetForCurrentDocument(ftn->current_frame_host());
  if (!devtools_preload_storage) {
    return;
  }

  // We update DevToolsPreloadStorage, even if there are no active DevTools
  // sessions, to persist the latest status update.
  devtools_preload_storage->UpdatePrefetchStatus(
      prefetch_url, preload_pipeline_id, status, prefetch_status, request_id);

  std::string initiating_frame_id =
      ftn->current_frame_host()->devtools_frame_token().ToString();
  DispatchToAgents(ftn, &protocol::PreloadHandler::DidUpdatePrefetchStatus,
                   initiator_devtools_navigation_token, initiating_frame_id,
                   prefetch_url, preload_pipeline_id, status, prefetch_status,
                   request_id);
}

void OnPrefetchRequestWillBeSent(
    FrameTreeNode& ftn,
    const std::string& request_id,
    const GURL& initiator,
    const network::ResourceRequest& request,
    std::optional<std::pair<const GURL&,
                            const network::mojom::URLResponseHeadDevToolsInfo&>>
        redirect_info) {
  auto timestamp = base::TimeTicks::Now();
  std::string frame_token =
      ftn.current_frame_host()->devtools_frame_token().ToString();
  DispatchToAgents(&ftn, &protocol::NetworkHandler::PrefetchRequestWillBeSent,
                   request_id, request, initiator, frame_token, timestamp,
                   redirect_info);
}

void OnPrefetchResponseReceived(FrameTreeNode* frame_tree_node,
                                const std::string& request_id,
                                const GURL& url,
                                const network::mojom::URLResponseHead& head) {
  std::string frame_token =
      frame_tree_node->current_frame_host()->devtools_frame_token().ToString();

  network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
      network::ExtractDevToolsInfo(head);
  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::ResponseReceived,
                   request_id, request_id, url,
                   protocol::Network::ResourceTypeEnum::Prefetch, *head_info,
                   frame_token);
}

void OnPrefetchRequestComplete(
    FrameTreeNode* frame_tree_node,
    const std::string& request_id,
    const network::URLLoaderCompletionStatus& status) {
  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::LoadingComplete,
                   request_id, protocol::Network::ResourceTypeEnum::Prefetch,
                   status);
}

void OnPrefetchBodyDataReceived(FrameTreeNode* frame_tree_node,
                                const std::string& request_id,
                                const std::string& body,
                                bool is_base64_encoded) {
  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::BodyDataReceived,
                   request_id, body, is_base64_encoded);
}

bool IsPrerenderAllowed(FrameTree& frame_tree) {
  FrameTreeNode* ftn = frame_tree.root();

  auto* render_frame_agent_host = static_cast<RenderFrameDevToolsAgentHost*>(
      RenderFrameDevToolsAgentHost::GetFor(ftn));
  if (render_frame_agent_host &&
      render_frame_agent_host->HasSessionsWithoutTabTargetSupport()) {
    return false;
  }

  bool is_allowed = true;
  DispatchToAgents(ftn, &protocol::PageHandler::IsPrerenderingAllowed,
                   is_allowed);
  return is_allowed;
}

void WillInitiatePrerender(FrameTree& frame_tree) {
  DCHECK(frame_tree.is_prerendering());
  auto* wc = WebContentsImpl::FromFrameTreeNode(frame_tree.root());
  if (auto* host = WebContentsDevToolsAgentHost::GetFor(wc)) {
    host->WillInitiatePrerender(frame_tree.root());
  }
}

void DidActivatePrerender(const NavigationRequest& nav_request,
                          const std::optional<base::UnguessableToken>&
                              initiator_devtools_navigation_token) {
  FrameTreeNode* ftn = nav_request.frame_tree_node();
  UpdateChildFrameTrees(ftn, /* update_target_info= */ true);
}

void DidUpdatePrerenderStatus(
    FrameTreeNodeId initiator_frame_tree_node_id,
    const base::UnguessableToken& initiator_devtools_navigation_token,
    blink::mojom::SpeculationAction action,
    const GURL& prerender_url,
    std::optional<blink::mojom::SpeculationTargetHint> target_hint,
    const base::UnguessableToken& preload_pipeline_id,
    PreloadingTriggeringOutcome status,
    std::optional<PrerenderFinalStatus> prerender_status,
    std::optional<std::string> disallowed_mojo_interface,
    const std::vector<PrerenderMismatchedHeaders>* mismatched_headers) {
  auto* ftn = FrameTreeNode::GloballyFindByID(initiator_frame_tree_node_id);
  // ftn will be null if this is browser-initiated, which has no initiator.
  if (!ftn) {
    return;
  }

  // See a comment in `PreloadingDecider::ctor()`.
  auto* devtools_preload_storage =
      DevToolsPreloadStorage::GetForCurrentDocument(ftn->current_frame_host());
  if (!devtools_preload_storage) {
    return;
  }

  // We update DevToolsPreloadStorage, even if there are no active DevTools
  // sessions, to persist the latest status update.
  devtools_preload_storage->UpdatePrerenderStatus(
      action, prerender_url, target_hint, preload_pipeline_id, status,
      prerender_status, disallowed_mojo_interface, mismatched_headers);

  DispatchToAgents(ftn, &protocol::PreloadHandler::DidUpdatePrerenderStatus,
                   initiator_devtools_navigation_token, action, prerender_url,
                   target_hint, preload_pipeline_id, status, prerender_status,
                   disallowed_mojo_interface, mismatched_headers);
}

namespace {

protocol::String BuildBlockedByResponseReason(
    network::mojom::BlockedByResponseReason reason) {
  // TODO(crbug.com/336752983):
  // Add specific error messages when a subresource load was blocked due to
  // Document-Isolation-Policy (Dip).
  switch (reason) {
    case network::mojom::BlockedByResponseReason::
        kCoepFrameResourceNeedsCoepHeader:
      return protocol::Audits::BlockedByResponseReasonEnum::
          CoepFrameResourceNeedsCoepHeader;
    case network::mojom::BlockedByResponseReason::
        kCoopSandboxedIFrameCannotNavigateToCoopPage:
      return protocol::Audits::BlockedByResponseReasonEnum::
          CoopSandboxedIFrameCannotNavigateToCoopPage;
    case network::mojom::BlockedByResponseReason::kCorpNotSameOrigin:
      return protocol::Audits::BlockedByResponseReasonEnum::CorpNotSameOrigin;
    case network::mojom::BlockedByResponseReason::
        kCorpNotSameOriginAfterDefaultedToSameOriginByCoep:
    case network::mojom::BlockedByResponseReason::
        kCorpNotSameOriginAfterDefaultedToSameOriginByDip:
    case network::mojom::BlockedByResponseReason::
        kCorpNotSameOriginAfterDefaultedToSameOriginByCoepAndDip:
      return protocol::Audits::BlockedByResponseReasonEnum::
          CorpNotSameOriginAfterDefaultedToSameOriginByCoep;
    case network::mojom::BlockedByResponseReason::kCorpNotSameSite:
      return protocol::Audits::BlockedByResponseReasonEnum::CorpNotSameSite;
    case network::mojom::BlockedByResponseReason::kSRIMessageSignatureMismatch:
      return protocol::Audits::BlockedByResponseReasonEnum::
          SRIMessageSignatureMismatch;
  }
}

void ReportBlockedByResponseIssue(
    const GURL& url,
    std::string& requestId,
    FrameTreeNode* ftn,
    RenderFrameHostImpl* parent_frame,
    const network::URLLoaderCompletionStatus& status) {
  DCHECK(status.blocked_by_response_reason);

  auto issueDetails = protocol::Audits::InspectorIssueDetails::Create();
  auto request = protocol::Audits::AffectedRequest::Create()
                     .SetRequestId(requestId)
                     .SetUrl(url.spec())
                     .Build();
  auto blockedByResponseDetails =
      protocol::Audits::BlockedByResponseIssueDetails::Create()
          .SetRequest(std::move(request))
          .SetReason(
              BuildBlockedByResponseReason(*status.blocked_by_response_reason))
          .Build();

  blockedByResponseDetails->SetBlockedFrame(
      protocol::Audits::AffectedFrame::Create()
          .SetFrameId(
              ftn->current_frame_host()->devtools_frame_token().ToString())
          .Build());
  if (parent_frame) {
    blockedByResponseDetails->SetParentFrame(
        protocol::Audits::AffectedFrame::Create()
            .SetFrameId(parent_frame->devtools_frame_token().ToString())
            .Build());
  }

  issueDetails.SetBlockedByResponseIssueDetails(
      std::move(blockedByResponseDetails));

  auto inspector_issue =
      protocol::Audits::InspectorIssue::Create()
          .SetCode(
              protocol::Audits::InspectorIssueCodeEnum::BlockedByResponseIssue)
          .SetDetails(issueDetails.Build())
          .Build();

  ReportBrowserInitiatedIssue(ftn->current_frame_host(),
                              std::move(inspector_issue));
}

}  // namespace

void OnNavigationRequestFailed(
    const NavigationRequest& nav_request,
    const network::URLLoaderCompletionStatus& status) {
  FrameTreeNode* ftn = nav_request.frame_tree_node();
  std::string id = nav_request.devtools_navigation_token().ToString();

  if (status.blocked_by_response_reason) {
    ReportBlockedByResponseIssue(
        const_cast<NavigationRequest&>(nav_request).GetURL(), id, ftn,
        ftn->parent(), status);
  }

  // If a BFCache navigation fails, it will be restarted as a regular
  // navigation, so we don't want to report this failure.
  if (nav_request.IsServedFromBackForwardCache()) {
    return;
  }

  // Activation of a prerender page is synchronous with its own activation flow
  // (crrev.com/c/2992411); if the prerender is cancelled (e.g. speculation rule
  // removed), the flow will fallback to a normal navigation, which is no longer
  // considered as a page activation.
  DCHECK(!nav_request.IsPageActivation());

  DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id,
                   protocol::Network::ResourceTypeEnum::Document, status);
}

bool ShouldBypassCSP(const NavigationRequest& nav_request) {
  DevToolsAgentHostImpl* agent_host =
      RenderFrameDevToolsAgentHost::GetFor(nav_request.frame_tree_node());
  if (!agent_host) {
    return false;
  }

  for (auto* page : protocol::PageHandler::ForAgentHost(agent_host)) {
    if (page->ShouldBypassCSP()) {
      return true;
    }
  }
  return false;
}

bool ShouldBypassCertificateErrors(DevToolsAgentHost* agent_host) {
  if (!agent_host) {
    return false;
  }

  DevToolsAgentHostImpl* host_impl =
      static_cast<DevToolsAgentHostImpl*>(agent_host);
  for (auto* security_handler :
       protocol::SecurityHandler::ForAgentHost(host_impl)) {
    if (security_handler->IsIgnoreCertificateErrorsSet()) {
      return true;
    }
  }
  return false;
}

bool ShouldBypassCertificateErrors() {
  for (auto* browser_agent_host : BrowserDevToolsAgentHost::Instances()) {
    if (ShouldBypassCertificateErrors(browser_agent_host)) {
      return true;
    }
  }
  return false;
}

void ApplyNetworkOverridesForDownload(
    RenderFrameHostImpl* rfh,
    download::DownloadUrlParameters* parameters) {
  FrameTreeNode* ftn =
      FrameTreeNode::GloballyFindByID(rfh->GetFrameTreeNodeId());
  if (ftn) {
    DispatchToAgents(
        ftn, &protocol::EmulationHandler::ApplyNetworkOverridesForDownload,
        parameters);
  }
}

void WillBeginDownload(download::DownloadCreateInfo* info,
                       download::DownloadItem* item) {
  if (!item) {
    return;
  }
  auto* rfh = static_cast<RenderFrameHostImpl*>(
      RenderFrameHost::FromID(info->render_process_id, info->render_frame_id));
  FrameTreeNode* ftn =
      rfh ? FrameTreeNode::GloballyFindByID(rfh->GetFrameTreeNodeId())
          : nullptr;
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn, &protocol::BrowserHandler::DownloadWillBegin, ftn,
                   item);
  DispatchToAgents(ftn, &protocol::PageHandler::DownloadWillBegin, ftn, item);

  for (auto* agent_host : BrowserDevToolsAgentHost::Instances()) {
    for (auto* browser_handler :
         protocol::BrowserHandler::ForAgentHost(agent_host)) {
      browser_handler->DownloadWillBegin(ftn, item);
    }
  }
}

void OnSignedExchangeReceived(
    FrameTreeNode* frame_tree_node,
    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) {
  DispatchToAgents(frame_tree_node,
                   &protocol::NetworkHandler::OnSignedExchangeReceived,
                   devtools_navigation_token, outer_request_url, outer_response,
                   envelope, certificate, ssl_info, errors);
}

namespace inspector_will_send_navigation_request_event {
std::unique_ptr<base::trace_event::TracedValue> Data(
    const base::UnguessableToken& request_id) {
  auto value = std::make_unique<base::trace_event::TracedValue>();
  value->SetString("requestId", request_id.ToString());
  return value;
}
}  // namespace inspector_will_send_navigation_request_event

void OnSignedExchangeCertificateRequestSent(
    FrameTreeNode* frame_tree_node,
    const base::UnguessableToken& request_id,
    const base::UnguessableToken& loader_id,
    const network::ResourceRequest& request,
    const GURL& signed_exchange_url) {
  // Make sure both back-ends yield the same timestamp.
  auto timestamp = base::TimeTicks::Now();
  network::mojom::URLRequestDevToolsInfoPtr request_info =
      network::ExtractDevToolsInfo(request);
  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::RequestSent,
                   request_id.ToString(), loader_id.ToString(), request.headers,
                   *request_info,
                   protocol::Network::Initiator::TypeEnum::SignedExchange,
                   signed_exchange_url, /*initiator_devtools_request_id=*/"",
                   /*frame_token=*/std::nullopt, timestamp);

  auto value = std::make_unique<base::trace_event::TracedValue>();
  value->SetString("requestId", request_id.ToString());
  TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
      "devtools.timeline", "ResourceWillSendRequest", TRACE_EVENT_SCOPE_PROCESS,
      timestamp, "data",
      inspector_will_send_navigation_request_event::Data(request_id));
}

void OnSignedExchangeCertificateResponseReceived(
    FrameTreeNode* frame_tree_node,
    const base::UnguessableToken& request_id,
    const base::UnguessableToken& loader_id,
    const GURL& url,
    const network::mojom::URLResponseHead& head) {
  network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
      network::ExtractDevToolsInfo(head);
  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::ResponseReceived,
                   request_id.ToString(), loader_id.ToString(), url,
                   protocol::Network::ResourceTypeEnum::Other, *head_info,
                   std::nullopt);
}

void OnSignedExchangeCertificateRequestCompleted(
    FrameTreeNode* frame_tree_node,
    const base::UnguessableToken& request_id,
    const network::URLLoaderCompletionStatus& status) {
  DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::LoadingComplete,
                   request_id.ToString(),
                   protocol::Network::ResourceTypeEnum::Other, status);
}

void ThrottleForServiceWorkerAgentHost(
    ServiceWorkerDevToolsAgentHost* agent_host,
    DevToolsAgentHostImpl* requesting_agent_host,
    scoped_refptr<DevToolsThrottleHandle> throttle_handle) {
  for (auto* target_handler :
       protocol::TargetHandler::ForAgentHost(requesting_agent_host)) {
    target_handler->AddWorkerThrottle(agent_host, throttle_handle);
  }
}

void CreateAndAddNavigationThrottles(NavigationThrottleRegistry& registry) {
  auto* navigation_handle = &registry.GetNavigationHandle();
  FrameTreeNode* frame_tree_node =
      NavigationRequest::From(navigation_handle)->frame_tree_node();
  FrameTreeNode* parent = FrameTreeNode::From(frame_tree_node->parent());

  if (!parent) {
    FrameTreeNode* outer_delegate_node =
        frame_tree_node->render_manager()->GetOuterDelegateNode();
    if (outer_delegate_node && frame_tree_node->IsFencedFrameRoot()) {
      parent = outer_delegate_node->parent()->frame_tree_node();
    } else if (frame_tree_node->GetFrameType() ==
                   FrameType::kPrerenderMainFrame &&
               !frame_tree_node->current_frame_host()
                    ->has_committed_any_navigation()) {
      if (auto* agent_host = WebContentsDevToolsAgentHost::GetFor(
              WebContentsImpl::FromFrameTreeNode(frame_tree_node))) {
        // For prerender, perform auto-attach to tab target at the point of
        // initial navigation.
        agent_host->auto_attacher()->CreateAndAddNavigationThrottles(registry);
        return;
      }
    }
  }

  if (parent) {
    if (auto* agent_host = RenderFrameDevToolsAgentHost::GetFor(parent)) {
      agent_host->auto_attacher()->CreateAndAddNavigationThrottles(registry);
    }
  } else {
    for (DevToolsAgentHostImpl* host : BrowserDevToolsAgentHost::Instances()) {
      host->auto_attacher()->CreateAndAddNavigationThrottles(registry);
    }
  }
}

void ThrottleServiceWorkerMainScriptFetch(
    ServiceWorkerContextWrapper* wrapper,
    int64_t version_id,
    const GlobalRenderFrameHostId& requesting_frame_id,
    scoped_refptr<DevToolsThrottleHandle> throttle_handle) {
  ServiceWorkerDevToolsAgentHost* agent_host =
      ServiceWorkerDevToolsManager::GetInstance()
          ->GetDevToolsAgentHostForNewInstallingWorker(wrapper, version_id);
  DCHECK(agent_host);

  // TODO(crbug.com/40276949): We should probably also add the
  // possibility for Browser wide agents to throttle the request.

  // If we have a requesting_frame_id, we should have a frame and a frame tree
  // node. However since the lifetime of these objects can be complex, we check
  // at each step that we indeed can go reach all the way to the FrameTreeNode.
  if (!requesting_frame_id) {
    return;
  }

  RenderFrameHostImpl* requesting_frame =
      RenderFrameHostImpl::FromID(requesting_frame_id);
  if (!requesting_frame) {
    return;
  }

  FrameTreeNode* ftn = requesting_frame->frame_tree_node();
  DCHECK(ftn);

  DevToolsAgentHostImpl* requesting_agent_host =
      RenderFrameDevToolsAgentHost::GetFor(ftn);
  if (!requesting_agent_host) {
    return;
  }

  ThrottleForServiceWorkerAgentHost(agent_host, requesting_agent_host,
                                    throttle_handle);
}

void ThrottleWorkerMainScriptFetch(
    const base::UnguessableToken& devtools_worker_token,
    const GlobalRenderFrameHostId& ancestor_render_frame_host_id,
    scoped_refptr<DevToolsThrottleHandle> throttle_handle) {
  DedicatedWorkerDevToolsAgentHost* agent_host =
      WorkerDevToolsManager::GetInstance().GetDevToolsHostFromToken(
          devtools_worker_token);
  if (!agent_host) {
    return;
  }

  RenderFrameHostImpl* rfh =
      RenderFrameHostImpl::FromID(ancestor_render_frame_host_id);
  if (!rfh) {
    return;
  }

  FrameTreeNode* ftn = rfh->frame_tree_node();
  DispatchToAgents(ftn, &protocol::TargetHandler::AddWorkerThrottle, agent_host,
                   std::move(throttle_handle));
}

bool ShouldWaitForDebuggerInWindowOpen() {
  for (auto* browser_agent_host : BrowserDevToolsAgentHost::Instances()) {
    for (auto* target_handler :
         protocol::TargetHandler::ForAgentHost(browser_agent_host)) {
      if (target_handler->ShouldThrottlePopups()) {
        return true;
      }
    }
  }
  return false;
}

DevtoolsOverriddenOutputParams ApplyEmulationOverrides(
    DevToolsAgentHostImpl* agent_host,
    net::HttpRequestHeaders* headers) {
  DevtoolsOverriddenOutputParams output_params;
  for (auto* emulation : protocol::EmulationHandler::ForAgentHost(agent_host)) {
    bool ua_overridden = false;
    bool accept_language_overridden = false;
    emulation->ApplyOverrides(headers, &ua_overridden,
                              &accept_language_overridden);

    output_params.user_agent_overridden |= ua_overridden;
    output_params.accept_language_overridden |= accept_language_overridden;
  }
  return output_params;
}

namespace {
// This is a helper function used in ApplyNetworkRequestOverrides and
// ApplyUserAgentMetadataOverrides to help correctly set network request header
// overrides. It behaves the same as RenderFrameDevToolsAgentHost::GetFor for
// all FrameTreeNodes except those that are prerendering. For prerendering
// FrameTreeNodes, it returns the DevToolsAgentHost of the primary main frame,
// even if it has a DTAH of its own. The network header overrides are applied
// too early, before the correct values sent by the client are propagated to the
// prerender's DTAH's handlers. As a result, we use the values that were
// previously set for the primary main frame.
DevToolsAgentHostImpl* GetDevToolsAgentHostForNetworkOverrides(
    FrameTreeNode* frame_tree_node) {
  if (frame_tree_node->frame_tree().is_prerendering()) {
    return RenderFrameDevToolsAgentHost::GetFor(
        WebContentsImpl::FromFrameTreeNode(frame_tree_node)
            ->GetPrimaryMainFrame()
            ->frame_tree_node());
  }
  return RenderFrameDevToolsAgentHost::GetFor(frame_tree_node);
}

void ApplyNetworkRequestOverrides(
    DevToolsAgentHostImpl* agent_host,
    net::HttpRequestHeaders* headers,
    bool* disable_cache,
    bool* network_instrumentation_enabled,
    bool* skip_service_worker,
    std::optional<std::vector<net::SourceStreamType>>*
        devtools_accepted_stream_types,
    bool* devtools_user_agent_overridden,
    bool* devtools_accept_language_overridden,
    GURL* referrer_override) {
  for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
    if (!network->enabled()) {
      continue;
    }
    if (network_instrumentation_enabled) {
      *network_instrumentation_enabled = true;
    }
    network->ApplyOverrides(headers, skip_service_worker, disable_cache,
                            devtools_accepted_stream_types, referrer_override);
  }

  DevtoolsOverriddenOutputParams output_params =
      ApplyEmulationOverrides(agent_host, headers);
  if (devtools_user_agent_overridden) {
    *devtools_user_agent_overridden = output_params.user_agent_overridden;
  }
  if (devtools_accept_language_overridden) {
    *devtools_accept_language_overridden =
        output_params.accept_language_overridden;
  }
}

}  // namespace

void ApplyAuctionNetworkRequestOverrides(
    FrameTreeNode* frame_tree_node,
    network::ResourceRequest* request,
    bool* network_instrumentation_enabled) {
  bool disable_cache = false;
  DevToolsAgentHostImpl* agent_host =
      GetDevToolsAgentHostForNetworkOverrides(frame_tree_node);
  if (!agent_host) {
    return;
  }
  ApplyNetworkRequestOverrides(
      agent_host, &request->headers, &disable_cache,
      network_instrumentation_enabled, &request->skip_service_worker,
      &request->devtools_accepted_stream_types, nullptr, nullptr, nullptr);
  if (disable_cache) {
    request->load_flags = net::LOAD_BYPASS_CACHE;
  }
}

void ApplyNetworkRequestOverrides(
    FrameTreeNode* frame_tree_node,
    blink::mojom::BeginNavigationParams* begin_params,
    bool* report_raw_headers,
    std::optional<std::vector<net::SourceStreamType>>*
        devtools_accepted_stream_types,
    bool* devtools_user_agent_overridden,
    bool* devtools_accept_language_overridden,
    GURL* referrer_override) {
  *devtools_user_agent_overridden = false;
  *devtools_accept_language_overridden = false;
  bool disable_cache = false;
  DevToolsAgentHostImpl* agent_host =
      GetDevToolsAgentHostForNetworkOverrides(frame_tree_node);
  if (!agent_host) {
    return;
  }
  net::HttpRequestHeaders headers;
  headers.AddHeadersFromString(begin_params->headers);
  ApplyNetworkRequestOverrides(
      agent_host, &headers, &disable_cache, report_raw_headers,
      &begin_params->skip_service_worker, devtools_accepted_stream_types,
      devtools_user_agent_overridden, devtools_accept_language_overridden,
      referrer_override);
  if (disable_cache) {
    begin_params->load_flags &=
        ~(net::LOAD_VALIDATE_CACHE | net::LOAD_SKIP_CACHE_VALIDATION |
          net::LOAD_ONLY_FROM_CACHE | net::LOAD_DISABLE_CACHE);
    begin_params->load_flags |= net::LOAD_BYPASS_CACHE;
  }

  begin_params->headers = headers.ToString();
}

bool ApplyUserAgentMetadataOverrides(
    FrameTreeNode* frame_tree_node,
    std::optional<blink::UserAgentMetadata>* override_out) {
  DevToolsAgentHostImpl* agent_host =
      GetDevToolsAgentHostForNetworkOverrides(frame_tree_node);
  if (!agent_host) {
    return false;
  }

  bool result = false;
  for (auto* emulation : protocol::EmulationHandler::ForAgentHost(agent_host)) {
    result = emulation->ApplyUserAgentMetadataOverrides(override_out) || result;
  }

  return result;
}

bool ApplyNetworkCookieControlsOverrides(
    RenderFrameHostImpl& rfh,
    net::CookieSettingOverrides& overrides) {
  FrameTreeNode* ftn = rfh.frame_tree_node();
  if (!ftn) {
    return false;
  }
  DevToolsAgentHostImpl* agent_host =
      GetDevToolsAgentHostForNetworkOverrides(ftn);

  return ApplyNetworkCookieControlsOverrides(agent_host, overrides);
}

bool ApplyNetworkCookieControlsOverrides(
    DevToolsAgentHostImpl* agent_host,
    net::CookieSettingOverrides& overrides) {
  if (!agent_host) {
    return false;
  }
  for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
    if (network->enabled()) {
      network->ApplyCookieControlsOverrides(overrides);
    }
  }
  return !overrides.empty();
}

namespace {
template <typename HandlerType>
bool MaybeCreateProxyForInterception(
    DevToolsAgentHostImpl* agent_host,
    int process_id,
    StoragePartition* storage_partition,
    const base::UnguessableToken& frame_token,
    bool is_navigation,
    bool is_download,
    network::mojom::URLLoaderFactoryOverride* agent_override) {
  if (!agent_host) {
    return false;
  }
  bool had_interceptors = false;
  const auto& handlers = HandlerType::ForAgentHost(agent_host);
  for (const auto& handler : base::Reversed(handlers)) {
    had_interceptors |= handler->MaybeCreateProxyForInterception(
        process_id, storage_partition, frame_token, is_navigation, is_download,
        agent_override);
  }
  return had_interceptors;
}

}  // namespace

bool WillCreateURLLoaderFactoryParams::Run(
    bool is_navigation,
    bool is_download,
    network::URLLoaderFactoryBuilder& factory_builder,
    network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
  CHECK(!is_download || is_navigation);

  network::mojom::URLLoaderFactoryOverride devtools_override;
  // If caller passed some existing overrides, use those.
  // Otherwise, use our local var, then if handlers actually
  // decide to intercept, move it to |factory_override|.
  network::mojom::URLLoaderFactoryOverride* handler_override =
      factory_override && *factory_override ? factory_override->get()
                                            : &devtools_override;

  // Order of targets and sessions matters -- the latter proxy is created,
  // the closer it is to the network. So start with frame's NetworkHandler,
  // then process frame's FetchHandler and then browser's FetchHandler.
  // Within the target, the agents added earlier are closer to network.
  bool had_interceptors =
      MaybeCreateProxyForInterception<protocol::NetworkHandler>(
          agent_host_, process_id_, storage_partition_, devtools_token_,
          is_navigation, is_download, handler_override);

  had_interceptors |= MaybeCreateProxyForInterception<protocol::FetchHandler>(
      agent_host_, process_id_, storage_partition_, devtools_token_,
      is_navigation, is_download, handler_override);

  // TODO(caseq): assure deterministic order of browser agents (or sessions).
  for (auto* browser_agent_host : BrowserDevToolsAgentHost::Instances()) {
    had_interceptors |= MaybeCreateProxyForInterception<protocol::FetchHandler>(
        browser_agent_host, process_id_, storage_partition_, devtools_token_,
        is_navigation, is_download, handler_override);
  }
  if (!had_interceptors) {
    return false;
  }
  CHECK(handler_override->overriding_factory);
  CHECK(handler_override->overridden_factory_receiver);
  if (!factory_override) {
    // Not a subresource navigation, so just override the target receiver.
    auto [receiver, remote] = factory_builder.Append();
    mojo::FusePipes(std::move(receiver),
                    std::move(devtools_override.overriding_factory));
    mojo::FusePipes(std::move(devtools_override.overridden_factory_receiver),
                    std::move(remote));
  } else if (!*factory_override) {
    // No other overrides, so just returns ours as is.
    *factory_override = network::mojom::URLLoaderFactoryOverride::New(
        std::move(devtools_override.overriding_factory),
        std::move(devtools_override.overridden_factory_receiver),
        /*skip_cors_enabled_scheme_check=*/false);
  }
  // ... else things are already taken care of, as handler_override was pointing
  // to factory override and we've done all magic in-place.
  CHECK(!devtools_override.overriding_factory);
  CHECK(!devtools_override.overridden_factory_receiver);

  return true;
}

WillCreateURLLoaderFactoryParams::WillCreateURLLoaderFactoryParams(
    DevToolsAgentHostImpl* agent_host,
    const base::UnguessableToken& devtools_token,
    int process_id,
    StoragePartition* storage_partition)
    : agent_host_(agent_host),
      devtools_token_(devtools_token),
      process_id_(process_id),
      storage_partition_(storage_partition) {}

WillCreateURLLoaderFactoryParams WillCreateURLLoaderFactoryParams::ForFrame(
    RenderFrameHostImpl* rfh) {
  return WillCreateURLLoaderFactoryParams(
      RenderFrameDevToolsAgentHost::GetFor(rfh), rfh->GetDevToolsFrameToken(),
      rfh->GetProcess()->GetDeprecatedID(),
      rfh->GetProcess()->GetStoragePartition());
}

WillCreateURLLoaderFactoryParams
WillCreateURLLoaderFactoryParams::ForServiceWorker(RenderProcessHost& rph,
                                                   int routing_id) {
  ServiceWorkerDevToolsAgentHost* agent_host =
      ServiceWorkerDevToolsManager::GetInstance()
          ->GetDevToolsAgentHostForWorker(rph.GetDeprecatedID(), routing_id);
  CHECK(agent_host);
  return WillCreateURLLoaderFactoryParams(
      agent_host, agent_host->devtools_worker_token(), rph.GetDeprecatedID(),
      rph.GetStoragePartition());
}

std::optional<WillCreateURLLoaderFactoryParams>
WillCreateURLLoaderFactoryParams::ForServiceWorkerMainScript(
    const ServiceWorkerContextWrapper* context_wrapper,
    std::optional<int64_t> version_id) {
  if (!version_id.has_value()) {
    return std::nullopt;
  }

  // If we have a version_id, we are fetching a worker main script. We have a
  // DevtoolsAgentHost ready for the worker and we can add the devtools override
  // before instantiating the URLFactoryLoader.
  ServiceWorkerDevToolsAgentHost* agent_host =
      ServiceWorkerDevToolsManager::GetInstance()
          ->GetDevToolsAgentHostForNewInstallingWorker(context_wrapper,
                                                       *version_id);
  CHECK(agent_host);
  return WillCreateURLLoaderFactoryParams(
      agent_host, agent_host->devtools_worker_token(),
      ChildProcessHost::kInvalidUniqueID, context_wrapper->storage_partition());
}

std::optional<WillCreateURLLoaderFactoryParams>
WillCreateURLLoaderFactoryParams::ForSharedWorker(SharedWorkerHost* host) {
  auto* agent_host = SharedWorkerDevToolsAgentHost::GetFor(host);
  if (!agent_host) {
    return std::nullopt;
  }
  RenderProcessHost* rph = agent_host->GetProcessHost();
  CHECK(rph);
  return WillCreateURLLoaderFactoryParams(
      agent_host, agent_host->devtools_worker_token(), rph->GetDeprecatedID(),
      rph->GetStoragePartition());
}

WillCreateURLLoaderFactoryParams
WillCreateURLLoaderFactoryParams::ForWorkerMainScript(
    DevToolsAgentHostImpl* agent_host,
    const base::UnguessableToken& worker_token,
    RenderFrameHostImpl& ancestor_render_frame_host) {
  // Use the ancestor frame's interceptor to align with the interception
  // behavior in the renderer that reuses the same url loader factory from
  // the ancestor frame for the worker.
  return WillCreateURLLoaderFactoryParams::ForFrame(
      &ancestor_render_frame_host);
}

void OnAuctionWorkletNetworkRequestWillBeSent(
    FrameTreeNodeId frame_tree_node_id,
    const network::ResourceRequest& request,
    base::TimeTicks timestamp) {
  if (request.devtools_request_id->empty()) {
    return;
  }

  network::mojom::URLRequestDevToolsInfoPtr request_info =
      network::ExtractDevToolsInfo(request);

  GURL initiator_url;
  if (request.request_initiator.has_value()) {
    initiator_url = request.request_initiator->GetURL();
  }
  // if we cannot get the loader_id from the parent, use an empty string.
  std::string loader_id = "";
  if (frame_tree_node_id) {
    FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);

    if (ftn == nullptr) {
      return;
    }
    const std::optional<base::UnguessableToken>& devtools_navigation_token =
        ftn->current_frame_host()->GetDevToolsNavigationToken();

    if (devtools_navigation_token.has_value()) {
      loader_id = devtools_navigation_token->ToString();
    }

    DispatchToAgents(
        frame_tree_node_id, &protocol::NetworkHandler::RequestSent,
        /*request_id=*/request.devtools_request_id.value(),
        /*loader_id=*/loader_id, request.headers, *request_info,
        /*initiator_type=*/protocol::Network::Initiator::TypeEnum::Other,
        initiator_url,
        /*initiator_devtools_request_id=*/"", /*frame_token=*/std::nullopt,
        timestamp);
  }
}

void OnAuctionWorkletNetworkResponseReceived(
    FrameTreeNodeId frame_tree_node_id,
    const std::string& request_id,
    const std::string& loader_id,
    const GURL& request_url,
    const network::mojom::URLResponseHead& headers) {
  network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
      network::ExtractDevToolsInfo(headers);
  DispatchToAgents(frame_tree_node_id,
                   &protocol::NetworkHandler::ResponseReceived, request_id,
                   loader_id, request_url,
                   /*resource_type=*/protocol::Network::ResourceTypeEnum::Other,
                   *head_info, base::ToString(frame_tree_node_id));
}

void OnAuctionWorkletNetworkRequestComplete(
    FrameTreeNodeId frame_tree_node_id,
    const std::string& request_id,
    const network::URLLoaderCompletionStatus& status) {
  DispatchToAgents(frame_tree_node_id,
                   &protocol::NetworkHandler::LoadingComplete, request_id,
                   /*resource_type=*/protocol::Network::ResourceTypeEnum::Other,
                   status);
}

bool NeedInterestGroupAuctionEvents(FrameTreeNodeId frame_tree_node_id) {
  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (!ftn) {
    return false;
  }
  DevToolsAgentHostImpl* agent_host = RenderFrameDevToolsAgentHost::GetFor(ftn);
  if (!agent_host) {
    return false;
  }
  for (auto* storage : protocol::StorageHandler::ForAgentHost(agent_host)) {
    if (storage->interest_group_auction_tracking_enabled()) {
      return true;
    }
  }
  return false;
}

void OnInterestGroupAuctionEventOccurred(
    FrameTreeNodeId frame_tree_node_id,
    base::Time event_time,
    InterestGroupAuctionEventType type,
    const std::string& unique_auction_id,
    base::optional_ref<const std::string> parent_auction_id,
    const base::Value::Dict& auction_config) {
  DispatchToAgents(
      frame_tree_node_id,
      &protocol::StorageHandler::NotifyInterestGroupAuctionEventOccurred,
      event_time, type, unique_auction_id, parent_auction_id, auction_config);
}

void OnInterestGroupAuctionNetworkRequestCreated(
    FrameTreeNodeId frame_tree_node_id,
    InterestGroupAuctionFetchType type,
    const std::string& request_id,
    const std::vector<std::string>& devtools_auction_ids) {
  DispatchToAgents(frame_tree_node_id,
                   &protocol::StorageHandler::
                       NotifyInterestGroupAuctionNetworkRequestCreated,
                   type, request_id, devtools_auction_ids);
}

void OnNavigationRequestWillBeSent(
    const NavigationRequest& navigation_request) {
  // Note this intentionally deviates from the usual instrumentation signal
  // logic and dispatches to all agents upwards from the frame, to make sure
  // the security checks are properly applied even if no DevTools session is
  // established for the navigated frame itself. This is because the page
  // agent may navigate all of its subframes currently.
  for (RenderFrameHostImpl* rfh =
           navigation_request.frame_tree_node()->current_frame_host();
       rfh; rfh = rfh->GetParentOrOuterDocument()) {
    // Only check frames that qualify as DevTools targets, i.e. (local)? roots.
    if (!RenderFrameDevToolsAgentHost::ShouldCreateDevToolsForHost(rfh)) {
      continue;
    }
    auto* agent_host = static_cast<RenderFrameDevToolsAgentHost*>(
        RenderFrameDevToolsAgentHost::GetFor(rfh));
    if (!agent_host) {
      continue;
    }
    agent_host->OnNavigationRequestWillBeSent(navigation_request);
  }

  // We use CachedNavigationURLLoader for page activation (BFCache navigations
  // and Prerender activations) and don't actually send a network request, so we
  // don't report this request to DevTools.
  if (navigation_request.IsPageActivation()) {
    return;
  }

  // Make sure both back-ends yield the same timestamp.
  auto timestamp = base::TimeTicks::Now();
  DispatchToAgents(navigation_request.frame_tree_node(),
                   &protocol::NetworkHandler::NavigationRequestWillBeSent,
                   navigation_request, timestamp);
  TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
      "devtools.timeline", "ResourceWillSendRequest", TRACE_EVENT_SCOPE_PROCESS,
      timestamp, "data",
      inspector_will_send_navigation_request_event::Data(
          navigation_request.devtools_navigation_token()));
}

// Notify the provided agent host of a certificate error. Returns true if one of
// the host's handlers will handle the certificate error.
bool NotifyCertificateError(DevToolsAgentHost* host,
                            int cert_error,
                            const GURL& request_url,
                            const CertErrorCallback& callback) {
  DevToolsAgentHostImpl* host_impl = static_cast<DevToolsAgentHostImpl*>(host);
  for (auto* security_handler :
       protocol::SecurityHandler::ForAgentHost(host_impl)) {
    if (security_handler->NotifyCertificateError(cert_error, request_url,
                                                 callback)) {
      return true;
    }
  }
  return false;
}

bool HandleCertificateError(WebContents* web_contents,
                            int cert_error,
                            const GURL& request_url,
                            CertErrorCallback callback) {
  if (!DevToolsAgentHost::HasFor(web_contents)) {
    return false;
  }
  scoped_refptr<DevToolsAgentHost> agent_host =
      DevToolsAgentHost::GetOrCreateFor(web_contents).get();
  if (NotifyCertificateError(agent_host.get(), cert_error, request_url,
                             callback)) {
    // Only allow a single agent host to handle the error.
    callback.Reset();
  }

  for (auto* browser_agent_host : BrowserDevToolsAgentHost::Instances()) {
    if (NotifyCertificateError(browser_agent_host, cert_error, request_url,
                               callback)) {
      // Only allow a single agent host to handle the error.
      callback.Reset();
    }
  }
  return !callback;
}

void FencedFrameCreated(
    base::SafeRef<RenderFrameHostImpl> owner_render_frame_host,
    FencedFrame* fenced_frame) {
  auto* agent_host = static_cast<RenderFrameDevToolsAgentHost*>(
      RenderFrameDevToolsAgentHost::GetFor(
          owner_render_frame_host->frame_tree_node()));
  if (!agent_host) {
    return;
  }
  agent_host->DidCreateFencedFrame(fenced_frame);
}

void WillStartDragging(FrameTreeNode* main_frame_tree_node,
                       const DropData& drop_data,
                       const blink::mojom::DragDataPtr drag_data,
                       blink::DragOperationsMask drag_operations_mask,
                       bool* intercepted) {
  DCHECK(main_frame_tree_node->frame_tree().root() == main_frame_tree_node);
  DispatchToAgents(main_frame_tree_node, &protocol::InputHandler::StartDragging,
                   drop_data, *drag_data, drag_operations_mask, intercepted);
}

void DragEnded(FrameTreeNode& node) {
  DCHECK(node.frame_tree().root() == &node);
  DispatchToAgents(&node, &protocol::InputHandler::DragEnded);
}

namespace {
std::unique_ptr<protocol::Array<protocol::String>> BuildExclusionReasons(
    net::CookieInclusionStatus status) {
  auto exclusion_reasons =
      std::make_unique<protocol::Array<protocol::String>>();
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::
              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) {
    exclusion_reasons->push_back(protocol::Audits::CookieExclusionReasonEnum::
                                     ExcludeSameSiteUnspecifiedTreatedAsLax);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SAMESITE_NONE_INSECURE)) {
    exclusion_reasons->push_back(protocol::Audits::CookieExclusionReasonEnum::
                                     ExcludeSameSiteNoneInsecure);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_LAX)) {
    exclusion_reasons->push_back(
        protocol::Audits::CookieExclusionReasonEnum::ExcludeSameSiteLax);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SAMESITE_STRICT)) {
    exclusion_reasons->push_back(
        protocol::Audits::CookieExclusionReasonEnum::ExcludeSameSiteStrict);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_DOMAIN_NON_ASCII)) {
    exclusion_reasons->push_back(
        protocol::Audits::CookieExclusionReasonEnum::ExcludeDomainNonASCII);
  }
  if (status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::
              EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET)) {
    exclusion_reasons->push_back(
        protocol::Audits::CookieExclusionReasonEnum::
            ExcludeThirdPartyCookieBlockedInFirstPartySet);
  }
  if (status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_THIRD_PARTY_PHASEOUT)) {
    exclusion_reasons->push_back(
        protocol::Audits::CookieExclusionReasonEnum::ExcludeThirdPartyPhaseout);
  }

  if (base::FeatureList::IsEnabled(net::features::kEnablePortBoundCookies) &&
      status.HasExclusionReason(
          net::CookieInclusionStatus::ExclusionReason::EXCLUDE_PORT_MISMATCH)) {
    exclusion_reasons->push_back(
        protocol::Audits::CookieExclusionReasonEnum::ExcludePortMismatch);
  }

  if (base::FeatureList::IsEnabled(net::features::kEnableSchemeBoundCookies) &&
      status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
                                    EXCLUDE_SCHEME_MISMATCH)) {
    exclusion_reasons->push_back(
        protocol::Audits::CookieExclusionReasonEnum::ExcludeSchemeMismatch);
  }

  return exclusion_reasons;
}

std::unique_ptr<protocol::Array<protocol::String>> BuildWarningReasons(
    net::CookieInclusionStatus status) {
  auto warning_reasons = std::make_unique<protocol::Array<protocol::String>>();
  if (status.HasWarningReason(net::CookieInclusionStatus::WarningReason::
                                  WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnAttributeValueExceedsMaxSize);
  }
  if (status.HasWarningReason(
          net::CookieInclusionStatus::WarningReason::
              WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnSameSiteUnspecifiedCrossSiteContext);
  }
  if (status.HasWarningReason(net::CookieInclusionStatus::WarningReason::
                                  WARN_SAMESITE_NONE_INSECURE)) {
    warning_reasons->push_back(
        protocol::Audits::CookieWarningReasonEnum::WarnSameSiteNoneInsecure);
  }
  if (status.HasWarningReason(net::CookieInclusionStatus::WarningReason::
                                  WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnSameSiteUnspecifiedLaxAllowUnsafe);
  }

  // There can only be one of the following warnings.
  if (status.HasWarningReason(net::CookieInclusionStatus::WarningReason::
                                  WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnSameSiteStrictLaxDowngradeStrict);
  } else if (status.HasWarningReason(
                 net::CookieInclusionStatus::WarningReason::
                     WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnSameSiteStrictCrossDowngradeStrict);
  } else if (status.HasWarningReason(
                 net::CookieInclusionStatus::WarningReason::
                     WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnSameSiteStrictCrossDowngradeLax);
  } else if (status.HasWarningReason(
                 net::CookieInclusionStatus::WarningReason::
                     WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnSameSiteLaxCrossDowngradeStrict);
  } else if (status.HasWarningReason(
                 net::CookieInclusionStatus::WarningReason::
                     WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE)) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnSameSiteLaxCrossDowngradeLax);
  }

  if (status.HasWarningReason(
          net::CookieInclusionStatus::WarningReason::WARN_DOMAIN_NON_ASCII)) {
    warning_reasons->push_back(
        protocol::Audits::CookieWarningReasonEnum::WarnDomainNonASCII);
  }

  if (status.HasWarningReason(net::CookieInclusionStatus::WarningReason::
                                  WARN_THIRD_PARTY_PHASEOUT)) {
    warning_reasons->push_back(
        protocol::Audits::CookieWarningReasonEnum::WarnThirdPartyPhaseout);
  }

  if (status.exemption_reason() ==
      net::CookieInclusionStatus::ExemptionReason::k3PCDMetadata) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnDeprecationTrialMetadata);
  } else if (status.exemption_reason() ==
             net::CookieInclusionStatus::ExemptionReason::k3PCDHeuristics) {
    warning_reasons->push_back(protocol::Audits::CookieWarningReasonEnum::
                                   WarnThirdPartyCookieHeuristic);
  }

  // This warning only affects cookies when the corresponding feature is
  // enabled, therefore we should only create an issue for it then.
  if (base::FeatureList::IsEnabled(
          net::features::kCookieSameSiteConsidersRedirectChain) &&
      status.HasWarningReason(
          net::CookieInclusionStatus::WarningReason::
              WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION)) {
    warning_reasons->push_back(
        protocol::Audits::CookieWarningReasonEnum::
            WarnCrossSiteRedirectDowngradeChangesInclusion);
  }

  return warning_reasons;
}

protocol::String BuildCookieOperation(blink::mojom::CookieOperation operation) {
  switch (operation) {
    case blink::mojom::CookieOperation::kReadCookie:
      return protocol::Audits::CookieOperationEnum::ReadCookie;
    case blink::mojom::CookieOperation::kSetCookie:
      return protocol::Audits::CookieOperationEnum::SetCookie;
  }
}

std::unique_ptr<protocol::Audits::InspectorIssue>
BuildCookieDeprecationMetadataIssue(
    const blink::mojom::CookieDeprecationMetadataIssueDetailsPtr&
        issue_details) {
  auto metadata_issue_details =
      protocol::Audits::CookieDeprecationMetadataIssueDetails::Create()
          .SetAllowedSites(std::make_unique<protocol::Array<protocol::String>>(
              issue_details->allowed_sites))
          .SetOptOutPercentage(issue_details->opt_out_percentage)
          .SetIsOptOutTopLevel(issue_details->is_opt_out_top_level)
          .SetOperation(BuildCookieOperation(issue_details->operation))
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetCookieDeprecationMetadataIssueDetails(
              std::move(metadata_issue_details))
          .Build();

  auto issue = protocol::Audits::InspectorIssue::Create()
                   .SetCode(protocol::Audits::InspectorIssueCodeEnum::
                                CookieDeprecationMetadataIssue)
                   .SetDetails(std::move(protocol_issue_details))
                   .Build();

  return issue;
}

std::unique_ptr<protocol::Audits::CookieIssueInsight> BuildCookieIssueInsight(
    std::string_view cookie_domain,
    const net::CookieInclusionStatus& status) {
  std::optional<CookieIssueInsight> insight =
      CookieInsightListHandler::GetInstance().GetInsight(cookie_domain, status);
  if (!insight.has_value()) {
    return nullptr;
  }

  switch (insight->type) {
    case InsightType::kGitHubResource:
      return protocol::Audits::CookieIssueInsight::Create()
          .SetType(protocol::Audits::InsightTypeEnum::GitHubResource)
          .SetTableEntryUrl(insight->domain_info.entry_url)
          .Build();
    case InsightType::kGracePeriod:
      return protocol::Audits::CookieIssueInsight::Create()
          .SetType(protocol::Audits::InsightTypeEnum::GracePeriod)
          .Build();
    case InsightType::kHeuristics:
      return protocol::Audits::CookieIssueInsight::Create()
          .SetType(protocol::Audits::InsightTypeEnum::Heuristics)
          .Build();
    default:
      NOTREACHED();
  }
}

}  // namespace

void ReportCookieIssue(
    RenderFrameHostImpl* render_frame_host_impl,
    const network::mojom::CookieOrLineWithAccessResultPtr& excluded_cookie,
    const GURL& url,
    const net::SiteForCookies& site_for_cookies,
    blink::mojom::CookieOperation operation,
    const std::optional<std::string>& devtools_request_id,
    const std::optional<std::string>& devtools_issue_id) {
  auto exclusion_reasons =
      BuildExclusionReasons(excluded_cookie->access_result.status);
  auto warning_reasons =
      BuildWarningReasons(excluded_cookie->access_result.status);
  if (exclusion_reasons->empty() && warning_reasons->empty()) {
    // If we don't report any reason, there is no point in informing DevTools.
    return;
  }

  std::unique_ptr<protocol::Audits::AffectedRequest> affected_request;
  if (devtools_request_id) {
    // We can report the url here, because if devtools_request_id is set, the
    // url is the url of the request.
    affected_request = protocol::Audits::AffectedRequest::Create()
                           .SetRequestId(*devtools_request_id)
                           .SetUrl(url.spec())
                           .Build();
  }

  auto cookie_issue_details =
      protocol::Audits::CookieIssueDetails::Create()
          .SetCookieExclusionReasons(std::move(exclusion_reasons))
          .SetCookieWarningReasons(std::move(warning_reasons))
          .SetOperation(BuildCookieOperation(operation))
          .SetCookieUrl(url.spec())
          .SetRequest(std::move(affected_request))
          .Build();

  if (excluded_cookie->cookie_or_line->is_cookie()) {
    const auto& cookie = excluded_cookie->cookie_or_line->get_cookie();
    auto affected_cookie = protocol::Audits::AffectedCookie::Create()
                               .SetName(cookie.Name())
                               .SetPath(cookie.Path())
                               .SetDomain(cookie.Domain())
                               .Build();
    cookie_issue_details->SetCookie(std::move(affected_cookie));

    cookie_issue_details->SetInsight(BuildCookieIssueInsight(
        cookie.DomainWithoutDot(), excluded_cookie->access_result.status));
  } else {
    CHECK(excluded_cookie->cookie_or_line->is_cookie_string());
    cookie_issue_details->SetRawCookieLine(
        excluded_cookie->cookie_or_line->get_cookie_string());
  }

  if (!site_for_cookies.IsNull()) {
    cookie_issue_details->SetSiteForCookies(
        site_for_cookies.RepresentativeUrl().spec());
  }

  auto details = protocol::Audits::InspectorIssueDetails::Create()
                     .SetCookieIssueDetails(std::move(cookie_issue_details))
                     .Build();

  auto issue =
      protocol::Audits::InspectorIssue::Create()
          .SetCode(protocol::Audits::InspectorIssueCodeEnum::CookieIssue)
          .SetDetails(std::move(details))
          .Build();
  if (devtools_issue_id.has_value()) {
    issue->SetIssueId(devtools_issue_id.value());
  }

  ReportBrowserInitiatedIssue(render_frame_host_impl, std::move(issue));
}

namespace {

const protocol::Audits::InspectorIssue& AddIssueToIssueStorage(
    RenderFrameHost* rfh,
    std::unique_ptr<protocol::Audits::InspectorIssue> issue) {
  // We only utilize a central storage on the page. Each issue is still
  // associated with the originating |RenderFrameHost| though.
  DevToolsIssueStorage* issue_storage =
      DevToolsIssueStorage::GetOrCreateForPage(
          rfh->GetOutermostMainFrame()->GetPage());

  return issue_storage->AddInspectorIssue(rfh, std::move(issue));
}

}  // namespace

namespace {

std::unique_ptr<protocol::Audits::InspectorIssue>
BuildUserReidentificationIssue(
    const blink::mojom::UserReidentificationIssueDetailsPtr& issue_details) {
  auto affected_request = issue_details->request.is_null()
                              ? nullptr
                              : protocol::Audits::AffectedRequest::Create()
                                    .SetUrl(issue_details->request->url)
                                    .Build();
  auto source_code_location =
      issue_details->sourceCodeLocation.is_null()
          ? nullptr
          : protocol::Audits::SourceCodeLocation::Create()
                .SetUrl(issue_details->sourceCodeLocation->url.value())
                .SetLineNumber(issue_details->sourceCodeLocation->line)
                .SetColumnNumber(issue_details->sourceCodeLocation->column)
                .Build();
  std::string issue_type;
  switch (issue_details->type) {
    case blink::mojom::UserReidentificationIssueType::kBlockedFrameNavigation:
      issue_type = protocol::Audits::UserReidentificationIssueTypeEnum::
          BlockedFrameNavigation;
      break;
    case blink::mojom::UserReidentificationIssueType::kBlockedSubresource:
      issue_type = protocol::Audits::UserReidentificationIssueTypeEnum::
          BlockedSubresource;
      break;
    case blink::mojom::UserReidentificationIssueType::kNoisedCanvasReadback:
      issue_type = protocol::Audits::UserReidentificationIssueTypeEnum::
          NoisedCanvasReadback;
      break;
    default:
      NOTREACHED();
  }
  auto reidentification_issue_details =
      protocol::Audits::UserReidentificationIssueDetails::Create()
          .SetType(issue_type)
          .SetRequest(std::move(affected_request))
          .Build();

  auto protocol_issue_details =
      protocol::Audits::InspectorIssueDetails::Create()
          .SetUserReidentificationIssueDetails(
              std::move(reidentification_issue_details))
          .Build();

  auto issue = protocol::Audits::InspectorIssue::Create()
                   .SetCode(protocol::Audits::InspectorIssueCodeEnum::
                                UserReidentificationIssue)
                   .SetDetails(std::move(protocol_issue_details))
                   .Build();

  return issue;
}

}  // namespace

void ReportBrowserInitiatedIssue(
    RenderFrameHostImpl* frame,
    std::unique_ptr<protocol::Audits::InspectorIssue> issue) {
  FrameTreeNode* ftn = frame->frame_tree_node();
  if (!ftn) {
    return;
  }

  const auto& issue_ptr = AddIssueToIssueStorage(frame, std::move(issue));
  DispatchToAgents(ftn, &protocol::AuditsHandler::OnIssueAdded, issue_ptr);
}

void BuildAndReportBrowserInitiatedIssue(
    RenderFrameHostImpl* frame,
    blink::mojom::InspectorIssueInfoPtr info) {
  std::unique_ptr<protocol::Audits::InspectorIssue> issue;
  if (info->code == blink::mojom::InspectorIssueCode::kHeavyAdIssue) {
    issue = BuildHeavyAdIssue(info->details->heavy_ad_issue_details);
  } else if (info->code ==
             blink::mojom::InspectorIssueCode::kFederatedAuthRequestIssue) {
    issue = BuildFederatedAuthRequestIssue(
        info->details->federated_auth_request_details);
  } else if (info->code ==
             blink::mojom::InspectorIssueCode::kDeprecationIssue) {
    issue = BuildDeprecationIssue(info->details->deprecation_issue_details);
  } else if (info->code ==
             blink::mojom::InspectorIssueCode::kBounceTrackingIssue) {
    issue =
        BuildBounceTrackingIssue(info->details->bounce_tracking_issue_details);
  } else if (info->code ==
             blink::mojom::InspectorIssueCode::kPartitioningBlobURLIssue) {
    issue = BuildPartitioningBlobURLIssue(
        info->details->partitioning_blob_url_issue_details);
  } else if (info->code == blink::mojom::InspectorIssueCode::
                               kCookieDeprecationMetadataIssue) {
    issue = BuildCookieDeprecationMetadataIssue(
        info->details->cookie_deprecation_metadata_issue_details);
  } else if (info->code == blink::mojom::InspectorIssueCode::
                               kFederatedAuthUserInfoRequestIssue) {
    issue = BuildFederatedAuthUserInfoRequestIssue(
        info->details->federated_auth_user_info_request_details);
  } else if (info->code ==
             blink::mojom::InspectorIssueCode::kAttributionReportingIssue) {
    issue = BuildAttributionReportingIssue(
        info->details->attribution_reporting_issue_details);
  } else if (info->code ==
             blink::mojom::InspectorIssueCode::kUserReidentificationIssue) {
    issue = BuildUserReidentificationIssue(
        info->details->user_reidentification_issue_details);
  } else {
    NOTREACHED() << "Unsupported type of browser-initiated issue";
  }
  ReportBrowserInitiatedIssue(frame, std::move(issue));
}

void OnWebTransportHandshakeFailed(
    RenderFrameHostImpl* frame,
    const GURL& url,
    const std::optional<net::WebTransportError>& error) {
  FrameTreeNode* ftn = frame->frame_tree_node();
  if (!ftn) {
    return;
  }
  std::string text = base::StringPrintf(
      "Failed to establish a connection to %s", url.spec().c_str());
  if (error) {
    text += ": ";
    text += net::WebTransportErrorToString(*error);
  }
  text += ".";
  auto entry =
      protocol::Log::LogEntry::Create()
          .SetSource(protocol::Log::LogEntry::SourceEnum::Network)
          .SetLevel(protocol::Log::LogEntry::LevelEnum::Error)
          .SetText(text)
          .SetTimestamp(base::Time::Now().InMillisecondsFSinceUnixEpoch())
          .Build();
  DispatchToAgents(ftn, &protocol::LogHandler::EntryAdded, entry.get());
}

void OnServiceWorkerMainScriptFetchingFailed(
    const GlobalRenderFrameHostId& requesting_frame_id,
    const ServiceWorkerContextWrapper* context_wrapper,
    int64_t version_id,
    const std::string& error,
    const network::URLLoaderCompletionStatus& status,
    const network::mojom::URLResponseHead* response_head,
    const GURL& url) {
  DCHECK(!error.empty());
  DCHECK_NE(net::OK, status.error_code);

  // If we have a requesting_frame_id, we should have a frame and a frame tree
  // node. However since the lifetime of these objects can be complex, we check
  // at each step that we indeed can go reach all the way to the FrameTreeNode.
  if (!requesting_frame_id) {
    return;
  }

  RenderFrameHostImpl* requesting_frame =
      RenderFrameHostImpl::FromID(requesting_frame_id);
  if (!requesting_frame) {
    return;
  }

  FrameTreeNode* ftn = requesting_frame->frame_tree_node();
  if (!ftn) {
    return;
  }

  auto entry =
      protocol::Log::LogEntry::Create()
          .SetSource(protocol::Log::LogEntry::SourceEnum::Network)
          .SetLevel(protocol::Log::LogEntry::LevelEnum::Error)
          .SetText(error)
          .SetTimestamp(base::Time::Now().InMillisecondsFSinceUnixEpoch())
          .Build();
  DispatchToAgents(ftn, &protocol::LogHandler::EntryAdded, entry.get());

  ServiceWorkerDevToolsAgentHost* agent_host =
      ServiceWorkerDevToolsManager::GetInstance()
          ->GetDevToolsAgentHostForNewInstallingWorker(context_wrapper,
                                                       version_id);

  if (response_head) {
    DCHECK(agent_host);
    network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
        network::ExtractDevToolsInfo(*response_head);
    auto worker_token = agent_host->devtools_worker_token().ToString();
    for (auto* network_handler :
         protocol::NetworkHandler::ForAgentHost(agent_host)) {
      network_handler->ResponseReceived(
          worker_token, worker_token, url,
          protocol::Network::ResourceTypeEnum::Other, *head_info,
          requesting_frame->devtools_frame_token().ToString());
      network_handler->frontend()->LoadingFinished(
          worker_token,
          status.completion_time.ToInternalValue() /
              static_cast<double>(base::Time::kMicrosecondsPerSecond),
          status.encoded_data_length);
    }
  } else if (agent_host) {
    for (auto* network_handler :
         protocol::NetworkHandler::ForAgentHost(agent_host)) {
      network_handler->LoadingComplete(
          agent_host->devtools_worker_token().ToString(),
          protocol::Network::ResourceTypeEnum::Other, status);
    }
  }
}

namespace {

// Only assign request id if there's an enabled agent host.
void MaybeAssignResourceRequestId(DevToolsAgentHostImpl* host,
                                  const std::string& id,
                                  network::ResourceRequest& request) {
  DCHECK(!request.devtools_request_id.has_value());
  for (auto* network_handler : protocol::NetworkHandler::ForAgentHost(host)) {
    if (network_handler->enabled()) {
      request.devtools_request_id = id;
      return;
    }
  }
}

}  // namespace

void MaybeAssignResourceRequestId(FrameTreeNode* ftn,
                                  const std::string& id,
                                  network::ResourceRequest& request) {
  if (auto* host = RenderFrameDevToolsAgentHost::GetFor(ftn)) {
    MaybeAssignResourceRequestId(host, id, request);
  }
}

void MaybeAssignResourceRequestId(FrameTreeNodeId frame_tree_node_id,
                                  const std::string& id,
                                  network::ResourceRequest& request) {
  auto* frame_tree_node = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (frame_tree_node) {
    MaybeAssignResourceRequestId(frame_tree_node, id, request);
  }
}

void OnServiceWorkerMainScriptRequestWillBeSent(
    const GlobalRenderFrameHostId& requesting_frame_id,
    const ServiceWorkerContextWrapper* context_wrapper,
    int64_t version_id,
    network::ResourceRequest& request) {
  // Currently, `requesting_frame_id` is invalid when payment apps and
  // extensions register a service worker. See the callers of
  // ServiceWorkerContextWrapper::RegisterServiceWorker().
  if (!requesting_frame_id) {
    return;
  }

  RenderFrameHostImpl* requesting_frame =
      RenderFrameHostImpl::FromID(requesting_frame_id);
  if (!requesting_frame) {
    return;
  }

  auto timestamp = base::TimeTicks::Now();
  network::mojom::URLRequestDevToolsInfoPtr request_info =
      network::ExtractDevToolsInfo(request);

  ServiceWorkerDevToolsAgentHost* agent_host =
      ServiceWorkerDevToolsManager::GetInstance()
          ->GetDevToolsAgentHostForNewInstallingWorker(context_wrapper,
                                                       version_id);
  DCHECK(agent_host);
  const std::string request_id = agent_host->devtools_worker_token().ToString();
  MaybeAssignResourceRequestId(agent_host, request_id, request);
  for (auto* network_handler :
       protocol::NetworkHandler::ForAgentHost(agent_host)) {
    network_handler->RequestSent(request_id,
                                 /*loader_id=*/"", request.headers,
                                 *request_info,
                                 protocol::Network::Initiator::TypeEnum::Other,
                                 requesting_frame->GetLastCommittedURL(),
                                 /*initiator_devtools_request_id=*/"",
                                 /*frame_token=*/std::nullopt, timestamp);
  }
}

void OnWorkerMainScriptLoadingFailed(
    const GURL& url,
    const base::UnguessableToken& worker_token,
    FrameTreeNode* ftn,
    RenderFrameHostImpl* ancestor_rfh,
    const network::URLLoaderCompletionStatus& status) {
  DCHECK(ftn);

  std::string id = worker_token.ToString();

  if (status.blocked_by_response_reason) {
    ReportBlockedByResponseIssue(url, id, ftn, ancestor_rfh, status);
  }

  DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id,
                   protocol::Network::ResourceTypeEnum::Other, status);
}

void OnWorkerMainScriptRequestWillBeSent(
    RenderFrameHostImpl& ancestor_frame_host,
    const base::UnguessableToken& worker_token,
    network::ResourceRequest& request) {
  FrameTreeNode* ftn = ancestor_frame_host.frame_tree_node();

  auto timestamp = base::TimeTicks::Now();
  network::mojom::URLRequestDevToolsInfoPtr request_info =
      network::ExtractDevToolsInfo(request);

  auto* owner_host = RenderFrameDevToolsAgentHost::GetFor(ftn);
  if (!owner_host) {
    return;
  }
  MaybeAssignResourceRequestId(owner_host, worker_token.ToString(), request);

  // Note: we apply overrides from the owner frame to match the behavior in the
  // renderer.
  bool disable_cache = false;
  ApplyNetworkRequestOverrides(owner_host, &request.headers, &disable_cache,
                               nullptr, &request.skip_service_worker,
                               &request.devtools_accepted_stream_types, nullptr,
                               nullptr, nullptr);
  if (disable_cache) {
    request.load_flags &=
        ~(net::LOAD_VALIDATE_CACHE | net::LOAD_SKIP_CACHE_VALIDATION |
          net::LOAD_ONLY_FROM_CACHE | net::LOAD_DISABLE_CACHE);
    request.load_flags |= net::LOAD_BYPASS_CACHE;
  }

  DispatchToAgents(
      ftn, &protocol::NetworkHandler::RequestSent, worker_token.ToString(),
      /*loader_id=*/"", request.headers, *request_info,
      protocol::Network::Initiator::TypeEnum::Other, ftn->current_url(),
      /*initiator_devtools_request_id*/ "",
      ancestor_frame_host.devtools_frame_token(), timestamp);
}

void LogWorkletMessage(RenderFrameHostImpl& frame_host,
                       blink::mojom::ConsoleMessageLevel log_level,
                       const std::string& message) {
  FrameTreeNode* ftn = frame_host.frame_tree_node();
  if (!ftn) {
    return;
  }

  std::string log_level_string;
  switch (log_level) {
    case blink::mojom::ConsoleMessageLevel::kVerbose:
      log_level_string = protocol::Log::LogEntry::LevelEnum::Verbose;
      break;
    case blink::mojom::ConsoleMessageLevel::kInfo:
      log_level_string = protocol::Log::LogEntry::LevelEnum::Info;
      break;
    case blink::mojom::ConsoleMessageLevel::kWarning:
      log_level_string = protocol::Log::LogEntry::LevelEnum::Warning;
      break;
    case blink::mojom::ConsoleMessageLevel::kError:
      log_level_string = protocol::Log::LogEntry::LevelEnum::Error;
      break;
  }

  DCHECK(!log_level_string.empty());

  auto entry =
      protocol::Log::LogEntry::Create()
          .SetSource(protocol::Log::LogEntry::SourceEnum::Other)
          .SetLevel(log_level_string)
          .SetText(message)
          .SetTimestamp(base::Time::Now().InMillisecondsFSinceUnixEpoch())
          .Build();
  DispatchToAgents(ftn, &protocol::LogHandler::EntryAdded, entry.get());

  // Manually trigger RenderFrameHostImpl::DidAddMessageToConsole, so that the
  // observer behavior aligns more with the observer behavior for the regular
  // devtools logging path from the renderer.
  frame_host.DidAddMessageToConsole(log_level, base::UTF8ToUTF16(message),
                                    /*line_no=*/0, /*source_id=*/{},
                                    /*untrusted_stack_trace=*/{});
}

void ApplyNetworkContextParamsOverrides(
    BrowserContext* browser_context,
    network::mojom::NetworkContextParams* context_params) {
  for (auto* agent_host : BrowserDevToolsAgentHost::Instances()) {
    for (auto* target_handler :
         protocol::TargetHandler::ForAgentHost(agent_host)) {
      target_handler->ApplyNetworkContextParamsOverrides(browser_context,
                                                         context_params);
    }
  }
}

protocol::Audits::GenericIssueErrorType GenericIssueErrorTypeToProtocol(
    blink::mojom::GenericIssueErrorType error_type) {
  switch (error_type) {
    case blink::mojom::GenericIssueErrorType::kFormLabelForNameError:
      return protocol::Audits::GenericIssueErrorTypeEnum::FormLabelForNameError;
    case blink::mojom::GenericIssueErrorType::kFormDuplicateIdForInputError:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormDuplicateIdForInputError;
    case blink::mojom::GenericIssueErrorType::kFormInputWithNoLabelError:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormInputWithNoLabelError;
    case blink::mojom::GenericIssueErrorType::
        kFormAutocompleteAttributeEmptyError:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormAutocompleteAttributeEmptyError;
    case blink::mojom::GenericIssueErrorType::
        kFormEmptyIdAndNameAttributesForInputError:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormEmptyIdAndNameAttributesForInputError;
    case blink::mojom::GenericIssueErrorType::
        kFormAriaLabelledByToNonExistingId:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormAriaLabelledByToNonExistingId;
    case blink::mojom::GenericIssueErrorType::
        kFormInputAssignedAutocompleteValueToIdOrNameAttributeError:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormInputAssignedAutocompleteValueToIdOrNameAttributeError;
    case blink::mojom::GenericIssueErrorType::
        kFormLabelHasNeitherForNorNestedInput:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormLabelHasNeitherForNorNestedInput;
    case blink::mojom::GenericIssueErrorType::
        kFormLabelForMatchesNonExistingIdError:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormLabelForMatchesNonExistingIdError;
    case blink::mojom::GenericIssueErrorType::
        kFormInputHasWrongButWellIntendedAutocompleteValueError:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          FormInputHasWrongButWellIntendedAutocompleteValueError;
    case blink::mojom::GenericIssueErrorType::kResponseWasBlockedByORB:
      return protocol::Audits::GenericIssueErrorTypeEnum::
          ResponseWasBlockedByORB;
  }
}

void UpdateDeviceRequestPrompt(RenderFrameHost* render_frame_host,
                               DevtoolsDeviceRequestPromptInfo* prompt_info) {
  FrameTreeNode* ftn = FrameTreeNode::From(render_frame_host);
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn,
                   &protocol::DeviceAccessHandler::UpdateDeviceRequestPrompt,
                   prompt_info);
}

void CleanUpDeviceRequestPrompt(RenderFrameHost* render_frame_host,
                                DevtoolsDeviceRequestPromptInfo* prompt_info) {
  FrameTreeNode* ftn = FrameTreeNode::From(render_frame_host);
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn,
                   &protocol::DeviceAccessHandler::CleanUpDeviceRequestPrompt,
                   prompt_info);
}

void WillSendFedCmRequest(RenderFrameHost& render_frame_host,
                          bool* intercept,
                          bool* disable_delay) {
  FrameTreeNode* ftn = FrameTreeNode::From(&render_frame_host);
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn, &protocol::FedCmHandler::WillSendRequest, intercept,
                   disable_delay);
}

void WillShowFedCmDialog(RenderFrameHost& render_frame_host, bool* intercept) {
  FrameTreeNode* ftn = FrameTreeNode::From(&render_frame_host);
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn, &protocol::FedCmHandler::WillShowDialog, intercept);
}

void DidShowFedCmDialog(RenderFrameHost& render_frame_host) {
  FrameTreeNode* ftn = FrameTreeNode::From(&render_frame_host);
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn, &protocol::FedCmHandler::DidShowDialog);
}

void DidCloseFedCmDialog(RenderFrameHost& render_frame_host) {
  FrameTreeNode* ftn = FrameTreeNode::From(&render_frame_host);
  if (!ftn) {
    return;
  }
  DispatchToAgents(ftn, &protocol::FedCmHandler::DidCloseDialog);
}

void WillSendFedCmNetworkRequest(
    FrameTreeNodeId frame_tree_node_id,
    const network::ResourceRequest& request,
    const std::optional<std::string>& request_body) {
  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (!ftn) {
    return;
  }

  // Get the DevTools navigation token from the current frame host
  const std::optional<base::UnguessableToken>& loader_id =
      ftn->current_frame_host()->GetDevToolsNavigationToken();

  if (!loader_id.has_value()) {
    return;
  }

  std::optional<base::UnguessableToken> frame_token =
      ftn->current_frame_host()->devtools_frame_token();

  GURL initiator_url;
  if (request.request_initiator.has_value()) {
    initiator_url = request.request_initiator->GetURL();
  }

  DispatchToAgents(frame_tree_node_id,
                   &protocol::NetworkHandler::FedCmRequestWillBeSent,
                   request.devtools_request_id.value(),
                   loader_id.value().ToString(), request, request_body,
                   initiator_url, frame_token, base::TimeTicks::Now());
}

void DidReceiveFedCmNetworkResponse(
    FrameTreeNodeId frame_tree_node_id,
    const std::string& devtools_request_id,
    const GURL& url,
    const network::mojom::URLResponseHead* response_head,
    const std::string& response_body,
    const network::URLLoaderCompletionStatus& status) {
  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (!ftn) {
    return;
  }

  // Get the DevTools navigation token from the current frame host
  const std::optional<base::UnguessableToken>& loader_id =
      ftn->current_frame_host()->GetDevToolsNavigationToken();

  if (!loader_id.has_value()) {
    return;
  }

  if (response_head) {
    network::mojom::URLResponseHeadDevToolsInfoPtr head_info =
        network::ExtractDevToolsInfo(*response_head);

    std::optional<base::UnguessableToken> frame_token =
        ftn->current_frame_host()->devtools_frame_token();

    DispatchToAgents(frame_tree_node_id,
                     &protocol::NetworkHandler::ResponseReceived,
                     devtools_request_id, loader_id.value().ToString(), url,
                     protocol::Network::ResourceTypeEnum::FedCM, *head_info,
                     frame_token.value().ToString());
  }

  if (status.error_code == net::OK) {
    DispatchToAgents(frame_tree_node_id,
                     &protocol::NetworkHandler::BodyDataReceived,
                     devtools_request_id, response_body,
                     /*is_base64_encoded=*/false);
  }

  DispatchToAgents(
      frame_tree_node_id, &protocol::NetworkHandler::LoadingComplete,
      devtools_request_id, protocol::Network::ResourceTypeEnum::FedCM, status);
}

void OnFencedFrameReportRequestSent(
    FrameTreeNodeId initiator_frame_tree_node_id,
    const std::string& devtools_request_id,
    network::ResourceRequest& request,
    const std::string& event_data) {
  DispatchToAgents(initiator_frame_tree_node_id,
                   &protocol::NetworkHandler::FencedFrameReportRequestSent,
                   /*request_id=*/devtools_request_id, request, event_data,
                   base::TimeTicks::Now());
}

void OnFencedFrameReportResponseReceived(
    FrameTreeNodeId initiator_frame_tree_node_id,
    const std::string& devtools_request_id,
    const GURL& final_url,
    scoped_refptr<net::HttpResponseHeaders> headers) {
  network::mojom::URLResponseHeadDevToolsInfoPtr response_info =
      network::mojom::URLResponseHeadDevToolsInfo::New();
  response_info->headers = headers;

  DispatchToAgents(initiator_frame_tree_node_id,
                   &protocol::NetworkHandler::ResponseReceived,
                   /*request_id=*/devtools_request_id,
                   /*loader_id=*/devtools_request_id, final_url,
                   protocol::Network::ResourceTypeEnum::Other, *response_info,
                   /*frame_id=*/std::nullopt);

  DispatchToAgents(initiator_frame_tree_node_id,
                   &protocol::NetworkHandler::LoadingComplete,
                   /*request_id=*/devtools_request_id,
                   protocol::Network::Initiator::TypeEnum::Other,
                   network::URLLoaderCompletionStatus(net::OK));
}

void DidChangeFrameLoadingState(FrameTreeNode& ftn) {
  DispatchToAgents(&ftn, &protocol::PageHandler::DidChangeFrameLoadingState,
                   ftn);
}

void DidStartNavigating(FrameTreeNode& ftn,
                        const GURL& url,
                        const base::UnguessableToken& loader_id,
                        const blink::mojom::NavigationType& navigation_type) {
  DispatchToAgents(&ftn, &protocol::PageHandler::DidStartNavigating, ftn, url,
                   loader_id, navigation_type);
}

}  // namespace devtools_instrumentation

}  // namespace content
