From 1649e103a6c9a386884f1a2366979b2b0e0bcd8c Mon Sep 17 00:00:00 2001 From: Aaron Tagliaboschi Date: Fri, 18 Jun 2021 23:15:07 +0000 Subject: [PATCH] [UA-CH] Implement Sec-CH-UA-Bitness client hint header Intent to Implement and Ship: https://groups.google.com/a/chromium.org/g/blink-dev/c/dafizBGwWMw https://github.com/WICG/ua-client-hints/issues/105 To be honest, the only real point of interest is `content/common/user_agent.cc`, which is where `GetLowEntropyCpuBitness` is implemented. Everything else is various levels of plumbing to set up a new Client Hint header, populate it, test it, and add a new Permissions Policy to control it. Bug: 1199809 Change-Id: I0e7f36c8915720cb46e06452a85092a64bde8f06 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2840423 Commit-Queue: Aaron Tagliaboschi Reviewed-by: Andrey Kosyakov Reviewed-by: Alex Moshchuk Reviewed-by: Yoav Weiss Reviewed-by: Daniel Cheng Reviewed-by: Colin Blundell Cr-Commit-Position: refs/heads/master@{#894021} --- .../client_hints/client_hints_browsertest.cc | 2 +- .../sessions/session_service_unittest.cc | 2 + .../sessions/tab_restore_service_unittest.cc | 1 + ...pt_ch_with_lifetime.html.mock-http-headers | 2 +- ...with_short_lifetime.html.mock-http-headers | 2 +- ...ch_without_lifetime.html.mock-http-headers | 2 +- ...etime_img_localhost.html.mock-http-headers | 2 +- .../http_equiv_accept_ch_merge.html | 2 +- .../http_equiv_accept_ch_with_lifetime.html | 2 +- ...http_equiv_accept_ch_without_lifetime.html | 2 +- ...ept_ch_without_lifetime_img_localhost.html | 2 +- .../embedder_support/user_agent_utils.cc | 11 +++++- .../user_agent_utils_unittest.cc | 1 + content/browser/client_hints/client_hints.cc | 9 ++++- content/common/user_agent.cc | 22 ++++++++--- .../common/common_param_traits_macros.h | 1 + content/public/common/user_agent.h | 4 ++ .../browser/shell_content_browser_client.cc | 2 + services/network/public/cpp/client_hints.cc | 3 +- services/network/public/cpp/cors/cors.cc | 1 + .../public/mojom/web_client_hints_types.mojom | 1 + .../blink/common/client_hints/client_hints.cc | 37 ++++++++++--------- .../client_hints/client_hints_unittest.cc | 24 ++++++------ .../common/user_agent/user_agent_metadata.cc | 5 ++- .../user_agent_metadata_unittest.cc | 1 + .../user_agent/user_agent_mojom_traits.cc | 4 ++ .../common/user_agent/user_agent_metadata.h | 1 + .../user_agent/user_agent_mojom_traits.h | 4 ++ .../devtools_protocol/browser_protocol.pdl | 1 + .../permissions_policy_feature.mojom | 2 + .../user_agent/user_agent_metadata.mojom | 1 + .../mojom/web_feature/web_feature.mojom | 1 + .../core/loader/base_fetch_context.cc | 10 +++++ .../frame_client_hints_preferences_context.cc | 1 + .../permissions_policy_features.json5 | 5 +++ .../feature-policy-features-expected.txt | 1 + .../feature-policy-features-expected.txt | 1 + tools/metrics/histograms/enums.xml | 2 + 38 files changed, 128 insertions(+), 49 deletions(-) diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc index 57538110741ac3..0b549bb633bf12 100644 --- a/chrome/browser/client_hints/client_hints_browsertest.cc +++ b/chrome/browser/client_hints/client_hints_browsertest.cc @@ -61,7 +61,7 @@ namespace { -const unsigned expected_client_hints_number = 13u; +const unsigned expected_client_hints_number = 14u; const int32_t uma_histogram_max_value = 1471228928; // An interceptor that records count of fetches and client hint headers for diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index 5f3d8dfa2afbd1..a4556aa76f0fd8 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc @@ -891,6 +891,8 @@ TEST_F(SessionServiceTest, PersistUserAgentOverrides) { client_hints_override.full_version = "18.0.1025.45"; client_hints_override.platform = "Linux"; client_hints_override.architecture = "x86_64"; + // Doesn't have to match, just needs to be different than the default + client_hints_override.bitness = "8"; SerializedNavigationEntry nav1 = ContentTestHelper::CreateNavigation("http://google.com", "abc"); diff --git a/chrome/browser/sessions/tab_restore_service_unittest.cc b/chrome/browser/sessions/tab_restore_service_unittest.cc index 00745344cec71b..f84fc6f37fd4a1 100644 --- a/chrome/browser/sessions/tab_restore_service_unittest.cc +++ b/chrome/browser/sessions/tab_restore_service_unittest.cc @@ -93,6 +93,7 @@ class TabRestoreServiceImplTest : public ChromeRenderViewHostTestHarness { user_agent_override_.ua_metadata_override->full_version = "18.0.1025.45"; user_agent_override_.ua_metadata_override->platform = "Linux"; user_agent_override_.ua_metadata_override->architecture = "x86_64"; + user_agent_override_.ua_metadata_override->bitness = "32"; } ~TabRestoreServiceImplTest() override {} diff --git a/chrome/test/data/client_hints/accept_ch_with_lifetime.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_with_lifetime.html.mock-http-headers index 69d9b0bc49769d..3424cf598395d4 100644 --- a/chrome/test/data/client_hints/accept_ch_with_lifetime.html.mock-http-headers +++ b/chrome/test/data/client_hints/accept_ch_with_lifetime.html.mock-http-headers @@ -1,3 +1,3 @@ HTTP/1.1 200 OK -Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme +Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness Accept-CH-Lifetime: 3600 diff --git a/chrome/test/data/client_hints/accept_ch_with_short_lifetime.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_with_short_lifetime.html.mock-http-headers index c8988014fc8967..4b19b92e4899d2 100644 --- a/chrome/test/data/client_hints/accept_ch_with_short_lifetime.html.mock-http-headers +++ b/chrome/test/data/client_hints/accept_ch_with_short_lifetime.html.mock-http-headers @@ -1,3 +1,3 @@ HTTP/1.1 200 OK -Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme +Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness Accept-CH-Lifetime: 1 diff --git a/chrome/test/data/client_hints/accept_ch_without_lifetime.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_without_lifetime.html.mock-http-headers index 066a3ffc763d96..6024c526cce3ce 100644 --- a/chrome/test/data/client_hints/accept_ch_without_lifetime.html.mock-http-headers +++ b/chrome/test/data/client_hints/accept_ch_without_lifetime.html.mock-http-headers @@ -1,2 +1,2 @@ HTTP/1.1 200 OK -Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme +Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness diff --git a/chrome/test/data/client_hints/accept_ch_without_lifetime_img_localhost.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_without_lifetime_img_localhost.html.mock-http-headers index 066a3ffc763d96..6024c526cce3ce 100644 --- a/chrome/test/data/client_hints/accept_ch_without_lifetime_img_localhost.html.mock-http-headers +++ b/chrome/test/data/client_hints/accept_ch_without_lifetime_img_localhost.html.mock-http-headers @@ -1,2 +1,2 @@ HTTP/1.1 200 OK -Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme +Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness diff --git a/chrome/test/data/client_hints/http_equiv_accept_ch_merge.html b/chrome/test/data/client_hints/http_equiv_accept_ch_merge.html index 5ab981beae21c5..b67e9f715c79d6 100644 --- a/chrome/test/data/client_hints/http_equiv_accept_ch_merge.html +++ b/chrome/test/data/client_hints/http_equiv_accept_ch_merge.html @@ -2,7 +2,7 @@ - + diff --git a/chrome/test/data/client_hints/http_equiv_accept_ch_with_lifetime.html b/chrome/test/data/client_hints/http_equiv_accept_ch_with_lifetime.html index 70649c70f08203..011142daa04bb6 100644 --- a/chrome/test/data/client_hints/http_equiv_accept_ch_with_lifetime.html +++ b/chrome/test/data/client_hints/http_equiv_accept_ch_with_lifetime.html @@ -1,5 +1,5 @@ - + diff --git a/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime.html b/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime.html index 905af643237ddf..0f2494da6a9636 100644 --- a/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime.html +++ b/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime.html @@ -1,5 +1,5 @@ - + Empty file which uses link-rel to disable favicon fetches. The corresponding diff --git a/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime_img_localhost.html b/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime_img_localhost.html index fd6cda74265f03..4942f1cf828fb2 100644 --- a/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime_img_localhost.html +++ b/chrome/test/data/client_hints/http_equiv_accept_ch_without_lifetime_img_localhost.html @@ -1,5 +1,5 @@ - + Empty file which uses link-rel to disable favicon fetches. The corresponding diff --git a/components/embedder_support/user_agent_utils.cc b/components/embedder_support/user_agent_utils.cc index fb11c01bf9a3fc..777bbfd72c001b 100644 --- a/components/embedder_support/user_agent_utils.cc +++ b/components/embedder_support/user_agent_utils.cc @@ -142,7 +142,6 @@ blink::UserAgentMetadata GetUserAgentMetadata() { metadata.platform = GetPlatformForUAMetadata(); metadata.architecture = content::GetLowEntropyCpuArchitecture(); metadata.model = content::BuildModelInfo(); - metadata.mobile = false; #if defined(OS_ANDROID) metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -153,6 +152,11 @@ blink::UserAgentMetadata GetUserAgentMetadata() { base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); metadata.platform_version = base::StringPrintf("%d.%d.%d", major, minor, bugfix); + // These methods use the same information as the User-Agent string, but are + // "low entropy" in that they reduce the number of options for output to a + // set number. For more information, see the respective headers. + metadata.architecture = content::GetLowEntropyCpuArchitecture(); + metadata.bitness = content::GetLowEntropyCpuBitness(); return metadata; } @@ -171,9 +175,12 @@ void SetDesktopUserAgentOverride(content::WebContents* web_contents, spoofed_ua.ua_metadata_override->platform = "Linux"; spoofed_ua.ua_metadata_override->platform_version = std::string(); // match content::GetOSVersion(false) on Linux - spoofed_ua.ua_metadata_override->architecture = "x86"; spoofed_ua.ua_metadata_override->model = std::string(); spoofed_ua.ua_metadata_override->mobile = false; + // Match the above "CpuInfo" string, which is also the most common Linux + // CPU architecture and bitness.` + spoofed_ua.ua_metadata_override->architecture = "x86"; + spoofed_ua.ua_metadata_override->bitness = "64"; web_contents->SetUserAgentOverride(spoofed_ua, override_in_new_tabs); } diff --git a/components/embedder_support/user_agent_utils_unittest.cc b/components/embedder_support/user_agent_utils_unittest.cc index 0e2176314834d7..da6b21ec6c4355 100644 --- a/components/embedder_support/user_agent_utils_unittest.cc +++ b/components/embedder_support/user_agent_utils_unittest.cc @@ -305,6 +305,7 @@ TEST(UserAgentUtilsTest, UserAgentMetadata) { #endif EXPECT_EQ(metadata.architecture, content::GetLowEntropyCpuArchitecture()); EXPECT_EQ(metadata.model, content::BuildModelInfo()); + EXPECT_EQ(metadata.bitness, content::GetLowEntropyCpuBitness()); } TEST(UserAgentUtilsTest, GenerateBrandVersionList) { diff --git a/content/browser/client_hints/client_hints.cc b/content/browser/client_hints/client_hints.cc index cc87b3bfc37d4a..a46d524340563d 100644 --- a/content/browser/client_hints/client_hints.cc +++ b/content/browser/client_hints/client_hints.cc @@ -556,6 +556,11 @@ void UpdateNavigationRequestClientUaHeadersImpl( AddUAHeader(headers, network::mojom::WebClientHintsType::kUAModel, SerializeHeaderString(ua_metadata->model)); } + if (ShouldAddClientHint(data, + network::mojom::WebClientHintsType::kUABitness)) { + AddUAHeader(headers, network::mojom::WebClientHintsType::kUABitness, + SerializeHeaderString(ua_metadata->bitness)); + } } else if (call_type == ClientUaHeaderCallType::kAfterCreated) { RemoveClientHintHeader(network::mojom::WebClientHintsType::kUA, headers); RemoveClientHintHeader(network::mojom::WebClientHintsType::kUAMobile, @@ -570,6 +575,8 @@ void UpdateNavigationRequestClientUaHeadersImpl( network::mojom::WebClientHintsType::kUAPlatformVersion, headers); RemoveClientHintHeader(network::mojom::WebClientHintsType::kUAModel, headers); + RemoveClientHintHeader(network::mojom::WebClientHintsType::kUABitness, + headers); } } @@ -678,7 +685,7 @@ void AddRequestClientHintsHeaders( // 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::kPrefersColorScheme == + network::mojom::WebClientHintsType::kUABitness == network::mojom::WebClientHintsType::kMaxValue, "Consider adding client hint request headers from the browser process"); diff --git a/content/common/user_agent.cc b/content/common/user_agent.cc index 7a30520850e0b3..b3e400cf99b07d 100644 --- a/content/common/user_agent.cc +++ b/content/common/user_agent.cc @@ -6,6 +6,7 @@ #include +#include "base/containers/contains.h" #include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -125,11 +126,7 @@ std::string GetLowEntropyCpuArchitecture() { return "arm"; } #elif defined(OS_POSIX) && !defined(OS_ANDROID) - // This extra cpu_info_str variable is required to make sure the compiler - // doesn't optimize the copy away and have the StringPiece point at the - // internal std::string, resulting in a memory violation. - std::string cpu_info_str = BuildCpuInfo(); - base::StringPiece cpu_info = cpu_info_str; + std::string cpu_info = BuildCpuInfo(); if (base::StartsWith(cpu_info, "arm") || base::StartsWith(cpu_info, "aarch")) { return "arm"; @@ -142,6 +139,21 @@ std::string GetLowEntropyCpuArchitecture() { return std::string(); } +std::string GetLowEntropyCpuBitness() { +#if defined(OS_WIN) + return (base::win::OSInfo::GetInstance()->GetArchitecture() == + base::win::OSInfo::X86_ARCHITECTURE) + ? "32" + : "64"; +#elif defined(OS_MAC) + return "64"; +#elif defined(OS_POSIX) && !defined(OS_ANDROID) + return base::Contains(BuildCpuInfo(), "64") ? "64" : "32"; +#else + return std::string(); +#endif +} + std::string GetOSVersion(IncludeAndroidBuildNumber include_android_build_number, IncludeAndroidModel include_android_model) { std::string os_version; diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h index 922c00f90ab3c3..70667bbd1a18de 100644 --- a/content/public/common/common_param_traits_macros.h +++ b/content/public/common/common_param_traits_macros.h @@ -88,6 +88,7 @@ IPC_STRUCT_TRAITS_BEGIN(blink::UserAgentMetadata) IPC_STRUCT_TRAITS_MEMBER(architecture) IPC_STRUCT_TRAITS_MEMBER(model) IPC_STRUCT_TRAITS_MEMBER(mobile) + IPC_STRUCT_TRAITS_MEMBER(bitness) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(blink::UserAgentOverride) diff --git a/content/public/common/user_agent.h b/content/public/common/user_agent.h index fd9008613d1492..77cef8b69ebde1 100644 --- a/content/public/common/user_agent.h +++ b/content/public/common/user_agent.h @@ -47,6 +47,10 @@ CONTENT_EXPORT std::string BuildCpuInfo(); // most common cases. CONTENT_EXPORT std::string GetLowEntropyCpuArchitecture(); +// Takes the cpu info (see BuildCpuInfo()) and extracts the CPU bitness for +// most common cases. +CONTENT_EXPORT std::string GetLowEntropyCpuBitness(); + // Builds a User-agent compatible string that describes the OS and CPU type. // On Android, the string will only include the build number and model if // relevant enums indicate they should be included. diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 51e315bd567616..4f004ea997e7d4 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc @@ -220,6 +220,8 @@ blink::UserAgentMetadata GetShellUserAgentMetadata() { metadata.architecture = BuildCpuInfo(); metadata.model = BuildModelInfo(); + metadata.bitness = GetLowEntropyCpuBitness(); + return metadata; } diff --git a/services/network/public/cpp/client_hints.cc b/services/network/public/cpp/client_hints.cc index 9113846e644937..25a543a0815e70 100644 --- a/services/network/public/cpp/client_hints.cc +++ b/services/network/public/cpp/client_hints.cc @@ -33,7 +33,8 @@ const char* const kClientHintsNameMapping[] = {"device-memory", "sec-ch-ua-mobile", "sec-ch-ua-full-version", "sec-ch-ua-platform-version", - "sec-ch-prefers-color-scheme"}; + "sec-ch-prefers-color-scheme", + "sec-ch-ua-bitness"}; const size_t kClientHintsMappingsCount = base::size(kClientHintsNameMapping); diff --git a/services/network/public/cpp/cors/cors.cc b/services/network/public/cpp/cors/cors.cc index 2e960432f19cc2..a1835cda1fb5de 100644 --- a/services/network/public/cpp/cors/cors.cc +++ b/services/network/public/cpp/cors/cors.cc @@ -466,6 +466,7 @@ bool IsCorsSafelistedHeader(const std::string& name, const std::string& value) { // // https://tomayac.github.io/user-preference-media-features-headers/#sec-ch-prefers-color-scheme "sec-ch-prefers-color-scheme", + "sec-ch-ua-bitness", }; if (std::find(std::begin(safe_names), std::end(safe_names), lower_name) == std::end(safe_names)) diff --git a/services/network/public/mojom/web_client_hints_types.mojom b/services/network/public/mojom/web_client_hints_types.mojom index 54916d96bb853c..889b235e1a9cac 100644 --- a/services/network/public/mojom/web_client_hints_types.mojom +++ b/services/network/public/mojom/web_client_hints_types.mojom @@ -32,6 +32,7 @@ enum WebClientHintsType { kUAFullVersion = 13, kUAPlatformVersion = 14, kPrefersColorScheme = 15, + kUABitness = 16, // Warning: Before adding a new client hint, read the warning at the top. }; diff --git a/third_party/blink/common/client_hints/client_hints.cc b/third_party/blink/common/client_hints/client_hints.cc index 4eefbeaef02891..1610d6110cdf1a 100644 --- a/third_party/blink/common/client_hints/client_hints.cc +++ b/third_party/blink/common/client_hints/client_hints.cc @@ -19,24 +19,23 @@ namespace blink { -const char* const kClientHintsHeaderMapping[] = { - "device-memory", - "dpr", - "width", - "viewport-width", - "rtt", - "downlink", - "ect", - "sec-ch-lang", - "sec-ch-ua", - "sec-ch-ua-arch", - "sec-ch-ua-platform", - "sec-ch-ua-model", - "sec-ch-ua-mobile", - "sec-ch-ua-full-version", - "sec-ch-ua-platform-version", - "sec-ch-prefers-color-scheme", -}; +const char* const kClientHintsHeaderMapping[] = {"device-memory", + "dpr", + "width", + "viewport-width", + "rtt", + "downlink", + "ect", + "sec-ch-lang", + "sec-ch-ua", + "sec-ch-ua-arch", + "sec-ch-ua-platform", + "sec-ch-ua-model", + "sec-ch-ua-mobile", + "sec-ch-ua-full-version", + "sec-ch-ua-platform-version", + "sec-ch-prefers-color-scheme", + "sec-ch-ua-bitness"}; const unsigned kClientHintsNumberOfLegacyHints = 4; @@ -60,6 +59,7 @@ const mojom::PermissionsPolicyFeature kClientHintsPermissionsPolicyMapping[] = { mojom::PermissionsPolicyFeature::kClientHintUAFullVersion, mojom::PermissionsPolicyFeature::kClientHintUAPlatformVersion, mojom::PermissionsPolicyFeature::kClientHintPrefersColorScheme, + mojom::PermissionsPolicyFeature::kClientHintUABitness, }; const size_t kClientHintsMappingsCount = base::size(kClientHintsHeaderMapping); @@ -117,6 +117,7 @@ absl::optional> FilterAcceptCH( case network::mojom::WebClientHintsType::kUAModel: case network::mojom::WebClientHintsType::kUAMobile: case network::mojom::WebClientHintsType::kUAFullVersion: + case network::mojom::WebClientHintsType::kUABitness: if (permit_ua_hints) result.push_back(hint); break; diff --git a/third_party/blink/common/client_hints/client_hints_unittest.cc b/third_party/blink/common/client_hints/client_hints_unittest.cc index f32cf38839a0f0..aa010f5f75086f 100644 --- a/third_party/blink/common/client_hints/client_hints_unittest.cc +++ b/third_party/blink/common/client_hints/client_hints_unittest.cc @@ -127,11 +127,11 @@ TEST(ClientHintsTest, FindClientHintsToRemoveLegacy) { std::vector removed_headers; FindClientHintsToRemove(nullptr, GURL(), &removed_headers); EXPECT_THAT(removed_headers, - UnorderedElementsAre("rtt", "downlink", "ect", "sec-ch-lang", - "sec-ch-ua-arch", "sec-ch-ua-platform", - "sec-ch-ua-model", "sec-ch-ua-full-version", - "sec-ch-ua-platform-version", - "sec-ch-prefers-color-scheme")); + UnorderedElementsAre( + "rtt", "downlink", "ect", "sec-ch-lang", "sec-ch-ua-arch", + "sec-ch-ua-platform", "sec-ch-ua-model", + "sec-ch-ua-full-version", "sec-ch-ua-platform-version", + "sec-ch-prefers-color-scheme", "sec-ch-ua-bitness")); } // Checks that the removed header list includes legacy headers but not the @@ -142,12 +142,12 @@ TEST(ClientHintsTest, FindClientHintsToRemoveNoLegacy) { features::kAllowClientHintsToThirdParty); std::vector removed_headers; FindClientHintsToRemove(nullptr, GURL(), &removed_headers); - EXPECT_THAT( - removed_headers, - UnorderedElementsAre( - "device-memory", "dpr", "width", "viewport-width", "rtt", "downlink", - "ect", "sec-ch-lang", "sec-ch-ua-arch", "sec-ch-ua-platform", - "sec-ch-ua-model", "sec-ch-ua-full-version", - "sec-ch-ua-platform-version", "sec-ch-prefers-color-scheme")); + EXPECT_THAT(removed_headers, + UnorderedElementsAre( + "device-memory", "dpr", "width", "viewport-width", "rtt", + "downlink", "ect", "sec-ch-lang", "sec-ch-ua-arch", + "sec-ch-ua-platform", "sec-ch-ua-model", + "sec-ch-ua-full-version", "sec-ch-ua-platform-version", + "sec-ch-prefers-color-scheme", "sec-ch-ua-bitness")); } } // namespace blink diff --git a/third_party/blink/common/user_agent/user_agent_metadata.cc b/third_party/blink/common/user_agent/user_agent_metadata.cc index f4fcbcdc54c37d..466f6556175617 100644 --- a/third_party/blink/common/user_agent/user_agent_metadata.cc +++ b/third_party/blink/common/user_agent/user_agent_metadata.cc @@ -61,6 +61,7 @@ absl::optional UserAgentMetadata::Marshal( out.WriteString(in->architecture); out.WriteString(in->model); out.WriteBool(in->mobile); + out.WriteString(in->bitness); return std::string(reinterpret_cast(out.data()), out.size()); } @@ -102,6 +103,8 @@ absl::optional UserAgentMetadata::Demarshal( return absl::nullopt; if (!in.ReadBool(&out.mobile)) return absl::nullopt; + if (!in.ReadString(&out.bitness)) + return absl::nullopt; return absl::make_optional(std::move(out)); } @@ -114,7 +117,7 @@ bool operator==(const UserAgentMetadata& a, const UserAgentMetadata& b) { a.full_version == b.full_version && a.platform == b.platform && a.platform_version == b.platform_version && a.architecture == b.architecture && a.model == b.model && - a.mobile == b.mobile; + a.mobile == b.mobile && a.bitness == b.bitness; } bool operator==(const UserAgentOverride& a, const UserAgentOverride& b) { diff --git a/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc b/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc index 4669b655e82412..80b8e63dff3de8 100644 --- a/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc +++ b/third_party/blink/common/user_agent/user_agent_metadata_unittest.cc @@ -24,6 +24,7 @@ blink::UserAgentMetadata MakeToEncode() { to_encode.architecture = "Z80"; to_encode.model = "unofficial"; to_encode.mobile = false; + to_encode.bitness = "8"; return to_encode; } diff --git a/third_party/blink/common/user_agent/user_agent_mojom_traits.cc b/third_party/blink/common/user_agent/user_agent_mojom_traits.cc index a490f9db0898a8..ed2ebbeeaa6016 100644 --- a/third_party/blink/common/user_agent/user_agent_mojom_traits.cc +++ b/third_party/blink/common/user_agent/user_agent_mojom_traits.cc @@ -53,6 +53,10 @@ bool StructTraitsmodel = string; out->mobile = data.mobile(); + if (!data.ReadBitness(&string)) + return false; + out->bitness = string; + return true; } diff --git a/third_party/blink/public/common/user_agent/user_agent_metadata.h b/third_party/blink/public/common/user_agent/user_agent_metadata.h index 4b5baa5bed5de2..945581761a5be4 100644 --- a/third_party/blink/public/common/user_agent/user_agent_metadata.h +++ b/third_party/blink/public/common/user_agent/user_agent_metadata.h @@ -47,6 +47,7 @@ struct BLINK_COMMON_EXPORT UserAgentMetadata { std::string architecture; std::string model; bool mobile = false; + std::string bitness; }; // Used when customizing the sent User-Agent and Sec-CH-UA-* for diff --git a/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h b/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h index ec09bc7834e0b7..f9bbd2c83d9955 100644 --- a/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h +++ b/third_party/blink/public/common/user_agent/user_agent_mojom_traits.h @@ -63,6 +63,10 @@ struct BLINK_COMMON_EXPORT StructTraitsfull_version)); } + + if (ShouldSendClientHint( + ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin, + network::mojom::blink::WebClientHintsType::kUABitness, + hints_preferences)) { + request.SetHttpHeaderField( + blink::kClientHintsHeaderMapping[static_cast( + network::mojom::blink::WebClientHintsType::kUABitness)], + SerializeHeaderString(ua->bitness)); + } } if (ShouldSendClientHint( diff --git a/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc b/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc index 5beaae9c70509b..32c0c16dfda342 100644 --- a/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc +++ b/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc @@ -33,6 +33,7 @@ static constexpr WebFeature kWebFeatureMapping[] = { WebFeature::kClientHintsUAFullVersion, WebFeature::kClientHintsUAPlatformVersion, WebFeature::kClientHintsPrefersColorScheme, + WebFeature::kClientHintsUABitness, }; static_assert(static_cast(network::mojom::WebClientHintsType::kMaxValue) + diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 index 66327a81dca498..d10f4bdc2a4747 100644 --- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 +++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 @@ -95,6 +95,11 @@ permissions_policy_name: "ch-ua-arch", depends_on: ["FeaturePolicyForClientHints"], }, + { + name: "ClientHintUABitness", + permissions_policy_name: "ch-ua-bitness", + depends_on: ["FeaturePolicyForClientHints"], + }, { name: "ClientHintUAPlatform", permissions_policy_name: "ch-ua-platform", diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt index ab87e91fcc6782..9236c7d7d4d75c 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt @@ -13,6 +13,7 @@ ch-prefers-color-scheme ch-rtt ch-ua ch-ua-arch +ch-ua-bitness ch-ua-full-version ch-ua-mobile ch-ua-model diff --git a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt index 2abc7f4b16a80c..66852c59dfc0a0 100644 --- a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt @@ -15,6 +15,7 @@ ch-prefers-color-scheme ch-rtt ch-ua ch-ua-arch +ch-ua-bitness ch-ua-full-version ch-ua-mobile ch-ua-model diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 6020a71a8309db..b70161dd61adfe 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml @@ -32981,6 +32981,7 @@ Called by update_use_counter_feature_enum.py.--> + @@ -33087,6 +33088,7 @@ Called by update_permissions_policy_enum.py.--> +