// Copyright 2019 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/client_hints/client_hints.h"

#include <algorithm>
#include <optional>
#include <string>

#include "base/check_is_test.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/preloading/prerender/prerender_host.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/navigator_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_hints_controller_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "net/base/url_util.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/structured_headers.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_quality_estimator_params.h"
#include "services/network/public/cpp/client_hints.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/network_quality_tracker.h"
#include "services/network/public/cpp/permissions_policy/client_hints_permissions_policy_mapping.h"
#include "services/network/public/cpp/permissions_policy/permissions_policy.h"
#include "services/network/public/cpp/permissions_policy/permissions_policy_declaration.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
#include "third_party/blink/public/common/device_memory/approximated_device_memory.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "url/origin.h"
#include "url/url_constants.h"

namespace content {

namespace {
using ::network::mojom::WebClientHintsType;

uint8_t randomization_salt = 0;

constexpr size_t kMaxRandomNumbers = 21;

// Returns the randomization salt (weak and insecure) that should be used when
// adding noise to the network quality metrics. This is known only to the
// device, and is generated only once. This makes it possible to add the same
// amount of noise for a given origin.
uint8_t RandomizationSalt() {
  if (randomization_salt == 0)
    randomization_salt = base::RandInt(1, kMaxRandomNumbers);
  DCHECK_LE(1, randomization_salt);
  DCHECK_GE(kMaxRandomNumbers, randomization_salt);
  return randomization_salt;
}

double GetRandomMultiplier(const std::string& host) {
  // The random number should be a function of the hostname to reduce
  // cross-origin fingerprinting. The random number should also be a function
  // of randomized salt which is known only to the device. This prevents
  // origin from removing noise from the estimates.
  unsigned hash = std::hash<std::string>{}(host) + RandomizationSalt();
  double random_multiplier =
      0.9 + static_cast<double>((hash % kMaxRandomNumbers)) * 0.01;
  DCHECK_LE(0.90, random_multiplier);
  DCHECK_GE(1.10, random_multiplier);
  return random_multiplier;
}

unsigned long RoundRtt(const std::string& host,
                       const std::optional<base::TimeDelta>& rtt) {
  if (!rtt.has_value()) {
    // RTT is unavailable. So, return the fastest value.
    return 0;
  }

  // Limit the maximum reported value and the granularity to reduce
  // fingerprinting.
  constexpr base::TimeDelta kMaxRtt = base::Seconds(3);
  constexpr base::TimeDelta kGranularity = base::Milliseconds(50);

  const base::TimeDelta modified_rtt =
      std::min(rtt.value() * GetRandomMultiplier(host), kMaxRtt);
  DCHECK_GE(modified_rtt, base::TimeDelta());
  return modified_rtt.RoundToMultiple(kGranularity).InMilliseconds();
}

double RoundKbpsToMbps(const std::string& host,
                       const std::optional<int32_t>& downlink_kbps) {
  // Limit the size of the buckets and the maximum reported value to reduce
  // fingerprinting.
  static const size_t kGranularityKbps = 50;
  static const double kMaxDownlinkKbps = 10.0 * 1000;

  // If downlink is unavailable, return the fastest value.
  double randomized_downlink_kbps = downlink_kbps.value_or(kMaxDownlinkKbps);
  randomized_downlink_kbps *= GetRandomMultiplier(host);

  randomized_downlink_kbps =
      std::min(randomized_downlink_kbps, kMaxDownlinkKbps);

  DCHECK_LE(0, randomized_downlink_kbps);
  DCHECK_GE(kMaxDownlinkKbps, randomized_downlink_kbps);
  // Round down to the nearest kGranularityKbps kbps value.
  double downlink_kbps_rounded =
      std::round(randomized_downlink_kbps / kGranularityKbps) *
      kGranularityKbps;

  // Convert from Kbps to Mbps.
  return downlink_kbps_rounded / 1000;
}

double GetDeviceScaleFactor() {
  double device_scale_factor = 1.0;
  if (display::Screen::Get()) {
    device_scale_factor =
        display::Screen::Get()->GetPrimaryDisplay().device_scale_factor();
  }
  DCHECK_LT(0.0, device_scale_factor);
  return device_scale_factor;
}

// Returns the zoom factor for a given |url|.
double GetZoomFactor(BrowserContext* context, const GURL& url) {
  double zoom_level = HostZoomMap::GetDefaultForBrowserContext(context)
                          ->GetZoomLevelForHostAndScheme(
                              url.scheme(), net::GetHostOrSpecFromURL(url));

  if (zoom_level == 0.0) {
    // Get default zoom level.
    zoom_level = HostZoomMap::GetDefaultForBrowserContext(context)
                     ->GetDefaultZoomLevel();
  }

  return blink::ZoomLevelToZoomFactor(zoom_level);
}

// Returns a string corresponding to |value|. The returned string satisfies
// ABNF: 1*DIGIT [ "." 1*DIGIT ]
std::string DoubleToSpecCompliantString(double value) {
  DCHECK_LE(0.0, value);
  std::string result = base::NumberToString(value);
  DCHECK(!result.empty());
  if (value >= 1.0)
    return result;

  DCHECK_LE(0.0, value);
  DCHECK_GT(1.0, value);

  // Check if there is at least one character before period.
  if (result.at(0) != '.')
    return result;

  // '.' is the first character in |result|. Prefix one digit before the
  // period to make it spec compliant.
  return "0" + result;
}

// Return the effective connection type value overridden for web APIs.
// If no override value has been set, a null value is returned.
std::optional<net::EffectiveConnectionType>
GetWebHoldbackEffectiveConnectionType() {
  if (!base::FeatureList::IsEnabled(
          features::kNetworkQualityEstimatorWebHoldback)) {
    return std::nullopt;
  }
  std::string effective_connection_type_param =
      base::GetFieldTrialParamValueByFeature(
          features::kNetworkQualityEstimatorWebHoldback,
          "web_effective_connection_type_override");

  std::optional<net::EffectiveConnectionType> effective_connection_type =
      net::GetEffectiveConnectionTypeForName(effective_connection_type_param);
  DCHECK(effective_connection_type_param.empty() || effective_connection_type);

  if (!effective_connection_type)
    return std::nullopt;
  DCHECK_NE(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
            effective_connection_type.value());
  return effective_connection_type;
}

void SetHeaderToDouble(net::HttpRequestHeaders* headers,
                       WebClientHintsType client_hint_type,
                       double value) {
  headers->SetHeader(network::GetClientHintToNameMap().at(client_hint_type),
                     DoubleToSpecCompliantString(value));
}

void SetHeaderToInt(net::HttpRequestHeaders* headers,
                    WebClientHintsType client_hint_type,
                    double value) {
  headers->SetHeader(network::GetClientHintToNameMap().at(client_hint_type),
                     base::NumberToString(std::round(value)));
}

void SetHeaderToString(net::HttpRequestHeaders* headers,
                       WebClientHintsType client_hint_type,
                       const std::string& value) {
  headers->SetHeader(network::GetClientHintToNameMap().at(client_hint_type),
                     value);
}

void RemoveClientHintHeader(WebClientHintsType client_hint_type,
                            net::HttpRequestHeaders* headers) {
  headers->RemoveHeader(network::GetClientHintToNameMap().at(client_hint_type));
}

void AddDeviceMemoryHeader(net::HttpRequestHeaders* headers,
                           bool use_deprecated_version = false) {
  DCHECK(headers);
  blink::ApproximatedDeviceMemory::Initialize();
  const float device_memory =
      blink::ApproximatedDeviceMemory::GetApproximatedDeviceMemory();
  DCHECK_LT(0.0, device_memory);
  SetHeaderToDouble(headers,
                    use_deprecated_version
                        ? WebClientHintsType::kDeviceMemory_DEPRECATED
                        : WebClientHintsType::kDeviceMemory,
                    device_memory);
}

void AddDPRHeader(net::HttpRequestHeaders* headers,
                  BrowserContext* context,
                  const GURL& url,
                  bool use_deprecated_version = false) {
  DCHECK(headers);
  DCHECK(context);
  double device_scale_factor = GetDeviceScaleFactor();
  double zoom_factor = GetZoomFactor(context, url);
  SetHeaderToDouble(headers,
                    use_deprecated_version ? WebClientHintsType::kDpr_DEPRECATED
                                           : WebClientHintsType::kDpr,
                    device_scale_factor * zoom_factor);
}

void AddSaveDataHeader(net::HttpRequestHeaders* headers,
                       BrowserContext* context) {
  DCHECK(headers);
  DCHECK(context);
  // Unlike other client hints, this one is only sent when it has a value.
  if (GetContentClient()->browser()->IsDataSaverEnabled(context))
    SetHeaderToString(headers, WebClientHintsType::kSaveData, "on");
}

RenderWidgetHostView* GetRenderWidgetHostViewFromFrameTreeNode(
    FrameTreeNode* frame_tree_node) {
  if (!frame_tree_node || !frame_tree_node->current_frame_host())
    return nullptr;

  return frame_tree_node->current_frame_host()->GetMainFrame()->GetView();
}

gfx::Size GetViewportSize(FrameTreeNode* frame_tree_node,
                          ClientHintsControllerDelegate* delegate) {
#if DCHECK_IS_ON()
  // In some tests we need to force an empty viewport size.
  if (delegate->ShouldForceEmptyViewportSize()) {
    CHECK_IS_TEST();
    return gfx::Size();
  }
#endif

  // If possible, return the current viewport size.
  RenderWidgetHostView* view =
      GetRenderWidgetHostViewFromFrameTreeNode(frame_tree_node);
  if (view) {
    return view->GetVisibleViewportSize();
  }

  // Otherwise, use the cached viewport size if it is valid (both dimensions are
  // greater than zero).
  gfx::Size cached_viewport_size =
      delegate->GetMostRecentMainFrameViewportSize();
  if (cached_viewport_size.width() > 0 && cached_viewport_size.height() > 0) {
    return cached_viewport_size;
  }

  // We used to return the display size here as a last resort if above methods
  // didn't work, but this was so inaccurate as to be useless. Short of trying
  // to build a more extensive caching method or restructuring the calculation
  // path to make the estimated size available here, we simply return 0.
  // Further context can be found in crbug.com/1430903.
  // viewport sizes already.
  return gfx::Size();
}

gfx::Size GetScaledViewportSize(BrowserContext* context,
                                const GURL& url,
                                FrameTreeNode* frame_tree_node,
                                ClientHintsControllerDelegate* delegate) {
  gfx::Size viewport_size = GetViewportSize(frame_tree_node, delegate);

#if BUILDFLAG(IS_ANDROID)
  // On Android, the viewport is scaled so the width is 980. See
  // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/css/viewportAndroid.css.
  // TODO(crbug.com/40196453): Improve the usefulness of the viewport client
  // hints for navigation requests.
  if (viewport_size.width() > 0) {
    viewport_size =
        ScaleToRoundedSize(viewport_size, 980.0 / viewport_size.width());
  }
#endif

  double zoom_factor = GetZoomFactor(context, url);
  if (zoom_factor > 0) {
    viewport_size = ScaleToRoundedSize(viewport_size, 1.0 / zoom_factor);
  }
  return viewport_size;
}

void AddViewportWidthHeader(net::HttpRequestHeaders* headers,
                            BrowserContext* context,
                            const GURL& url,
                            FrameTreeNode* frame_tree_node,
                            ClientHintsControllerDelegate* delegate,
                            bool use_deprecated_version = false) {
  DCHECK(headers);
  DCHECK(context);

  gfx::Size viewport_size =
      GetScaledViewportSize(context, url, frame_tree_node, delegate);

  // The width cannot be less than 0, but if it is zero that means we could not
  // determine the width and should omit the header.
  DCHECK_LE(0, viewport_size.width());
  if (viewport_size.width() > 0) {
    SetHeaderToInt(headers,
                   use_deprecated_version
                       ? WebClientHintsType::kViewportWidth_DEPRECATED
                       : WebClientHintsType::kViewportWidth,
                   viewport_size.width());
  }
}

void AddViewportHeightHeader(net::HttpRequestHeaders* headers,
                             BrowserContext* context,
                             const GURL& url,
                             FrameTreeNode* frame_tree_node,
                             ClientHintsControllerDelegate* delegate) {
  DCHECK(headers);
  DCHECK(context);

  gfx::Size viewport_size =
      GetScaledViewportSize(context, url, frame_tree_node, delegate);

  // The height cannot be less than 0, but if it is zero that means we could not
  // determine the height and should omit the header.
  DCHECK_LE(0, viewport_size.height());
  if (viewport_size.height() > 0) {
    SetHeaderToInt(headers, network::mojom::WebClientHintsType::kViewportHeight,
                   viewport_size.height());
  }
}

void AddRttHeader(net::HttpRequestHeaders* headers,
                  network::NetworkQualityTracker* network_quality_tracker,
                  const GURL& url) {
  DCHECK(headers);

  std::optional<net::EffectiveConnectionType> web_holdback_ect =
      GetWebHoldbackEffectiveConnectionType();

  base::TimeDelta http_rtt;
  if (web_holdback_ect.has_value()) {
    http_rtt = net::NetworkQualityEstimatorParams::GetDefaultTypicalHttpRtt(
        web_holdback_ect.value());
  } else if (network_quality_tracker) {
    http_rtt = network_quality_tracker->GetHttpRTT();
  } else {
    http_rtt = net::NetworkQualityEstimatorParams::GetDefaultTypicalHttpRtt(
        net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
  }
  SetHeaderToInt(headers, WebClientHintsType::kRtt_DEPRECATED,
                 RoundRtt(url.host(), http_rtt));
}

void AddDownlinkHeader(net::HttpRequestHeaders* headers,
                       network::NetworkQualityTracker* network_quality_tracker,
                       const GURL& url) {
  DCHECK(headers);
  std::optional<net::EffectiveConnectionType> web_holdback_ect =
      GetWebHoldbackEffectiveConnectionType();

  int32_t downlink_throughput_kbps;

  if (web_holdback_ect.has_value()) {
    downlink_throughput_kbps =
        net::NetworkQualityEstimatorParams::GetDefaultTypicalDownlinkKbps(
            web_holdback_ect.value());
  } else if (network_quality_tracker) {
    downlink_throughput_kbps =
        network_quality_tracker->GetDownstreamThroughputKbps();
  } else {
    downlink_throughput_kbps =
        net::NetworkQualityEstimatorParams::GetDefaultTypicalDownlinkKbps(
            net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
  }

  SetHeaderToDouble(headers, WebClientHintsType::kDownlink_DEPRECATED,
                    RoundKbpsToMbps(url.host(), downlink_throughput_kbps));
}

void AddEctHeader(net::HttpRequestHeaders* headers,
                  network::NetworkQualityTracker* network_quality_tracker,
                  const GURL& url) {
  DCHECK(headers);

  std::optional<net::EffectiveConnectionType> web_holdback_ect =
      GetWebHoldbackEffectiveConnectionType();

  int effective_connection_type;
  if (web_holdback_ect.has_value()) {
    effective_connection_type = web_holdback_ect.value();
  } else if (network_quality_tracker) {
    effective_connection_type =
        static_cast<int>(network_quality_tracker->GetEffectiveConnectionType());
  } else {
    effective_connection_type =
        static_cast<int>(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
  }

  SetHeaderToString(
      headers, WebClientHintsType::kEct_DEPRECATED,
      network::kWebEffectiveConnectionTypeMapping[effective_connection_type]);
}

void AddPrefersColorSchemeHeader(net::HttpRequestHeaders* headers,
                                 FrameTreeNode* frame_tree_node) {
  if (!frame_tree_node)
    return;
  blink::mojom::PreferredColorScheme preferred_color_scheme =
      WebContents::FromRenderFrameHost(frame_tree_node->current_frame_host())
          ->GetOrCreateWebPreferences()
          .preferred_color_scheme;
  bool is_dark_mode =
      preferred_color_scheme == blink::mojom::PreferredColorScheme::kDark;
  SetHeaderToString(headers, WebClientHintsType::kPrefersColorScheme,
                    is_dark_mode ? network::kPrefersColorSchemeDark
                                 : network::kPrefersColorSchemeLight);
}

void AddPrefersReducedMotionHeader(net::HttpRequestHeaders* headers,
                                   FrameTreeNode* frame_tree_node) {
  if (!frame_tree_node)
    return;
  bool prefers_reduced_motion =
      WebContents::FromRenderFrameHost(frame_tree_node->current_frame_host())
          ->GetOrCreateWebPreferences()
          .prefers_reduced_motion;
  SetHeaderToString(headers, WebClientHintsType::kPrefersReducedMotion,
                    prefers_reduced_motion
                        ? network::kPrefersReducedMotionReduce
                        : network::kPrefersReducedMotionNoPreference);
}

void AddPrefersReducedTransparencyHeader(net::HttpRequestHeaders* headers,
                                         FrameTreeNode* frame_tree_node) {
  if (!frame_tree_node) {
    return;
  }
  bool prefers_reduced_transparency =
      WebContents::FromRenderFrameHost(frame_tree_node->current_frame_host())
          ->GetOrCreateWebPreferences()
          .prefers_reduced_transparency;
  SetHeaderToString(headers, WebClientHintsType::kPrefersReducedTransparency,
                    prefers_reduced_transparency
                        ? network::kPrefersReducedTransparencyReduce
                        : network::kPrefersReducedTransparencyNoPreference);
}

bool IsValidURLForClientHints(const url::Origin& origin) {
  return network::IsOriginPotentiallyTrustworthy(origin);
}

void AddUAHeader(net::HttpRequestHeaders* headers,
                 WebClientHintsType type,
                 const std::string& value) {
  SetHeaderToString(headers, type, value);
}

// Creates a serialized string header value out of the input type, using
// structured headers as described in
// https://www.rfc-editor.org/rfc/rfc8941.html.
template <typename T>
const std::string SerializeHeaderString(const T& value) {
  return net::structured_headers::SerializeItem(
             net::structured_headers::Item(value))
      .value_or(std::string());
}

// Captures the state used in applying client hints.
struct ClientHintsExtendedData {
  ClientHintsExtendedData(const url::Origin& origin,
                          FrameTreeNode* frame_tree_node,
                          ClientHintsControllerDelegate* delegate)
      : resource_origin(origin) {
    // If the current frame is the outermost main frame, the URL wasn't
    // committed yet, so in order to get the main frame URL, we should use the
    // provided URL instead. Otherwise, the current frame is a subframe and the
    // outermost main frame URL was committed, so we can safely get it from it.
    // Similarly, an in-navigation outermost main frame doesn't yet have a
    // permissions policy.
    is_outermost_main_frame =
        !frame_tree_node || frame_tree_node->IsOutermostMainFrame();
    if (is_outermost_main_frame) {
      main_frame_origin = resource_origin;
    } else if (frame_tree_node->IsInFencedFrameTree()) {
      // TODO(crbug.com/40263100) Add WPT tests and specify the behavior
      // of client hints delegation for subframes inside FencedFrames.
      // Test cases should cover this 3 layers nested frames case, from top to
      // bottom:
      // 1. Fenced frame.
      // 2. Urn iframe.
      // 3. Iframe.
      // `GetFencedFrameProperties()` called from the iframe returns the
      // fenced frame properties from the urn iframe because it does a bottom
      // up traversal.
      // See crbug.com/1470634.
      const std::optional<FencedFrameProperties>& fenced_frame_properties =
          frame_tree_node->GetFencedFrameProperties();
      base::span<const network::mojom::PermissionsPolicyFeature> permissions;
      if (fenced_frame_properties) {
        permissions = fenced_frame_properties->effective_enabled_permissions();
      }
      permissions_policy =
          network::PermissionsPolicy::CreateFixedForFencedFrame(
              resource_origin, /*header_policy=*/{}, permissions);
    } else {
      RenderFrameHostImpl* main_frame =
          frame_tree_node->frame_tree().GetMainFrame();
      main_frame_origin = main_frame->GetLastCommittedOrigin();
      permissions_policy = network::PermissionsPolicy::CopyStateFrom(
          main_frame->GetPermissionsPolicy());
    }

    const base::TimeTicks start_time = base::TimeTicks::Now();
    delegate->GetAllowedClientHintsFromSource(main_frame_origin, &hints);
    const base::TimeTicks pref_read_time = base::TimeTicks::Now();

    // If this is a prerender tree, also capture prerender local setting. The
    // setting was given by navigation requests on the prerendering page, and
    // has not been used as a global setting.
    if (frame_tree_node) {
      if (auto* host = PrerenderHost::GetFromFrameTreeNodeIfPrerendering(
              *frame_tree_node)) {
        host->GetAllowedClientHintsOnPage(main_frame_origin, &hints);
      }
    }

    // Record the time spent getting the client hints.
    const base::TimeTicks end_time = base::TimeTicks::Now();
    base::UmaHistogramMicrosecondsTimes("ClientHints.FetchLatency_PrefRead",
                                        pref_read_time - start_time);
    base::UmaHistogramMicrosecondsTimes(
        "ClientHints.FetchLatency_PrerenderHost", end_time - pref_read_time);
    base::UmaHistogramMicrosecondsTimes("ClientHints.FetchLatency_Total",
                                        end_time - start_time);
  }

  blink::EnabledClientHints hints;
  url::Origin resource_origin;
  bool is_outermost_main_frame = false;
  url::Origin main_frame_origin;
  std::unique_ptr<network::PermissionsPolicy> permissions_policy;
};

bool IsClientHintEnabled(const ClientHintsExtendedData& data,
                         WebClientHintsType type) {
  return blink::IsClientHintSentByDefault(type) || data.hints.IsEnabled(type);
}

bool IsClientHintAllowed(const ClientHintsExtendedData& data,
                         WebClientHintsType type) {
  if (data.is_outermost_main_frame) {
    return true;
  }
  return (data.permissions_policy->IsFeatureEnabledForOrigin(
      network::GetClientHintToPolicyFeatureMap().at(type),
      data.resource_origin));
}

bool ShouldAddClientHint(const ClientHintsExtendedData& data,
                         WebClientHintsType type) {
  return IsClientHintEnabled(data, type) && IsClientHintAllowed(data, type);
}

bool IsJavascriptEnabled(FrameTreeNode* frame_tree_node) {
  return WebContents::FromRenderFrameHost(frame_tree_node->current_frame_host())
      ->GetOrCreateWebPreferences()
      .javascript_enabled;
}

// This modifies `data.permissions_policy` to reflect any changes to client hint
// permissions which may have occurred via the named accept-ch meta tag.
// The permissions policy the browser side has for the frame was set in stone
// before HTML parsing began, so any updates must be sent via
// `container_policy`.
// TODO(crbug.com/40208054): Replace w/ generic HTML policy modification.
void UpdateIFramePermissionsPolicyWithDelegationSupportForClientHints(
    ClientHintsExtendedData& data,
    const network::ParsedPermissionsPolicy& container_policy) {
  if (container_policy.empty()) {
    return;
  }

  // For client hints specifically, we need to allow the container policy
  // to overwrite the parent policy so that permissions policies set in HTML
  // via an accept-ch meta tag can be respected.
  network::ParsedPermissionsPolicy client_hints_container_policy;
  for (const auto& container_policy_item : container_policy) {
    const auto& it = network::GetPolicyFeatureToClientHintMap().find(
        container_policy_item.feature);
    if (it != network::GetPolicyFeatureToClientHintMap().end()) {
      client_hints_container_policy.push_back(container_policy_item);

      // We need to ensure `blink::EnabledClientHints` is updated where the
      // main frame now has permission for the given client hints.
      for (const auto& origin_with_possible_wildcards :
           container_policy_item.allowed_origins) {
        if (origin_with_possible_wildcards.DoesMatchOrigin(
                data.main_frame_origin)) {
          for (const auto& hint : it->second) {
            data.hints.SetIsEnabled(hint, /*should_send*/ true);
          }
          break;
        }
      }
    }
  }
  data.permissions_policy =
      data.permissions_policy->WithClientHints(client_hints_container_policy);
}

// Captures when UpdateNavigationRequestClientUaHeadersImpl() is being called.
enum class ClientUaHeaderCallType {
  // The call is happening during creation of the NavigationRequest.
  kDuringCreation,

  // The call is happening after creation of the NavigationRequest.
  kAfterCreated,
};

// Implementation of UpdateNavigationRequestClientUaHeaders().
void UpdateNavigationRequestClientUaHeadersImpl(
    ClientHintsControllerDelegate* delegate,
    bool is_ua_override_on,
    FrameTreeNode* ftn_for_web_contents_override,
    ClientUaHeaderCallType call_type,
    net::HttpRequestHeaders* headers,
    const network::ParsedPermissionsPolicy& container_policy,
    const ClientHintsExtendedData& data,
    FrameTreeNode* ftn_for_devtools_override) {
  std::optional<blink::UserAgentMetadata> ua_metadata;
  bool disable_due_to_custom_ua = false;
  if (is_ua_override_on) {
    NavigatorDelegate* nav_delegate =
        ftn_for_web_contents_override
            ? ftn_for_web_contents_override->navigator().GetDelegate()
            : nullptr;
    ua_metadata = nav_delegate
                      ? nav_delegate
                            ->GetUserAgentOverride(
                                ftn_for_web_contents_override->frame_tree())
                            .ua_metadata_override
                      : std::nullopt;
    // If a custom UA override is set, but no value is provided for UA client
    // hints, disable them.
    disable_due_to_custom_ua = !ua_metadata.has_value();
  }

  if (ftn_for_devtools_override &&
      devtools_instrumentation::ApplyUserAgentMetadataOverrides(
          ftn_for_devtools_override, &ua_metadata)) {
    // Likewise, if devtools says to override client hints but provides no
    // value, disable them. This overwrites previous decision from UI.
    disable_due_to_custom_ua = !ua_metadata.has_value();
  }

  if (!disable_due_to_custom_ua) {
    if (!ua_metadata.has_value())
      ua_metadata = delegate->GetUserAgentMetadata();

    // The `Sec-CH-UA` client hint is attached to all outgoing requests. This is
    // (intentionally) different than other client hints.
    // It's barred behind ShouldAddClientHints to make sure it's controlled by
    // Permissions Policy.
    //
    // https://wicg.github.io/client-hints-infrastructure/#abstract-opdef-append-client-hints-to-request
    if (ShouldAddClientHint(data, WebClientHintsType::kUA)) {
      AddUAHeader(headers, WebClientHintsType::kUA,
                  ua_metadata->SerializeBrandMajorVersionList());
    }
    // The `Sec-CH-UA-Mobile client hint was also deemed "low entropy" and can
    // safely be sent with every request. Similarly to UA, ShouldAddClientHints
    // makes sure it's controlled by Permissions Policy.
    if (ShouldAddClientHint(data, WebClientHintsType::kUAMobile)) {
      AddUAHeader(headers, WebClientHintsType::kUAMobile,
                  SerializeHeaderString(ua_metadata->mobile));
    }

    if (ShouldAddClientHint(data, WebClientHintsType::kUAFullVersion)) {
      AddUAHeader(headers, WebClientHintsType::kUAFullVersion,
                  SerializeHeaderString(ua_metadata->full_version));
    }

    if (ShouldAddClientHint(data, WebClientHintsType::kUAArch)) {
      AddUAHeader(headers, WebClientHintsType::kUAArch,
                  SerializeHeaderString(ua_metadata->architecture));
    }

    if (ShouldAddClientHint(data, WebClientHintsType::kUAPlatform)) {
      AddUAHeader(headers, WebClientHintsType::kUAPlatform,
                  SerializeHeaderString(ua_metadata->platform));
    }

    if (ShouldAddClientHint(data, WebClientHintsType::kUAPlatformVersion)) {
      AddUAHeader(headers, WebClientHintsType::kUAPlatformVersion,
                  SerializeHeaderString(ua_metadata->platform_version));
    }

    if (ShouldAddClientHint(data, WebClientHintsType::kUAModel)) {
      AddUAHeader(headers, WebClientHintsType::kUAModel,
                  SerializeHeaderString(ua_metadata->model));
    }
    if (ShouldAddClientHint(data, WebClientHintsType::kUABitness)) {
      AddUAHeader(headers, WebClientHintsType::kUABitness,
                  SerializeHeaderString(ua_metadata->bitness));
    }
    if (ShouldAddClientHint(data, WebClientHintsType::kUAWoW64)) {
      AddUAHeader(headers, WebClientHintsType::kUAWoW64,
                  SerializeHeaderString(ua_metadata->wow64));
    }
    if (ShouldAddClientHint(data, WebClientHintsType::kUAFullVersionList)) {
      AddUAHeader(headers, WebClientHintsType::kUAFullVersionList,
                  ua_metadata->SerializeBrandFullVersionList());
    }
    if (ShouldAddClientHint(data, WebClientHintsType::kUAFormFactors)) {
      AddUAHeader(headers, WebClientHintsType::kUAFormFactors,
                  ua_metadata->SerializeFormFactors());
    }
  } else if (call_type == ClientUaHeaderCallType::kAfterCreated) {
    RemoveClientHintHeader(WebClientHintsType::kUA, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAMobile, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAFullVersion, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAArch, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAPlatform, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAPlatformVersion, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAModel, headers);
    RemoveClientHintHeader(WebClientHintsType::kUABitness, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAFullVersionList, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAWoW64, headers);
    RemoveClientHintHeader(WebClientHintsType::kUAFormFactors, headers);
  }
}

}  // namespace

bool ShouldAddClientHints(const url::Origin& origin,
                          FrameTreeNode* frame_tree_node,
                          ClientHintsControllerDelegate* delegate,
                          const std::optional<GURL> maybe_request_url) {
  url::Origin origin_to_check =
      maybe_request_url ? url::Origin::Create(maybe_request_url.value())
                        : origin;
  // Client hints should only be enabled when JavaScript is enabled. Platforms
  // which enable/disable JavaScript on a per-origin basis should implement
  // IsJavaScriptAllowed to check a given origin. Other platforms (Android
  // WebView) enable/disable JavaScript on a per-View basis, using the
  // WebPreferences setting.
  return IsValidURLForClientHints(origin_to_check) &&
         delegate->IsJavaScriptAllowed(
             origin_to_check.GetURL(),
             frame_tree_node ? frame_tree_node->GetParentOrOuterDocument()
                             : nullptr) &&
         (!frame_tree_node || IsJavascriptEnabled(frame_tree_node));
}

unsigned long RoundRttForTesting(const std::string& host,
                                 const std::optional<base::TimeDelta>& rtt) {
  return RoundRtt(host, rtt);
}

double RoundKbpsToMbpsForTesting(const std::string& host,
                                 const std::optional<int32_t>& downlink_kbps) {
  return RoundKbpsToMbps(host, downlink_kbps);
}

void UpdateNavigationRequestClientUaHeaders(
    const url::Origin& origin,
    ClientHintsControllerDelegate* delegate,
    bool override_ua,
    FrameTreeNode* frame_tree_node,
    net::HttpRequestHeaders* headers,
    const std::optional<GURL>& request_url) {
  DCHECK(frame_tree_node);
  if (!ShouldAddClientHints(origin, frame_tree_node, delegate, request_url)) {
    return;
  }

  // In usual navigation, use the common FrameTreeNode to look up DevTools for
  // the DevTools UA override logic.
  ClientHintsExtendedData data(origin, frame_tree_node, delegate);
  UpdateNavigationRequestClientUaHeadersImpl(
      delegate, override_ua, frame_tree_node,
      ClientUaHeaderCallType::kAfterCreated, headers, {}, data,
      /*ftn_for_devtools_override=*/frame_tree_node);
}
namespace {

// The main logic of adding Client Hints headers to `headers`. `frame_tree_node`
// is used for checking the client hints policies, looking up UA overrides in
// the corresponding WebContents, and calculating client hints values like
// ViewportWidth, whereas `ftn_for_devtools_override` only serves as source of
// UA override by DevTools. The two FrameTreeNode parameters can differ in
// prefetch navigation cases because the FrameTreeNode of the navigation target
// is sometimes unavailable during prefetch, and we must find an alternative
// FrameTreeNode for the DevTools UA override source in such cases.
void AddRequestClientHintsHeaders(
    const url::Origin& origin,
    net::HttpRequestHeaders* headers,
    BrowserContext* context,
    ClientHintsControllerDelegate* delegate,
    bool is_ua_override_on,
    FrameTreeNode* frame_tree_node,
    const network::ParsedPermissionsPolicy& container_policy,
    FrameTreeNode* ftn_for_devtools_override) {
  ClientHintsExtendedData data(origin, frame_tree_node, delegate);
  UpdateIFramePermissionsPolicyWithDelegationSupportForClientHints(
      data, container_policy);

  GURL url = origin.GetURL();

  // Add Headers
  if (ShouldAddClientHint(data, WebClientHintsType::kDeviceMemory_DEPRECATED)) {
    AddDeviceMemoryHeader(headers, /*use_deprecated_version*/ true);
  }
  if (ShouldAddClientHint(data, WebClientHintsType::kDeviceMemory)) {
    AddDeviceMemoryHeader(headers);
  }
  if (ShouldAddClientHint(data, WebClientHintsType::kDpr_DEPRECATED)) {
    AddDPRHeader(headers, context, url, /*use_deprecated_version*/ true);
  }
  if (ShouldAddClientHint(data, WebClientHintsType::kDpr)) {
    AddDPRHeader(headers, context, url);
  }
  if (ShouldAddClientHint(data,
                          WebClientHintsType::kViewportWidth_DEPRECATED)) {
    AddViewportWidthHeader(headers, context, url, frame_tree_node, delegate,
                           /*use_deprecated_version*/ true);
  }
  if (ShouldAddClientHint(data, WebClientHintsType::kViewportWidth)) {
    AddViewportWidthHeader(headers, context, url, frame_tree_node, delegate);
  }
  if (ShouldAddClientHint(
          data, network::mojom::WebClientHintsType::kViewportHeight)) {
    AddViewportHeightHeader(headers, context, url, frame_tree_node, delegate);
  }
  network::NetworkQualityTracker* network_quality_tracker =
      delegate->GetNetworkQualityTracker();
  if (ShouldAddClientHint(data, WebClientHintsType::kRtt_DEPRECATED)) {
    AddRttHeader(headers, network_quality_tracker, url);
  }
  if (ShouldAddClientHint(data, WebClientHintsType::kDownlink_DEPRECATED)) {
    AddDownlinkHeader(headers, network_quality_tracker, url);
  }
  if (ShouldAddClientHint(data, WebClientHintsType::kEct_DEPRECATED)) {
    AddEctHeader(headers, network_quality_tracker, url);
  }

  UpdateNavigationRequestClientUaHeadersImpl(
      delegate, is_ua_override_on, frame_tree_node,
      ClientUaHeaderCallType::kDuringCreation, headers, container_policy, data,
      ftn_for_devtools_override);

  if (ShouldAddClientHint(data, WebClientHintsType::kPrefersColorScheme)) {
    AddPrefersColorSchemeHeader(headers, frame_tree_node);
  }

  if (ShouldAddClientHint(data, WebClientHintsType::kPrefersReducedMotion)) {
    AddPrefersReducedMotionHeader(headers, frame_tree_node);
  }

  if (ShouldAddClientHint(data,
                          WebClientHintsType::kPrefersReducedTransparency)) {
    AddPrefersReducedTransparencyHeader(headers, frame_tree_node);
  }

  if (ShouldAddClientHint(data, WebClientHintsType::kSaveData))
    AddSaveDataHeader(headers, context);

  // Static assert that triggers if a new client hint header is added. If a
  // new client hint header is added, the following assertion should be updated.
  // If possible, logic should be added above so that the request headers for
  // the newly added client hint can be added to the request.
  static_assert(
      network::mojom::WebClientHintsType::kPrefersReducedTransparency ==
          network::mojom::WebClientHintsType::kMaxValue,
      "Consider adding client hint request headers from the browser process");

  // TODO(crbug.com/40526905): If the request is redirected, the client hint
  // headers stay attached to the redirected request. Consider removing/adding
  // the client hints headers if the request is redirected with a change in
  // scheme or a change in the origin.
}

}  // namespace

void AddPrefetchNavigationRequestClientHintsHeaders(
    const url::Origin& origin,
    net::HttpRequestHeaders* headers,
    BrowserContext* context,
    ClientHintsControllerDelegate* delegate,
    bool is_ua_override_on,
    FrameTreeNode* ftn_for_devtools_override) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(context);

  if (!ShouldAddClientHints(origin, nullptr, delegate)) {
    return;
  }

  // FrameTreeNode is nullptr because it is possible that no navigation has been
  // committed yet. Nevertheless, `ftn_for_devtools_override` serves as a
  // workaround for DevTools-initiated UA overrides.
  AddRequestClientHintsHeaders(origin, headers, context, delegate,
                               is_ua_override_on, nullptr, {},
                               ftn_for_devtools_override);
}

void AddNavigationRequestClientHintsHeaders(
    const url::Origin& origin,
    net::HttpRequestHeaders* headers,
    BrowserContext* context,
    ClientHintsControllerDelegate* delegate,
    bool is_ua_override_on,
    FrameTreeNode* frame_tree_node,
    const network::ParsedPermissionsPolicy& container_policy,
    const std::optional<GURL>& request_url) {
  DCHECK(frame_tree_node);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(context);
  if (!ShouldAddClientHints(origin, frame_tree_node, delegate, request_url)) {
    return;
  }

  // In usual navigation, use the common FrameTreeNode to look up DevTools for
  // the DevTools UA override logic.
  AddRequestClientHintsHeaders(
      origin, headers, context, delegate, is_ua_override_on, frame_tree_node,
      container_policy, /*ftn_for_devtools_override=*/frame_tree_node);
}

std::optional<std::vector<WebClientHintsType>>
ParseAndPersistAcceptCHForNavigation(
    const url::Origin& origin,
    const network::mojom::ParsedHeadersPtr& parsed_headers,
    const net::HttpResponseHeaders* response_headers,
    BrowserContext* context,
    ClientHintsControllerDelegate* delegate,
    FrameTreeNode* frame_tree_node) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(context);
  DCHECK(parsed_headers);

  if (!parsed_headers->accept_ch)
    return std::nullopt;

  if (!IsValidURLForClientHints(origin))
    return std::nullopt;

  // Client hints should only be enabled when JavaScript is enabled. Platforms
  // which enable/disable JavaScript on a per-origin basis should implement
  // IsJavaScriptAllowed to check a given origin. Other platforms (Android
  // WebView) enable/disable JavaScript on a per-View basis, using the
  // WebPreferences setting.
  if (!delegate->IsJavaScriptAllowed(
          origin.GetURL(), frame_tree_node->GetParentOrOuterDocument()) ||
      !IsJavascriptEnabled(frame_tree_node)) {
    return std::nullopt;
  }

  // Only the main frame should parse accept-CH.
  if (!frame_tree_node->IsMainFrame()) {
    return std::nullopt;
  }

  blink::EnabledClientHints enabled_hints;
  for (const WebClientHintsType type : parsed_headers->accept_ch.value()) {
    enabled_hints.SetIsEnabled(type, true);
  }
  const std::vector<WebClientHintsType> persisted_hints =
      enabled_hints.GetEnabledHints();
  DCHECK(frame_tree_node);
  PersistAcceptCH(origin, *frame_tree_node, delegate, persisted_hints);
  return persisted_hints;
}

void PersistAcceptCH(const url::Origin& origin,
                     FrameTreeNode& frame_tree_node,
                     ClientHintsControllerDelegate* delegate,
                     const std::vector<WebClientHintsType>& hints) {
  DCHECK(delegate);

  // For prerendering headers, it should not persist the client header until
  // activation, considering user has not visited the page and allowed it to
  // change content setting yet. The client hints should apply to navigations
  // in the prerendering page, and propagate to the global setting upon user
  // navigation.
  if (auto* host =
          PrerenderHost::GetFromFrameTreeNodeIfPrerendering(frame_tree_node)) {
    host->OnAcceptClientHintChanged(origin, hints);
    return;
  }

  delegate->PersistClientHints(
      origin, frame_tree_node.GetParentOrOuterDocument(), hints);
}

std::vector<WebClientHintsType> LookupAcceptCHForCommit(
    const url::Origin& origin,
    ClientHintsControllerDelegate* delegate,
    FrameTreeNode* frame_tree_node,
    const std::optional<GURL>& request_url) {
  std::vector<WebClientHintsType> result;
  if (!ShouldAddClientHints(origin, frame_tree_node, delegate, request_url)) {
    return result;
  }

  const ClientHintsExtendedData data(origin, frame_tree_node, delegate);
  return data.hints.GetEnabledHints();
}

CriticalHintsMissingStatus GetCriticalHintsMissingStatus(
    const url::Origin& origin,
    FrameTreeNode* frame_tree_node,
    ClientHintsControllerDelegate* delegate,
    const std::vector<WebClientHintsType>& critical_hints) {
  ClientHintsExtendedData data(origin, frame_tree_node, delegate);

  bool contains_not_allowed = false;
  // Note: these only check for per-hint origin/permissions policy settings, not
  // origin-level or "browser-level" policies like disabling JS or other
  // features.
  for (auto hint : critical_hints) {
    if (!IsClientHintAllowed(data, hint)) {
      contains_not_allowed = true;
      continue;
    }
    if (!IsClientHintEnabled(data, hint)) {
      return CriticalHintsMissingStatus::kMissing;
    }
  }

  return contains_not_allowed
             ? CriticalHintsMissingStatus::kPresentButContainsNotAllowed
             : CriticalHintsMissingStatus::kPresent;
}

network::ResourceRequest::TrustedParams::EnabledClientHints
GetEnabledClientHints(const url::Origin& origin,
                      FrameTreeNode* frame_tree_node,
                      ClientHintsControllerDelegate* delegate) {
  ClientHintsExtendedData data(origin, frame_tree_node, delegate);

  network::ResourceRequest::TrustedParams::EnabledClientHints
      enabled_client_hints;
  enabled_client_hints.is_outermost_main_frame = data.is_outermost_main_frame;
  const auto& client_hints_map = network::GetClientHintToNameMap();
  // Note: these only check for per-hint origin/permissions policy settings, not
  // origin-level or "browser-level" policies like disabling JS or other
  // features.
  for (const auto& [hint, _] : client_hints_map) {
    // `enabled_client_hints.hints` are client hints that are enabled for the
    // origin and allowed to be attached to the request.
    if (ShouldAddClientHint(data, hint)) {
      enabled_client_hints.hints.push_back(hint);
    }
    // `enabled_client_hints.not_allowed_hints` are client hints that are
    // currently not allowed to be attached to the request.
    if (base::FeatureList::IsEnabled(
            network::features::kOffloadAcceptCHFrameCheck) &&
        network::features::kAcceptCHFrameOffloadNotAllowedHints.Get() &&
        !IsClientHintAllowed(data, hint)) {
      enabled_client_hints.not_allowed_hints.push_back(hint);
    }
  }
  enabled_client_hints.origin = data.main_frame_origin;
  return enabled_client_hints;
}

}  // namespace content
