#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#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/is_potentially_trustworthy.h"
#include "services/network/public/cpp/network_quality_tracker.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/permissions_policy/origin_with_possible_wildcards.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy.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 {
WebClientHintsType;
uint8_t randomization_salt = …;
constexpr size_t kMaxRandomNumbers = …;
uint8_t RandomizationSalt() { … }
double GetRandomMultiplier(const std::string& host) { … }
unsigned long RoundRtt(const std::string& host,
const std::optional<base::TimeDelta>& rtt) { … }
double RoundKbpsToMbps(const std::string& host,
const std::optional<int32_t>& downlink_kbps) { … }
double GetDeviceScaleFactor() { … }
double GetZoomFactor(BrowserContext* context, const GURL& url) { … }
std::string DoubleToSpecCompliantString(double value) { … }
std::optional<net::EffectiveConnectionType>
GetWebHoldbackEffectiveConnectionType() { … }
void SetHeaderToDouble(net::HttpRequestHeaders* headers,
WebClientHintsType client_hint_type,
double value) { … }
void SetHeaderToInt(net::HttpRequestHeaders* headers,
WebClientHintsType client_hint_type,
double value) { … }
void SetHeaderToString(net::HttpRequestHeaders* headers,
WebClientHintsType client_hint_type,
const std::string& value) { … }
void RemoveClientHintHeader(WebClientHintsType client_hint_type,
net::HttpRequestHeaders* headers) { … }
void AddDeviceMemoryHeader(net::HttpRequestHeaders* headers,
bool use_deprecated_version = false) { … }
void AddDPRHeader(net::HttpRequestHeaders* headers,
BrowserContext* context,
const GURL& url,
bool use_deprecated_version = false) { … }
void AddSaveDataHeader(net::HttpRequestHeaders* headers,
BrowserContext* context) { … }
RenderWidgetHostView* GetRenderWidgetHostViewFromFrameTreeNode(
FrameTreeNode* frame_tree_node) { … }
gfx::Size GetViewportSize(FrameTreeNode* frame_tree_node,
ClientHintsControllerDelegate* delegate) { … }
gfx::Size GetScaledViewportSize(BrowserContext* context,
const GURL& url,
FrameTreeNode* frame_tree_node,
ClientHintsControllerDelegate* delegate) { … }
void AddViewportWidthHeader(net::HttpRequestHeaders* headers,
BrowserContext* context,
const GURL& url,
FrameTreeNode* frame_tree_node,
ClientHintsControllerDelegate* delegate,
bool use_deprecated_version = false) { … }
void AddViewportHeightHeader(net::HttpRequestHeaders* headers,
BrowserContext* context,
const GURL& url,
FrameTreeNode* frame_tree_node,
ClientHintsControllerDelegate* delegate) { … }
void AddRttHeader(net::HttpRequestHeaders* headers,
network::NetworkQualityTracker* network_quality_tracker,
const GURL& url) { … }
void AddDownlinkHeader(net::HttpRequestHeaders* headers,
network::NetworkQualityTracker* network_quality_tracker,
const GURL& url) { … }
void AddEctHeader(net::HttpRequestHeaders* headers,
network::NetworkQualityTracker* network_quality_tracker,
const GURL& url) { … }
void AddPrefersColorSchemeHeader(net::HttpRequestHeaders* headers,
FrameTreeNode* frame_tree_node) { … }
void AddPrefersReducedMotionHeader(net::HttpRequestHeaders* headers,
FrameTreeNode* frame_tree_node) { … }
void AddPrefersReducedTransparencyHeader(net::HttpRequestHeaders* headers,
FrameTreeNode* frame_tree_node) { … }
bool IsValidURLForClientHints(const url::Origin& origin) { … }
void AddUAHeader(net::HttpRequestHeaders* headers,
WebClientHintsType type,
const std::string& value) { … }
template <typename T>
const std::string SerializeHeaderString(const T& value) { … }
struct ClientHintsExtendedData { … };
bool IsClientHintEnabled(const ClientHintsExtendedData& data,
WebClientHintsType type) { … }
bool IsClientHintAllowed(const ClientHintsExtendedData& data,
WebClientHintsType type) { … }
bool ShouldAddClientHint(const ClientHintsExtendedData& data,
WebClientHintsType type) { … }
bool IsJavascriptEnabled(FrameTreeNode* frame_tree_node) { … }
void UpdateIFramePermissionsPolicyWithDelegationSupportForClientHints(
ClientHintsExtendedData& data,
const blink::ParsedPermissionsPolicy& container_policy) { … }
enum class ClientUaHeaderCallType { … };
void UpdateNavigationRequestClientUaHeadersImpl(
ClientHintsControllerDelegate* delegate,
bool override_ua,
FrameTreeNode* frame_tree_node,
ClientUaHeaderCallType call_type,
net::HttpRequestHeaders* headers,
const blink::ParsedPermissionsPolicy& container_policy,
const std::optional<GURL>& request_url,
const ClientHintsExtendedData& data) { … }
}
bool ShouldAddClientHints(const url::Origin& origin,
FrameTreeNode* frame_tree_node,
ClientHintsControllerDelegate* delegate,
const std::optional<GURL> maybe_request_url) { … }
unsigned long RoundRttForTesting(const std::string& host,
const std::optional<base::TimeDelta>& rtt) { … }
double RoundKbpsToMbpsForTesting(const std::string& host,
const std::optional<int32_t>& 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) { … }
namespace {
void AddRequestClientHintsHeaders(
const url::Origin& origin,
net::HttpRequestHeaders* headers,
BrowserContext* context,
ClientHintsControllerDelegate* delegate,
bool is_ua_override_on,
FrameTreeNode* frame_tree_node,
const blink::ParsedPermissionsPolicy& container_policy,
const std::optional<GURL>& request_url) { … }
}
void AddPrefetchNavigationRequestClientHintsHeaders(
const url::Origin& origin,
net::HttpRequestHeaders* headers,
BrowserContext* context,
ClientHintsControllerDelegate* delegate,
bool is_ua_override_on,
bool is_javascript_enabled) { … }
void AddNavigationRequestClientHintsHeaders(
const url::Origin& origin,
net::HttpRequestHeaders* headers,
BrowserContext* context,
ClientHintsControllerDelegate* delegate,
bool is_ua_override_on,
FrameTreeNode* frame_tree_node,
const blink::ParsedPermissionsPolicy& container_policy,
const std::optional<GURL>& request_url) { … }
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) { … }
void PersistAcceptCH(const url::Origin& origin,
FrameTreeNode& frame_tree_node,
ClientHintsControllerDelegate* delegate,
const std::vector<WebClientHintsType>& hints) { … }
std::vector<WebClientHintsType> LookupAcceptCHForCommit(
const url::Origin& origin,
ClientHintsControllerDelegate* delegate,
FrameTreeNode* frame_tree_node,
const std::optional<GURL>& request_url) { … }
bool AreCriticalHintsMissing(
const url::Origin& origin,
FrameTreeNode* frame_tree_node,
ClientHintsControllerDelegate* delegate,
const std::vector<WebClientHintsType>& critical_hints) { … }
}