[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 <aarontag@chromium.org> Reviewed-by: Andrey Kosyakov <caseq@chromium.org> Reviewed-by: Alex Moshchuk <alexmos@chromium.org> Reviewed-by: Yoav Weiss <yoavweiss@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Colin Blundell <blundell@chromium.org> Cr-Commit-Position: refs/heads/master@{#894021}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
a7194e8769
commit
1649e103a6
chrome
browser
client_hints
sessions
test
data
client_hints
accept_ch_with_lifetime.html.mock-http-headersaccept_ch_with_short_lifetime.html.mock-http-headersaccept_ch_without_lifetime.html.mock-http-headersaccept_ch_without_lifetime_img_localhost.html.mock-http-headershttp_equiv_accept_ch_merge.htmlhttp_equiv_accept_ch_with_lifetime.htmlhttp_equiv_accept_ch_without_lifetime.htmlhttp_equiv_accept_ch_without_lifetime_img_localhost.html
components/embedder_support
content
browser
client_hints
common
public
shell
services/network/public
third_party/blink
common
client_hints
user_agent
public
common
devtools_protocol
mojom
permissions_policy
user_agent
web_feature
renderer
core
loader
permissions_policy
web_tests
virtual
stable
webexposed
webexposed
tools/metrics/histograms
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const unsigned expected_client_hints_number = 13u;
|
const unsigned expected_client_hints_number = 14u;
|
||||||
const int32_t uma_histogram_max_value = 1471228928;
|
const int32_t uma_histogram_max_value = 1471228928;
|
||||||
|
|
||||||
// An interceptor that records count of fetches and client hint headers for
|
// An interceptor that records count of fetches and client hint headers for
|
||||||
|
@ -891,6 +891,8 @@ TEST_F(SessionServiceTest, PersistUserAgentOverrides) {
|
|||||||
client_hints_override.full_version = "18.0.1025.45";
|
client_hints_override.full_version = "18.0.1025.45";
|
||||||
client_hints_override.platform = "Linux";
|
client_hints_override.platform = "Linux";
|
||||||
client_hints_override.architecture = "x86_64";
|
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 =
|
SerializedNavigationEntry nav1 =
|
||||||
ContentTestHelper::CreateNavigation("http://google.com", "abc");
|
ContentTestHelper::CreateNavigation("http://google.com", "abc");
|
||||||
|
@ -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->full_version = "18.0.1025.45";
|
||||||
user_agent_override_.ua_metadata_override->platform = "Linux";
|
user_agent_override_.ua_metadata_override->platform = "Linux";
|
||||||
user_agent_override_.ua_metadata_override->architecture = "x86_64";
|
user_agent_override_.ua_metadata_override->architecture = "x86_64";
|
||||||
|
user_agent_override_.ua_metadata_override->bitness = "32";
|
||||||
}
|
}
|
||||||
|
|
||||||
~TabRestoreServiceImplTest() override {}
|
~TabRestoreServiceImplTest() override {}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
HTTP/1.1 200 OK
|
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
|
Accept-CH-Lifetime: 3600
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
HTTP/1.1 200 OK
|
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
|
Accept-CH-Lifetime: 1
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
HTTP/1.1 200 OK
|
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
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
HTTP/1.1 200 OK
|
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
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<!-- This is split in two since data from header may round trip quickly
|
<!-- This is split in two since data from header may round trip quickly
|
||||||
enough from browser to be used, so this makes sure we actually merge -->
|
enough from browser to be used, so this makes sure we actually merge -->
|
||||||
<meta http-equiv="Accept-CH" content="lang,sec-ch-ua-arch,sec-ch-ua-platform">
|
<meta http-equiv="Accept-CH" content="lang,sec-ch-ua-arch,sec-ch-ua-platform">
|
||||||
<meta http-equiv="Accept-CH" content="sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme">
|
<meta http-equiv="Accept-CH" content="sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness">
|
||||||
<link rel="icon" href="data:;base64,=">
|
<link rel="icon" href="data:;base64,=">
|
||||||
<!-- A subresource! -->
|
<!-- A subresource! -->
|
||||||
<img src="non-existing-image.jpg"></img>
|
<img src="non-existing-image.jpg"></img>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<html>
|
<html>
|
||||||
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-model,sec-ch-ua-full-version">
|
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-ua-bitness">
|
||||||
<meta http-equiv="Accept-CH-Lifetime" content="3600">
|
<meta http-equiv="Accept-CH-Lifetime" content="3600">
|
||||||
<link rel="icon" href="data:;base64,=">
|
<link rel="icon" href="data:;base64,=">
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<html>
|
<html>
|
||||||
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-model,sec-ch-ua-full-version">
|
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-ua-bitness">
|
||||||
<link rel="icon" href="data:;base64,=">
|
<link rel="icon" href="data:;base64,=">
|
||||||
<head></head>
|
<head></head>
|
||||||
Empty file which uses link-rel to disable favicon fetches. The corresponding
|
Empty file which uses link-rel to disable favicon fetches. The corresponding
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<html>
|
<html>
|
||||||
<meta http-equiv="Accept-CH" content="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">
|
<meta http-equiv="Accept-CH" content="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">
|
||||||
<link rel="icon" href="data:;base64,=">
|
<link rel="icon" href="data:;base64,=">
|
||||||
<head></head>
|
<head></head>
|
||||||
Empty file which uses link-rel to disable favicon fetches. The corresponding
|
Empty file which uses link-rel to disable favicon fetches. The corresponding
|
||||||
|
@ -142,7 +142,6 @@ blink::UserAgentMetadata GetUserAgentMetadata() {
|
|||||||
metadata.platform = GetPlatformForUAMetadata();
|
metadata.platform = GetPlatformForUAMetadata();
|
||||||
metadata.architecture = content::GetLowEntropyCpuArchitecture();
|
metadata.architecture = content::GetLowEntropyCpuArchitecture();
|
||||||
metadata.model = content::BuildModelInfo();
|
metadata.model = content::BuildModelInfo();
|
||||||
|
|
||||||
metadata.mobile = false;
|
metadata.mobile = false;
|
||||||
#if defined(OS_ANDROID)
|
#if defined(OS_ANDROID)
|
||||||
metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch(
|
metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||||
@ -153,6 +152,11 @@ blink::UserAgentMetadata GetUserAgentMetadata() {
|
|||||||
base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
|
base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
|
||||||
metadata.platform_version =
|
metadata.platform_version =
|
||||||
base::StringPrintf("%d.%d.%d", major, minor, bugfix);
|
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;
|
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 = "Linux";
|
||||||
spoofed_ua.ua_metadata_override->platform_version =
|
spoofed_ua.ua_metadata_override->platform_version =
|
||||||
std::string(); // match content::GetOSVersion(false) on Linux
|
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->model = std::string();
|
||||||
spoofed_ua.ua_metadata_override->mobile = false;
|
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);
|
web_contents->SetUserAgentOverride(spoofed_ua, override_in_new_tabs);
|
||||||
}
|
}
|
||||||
|
@ -305,6 +305,7 @@ TEST(UserAgentUtilsTest, UserAgentMetadata) {
|
|||||||
#endif
|
#endif
|
||||||
EXPECT_EQ(metadata.architecture, content::GetLowEntropyCpuArchitecture());
|
EXPECT_EQ(metadata.architecture, content::GetLowEntropyCpuArchitecture());
|
||||||
EXPECT_EQ(metadata.model, content::BuildModelInfo());
|
EXPECT_EQ(metadata.model, content::BuildModelInfo());
|
||||||
|
EXPECT_EQ(metadata.bitness, content::GetLowEntropyCpuBitness());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UserAgentUtilsTest, GenerateBrandVersionList) {
|
TEST(UserAgentUtilsTest, GenerateBrandVersionList) {
|
||||||
|
@ -556,6 +556,11 @@ void UpdateNavigationRequestClientUaHeadersImpl(
|
|||||||
AddUAHeader(headers, network::mojom::WebClientHintsType::kUAModel,
|
AddUAHeader(headers, network::mojom::WebClientHintsType::kUAModel,
|
||||||
SerializeHeaderString(ua_metadata->model));
|
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) {
|
} else if (call_type == ClientUaHeaderCallType::kAfterCreated) {
|
||||||
RemoveClientHintHeader(network::mojom::WebClientHintsType::kUA, headers);
|
RemoveClientHintHeader(network::mojom::WebClientHintsType::kUA, headers);
|
||||||
RemoveClientHintHeader(network::mojom::WebClientHintsType::kUAMobile,
|
RemoveClientHintHeader(network::mojom::WebClientHintsType::kUAMobile,
|
||||||
@ -570,6 +575,8 @@ void UpdateNavigationRequestClientUaHeadersImpl(
|
|||||||
network::mojom::WebClientHintsType::kUAPlatformVersion, headers);
|
network::mojom::WebClientHintsType::kUAPlatformVersion, headers);
|
||||||
RemoveClientHintHeader(network::mojom::WebClientHintsType::kUAModel,
|
RemoveClientHintHeader(network::mojom::WebClientHintsType::kUAModel,
|
||||||
headers);
|
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
|
// If possible, logic should be added above so that the request headers for
|
||||||
// the newly added client hint can be added to the request.
|
// the newly added client hint can be added to the request.
|
||||||
static_assert(
|
static_assert(
|
||||||
network::mojom::WebClientHintsType::kPrefersColorScheme ==
|
network::mojom::WebClientHintsType::kUABitness ==
|
||||||
network::mojom::WebClientHintsType::kMaxValue,
|
network::mojom::WebClientHintsType::kMaxValue,
|
||||||
"Consider adding client hint request headers from the browser process");
|
"Consider adding client hint request headers from the browser process");
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "base/containers/contains.h"
|
||||||
#include "base/strings/strcat.h"
|
#include "base/strings/strcat.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/strings/stringprintf.h"
|
#include "base/strings/stringprintf.h"
|
||||||
@ -125,11 +126,7 @@ std::string GetLowEntropyCpuArchitecture() {
|
|||||||
return "arm";
|
return "arm";
|
||||||
}
|
}
|
||||||
#elif defined(OS_POSIX) && !defined(OS_ANDROID)
|
#elif defined(OS_POSIX) && !defined(OS_ANDROID)
|
||||||
// This extra cpu_info_str variable is required to make sure the compiler
|
std::string cpu_info = BuildCpuInfo();
|
||||||
// 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;
|
|
||||||
if (base::StartsWith(cpu_info, "arm") ||
|
if (base::StartsWith(cpu_info, "arm") ||
|
||||||
base::StartsWith(cpu_info, "aarch")) {
|
base::StartsWith(cpu_info, "aarch")) {
|
||||||
return "arm";
|
return "arm";
|
||||||
@ -142,6 +139,21 @@ std::string GetLowEntropyCpuArchitecture() {
|
|||||||
return std::string();
|
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,
|
std::string GetOSVersion(IncludeAndroidBuildNumber include_android_build_number,
|
||||||
IncludeAndroidModel include_android_model) {
|
IncludeAndroidModel include_android_model) {
|
||||||
std::string os_version;
|
std::string os_version;
|
||||||
|
@ -88,6 +88,7 @@ IPC_STRUCT_TRAITS_BEGIN(blink::UserAgentMetadata)
|
|||||||
IPC_STRUCT_TRAITS_MEMBER(architecture)
|
IPC_STRUCT_TRAITS_MEMBER(architecture)
|
||||||
IPC_STRUCT_TRAITS_MEMBER(model)
|
IPC_STRUCT_TRAITS_MEMBER(model)
|
||||||
IPC_STRUCT_TRAITS_MEMBER(mobile)
|
IPC_STRUCT_TRAITS_MEMBER(mobile)
|
||||||
|
IPC_STRUCT_TRAITS_MEMBER(bitness)
|
||||||
IPC_STRUCT_TRAITS_END()
|
IPC_STRUCT_TRAITS_END()
|
||||||
|
|
||||||
IPC_STRUCT_TRAITS_BEGIN(blink::UserAgentOverride)
|
IPC_STRUCT_TRAITS_BEGIN(blink::UserAgentOverride)
|
||||||
|
@ -47,6 +47,10 @@ CONTENT_EXPORT std::string BuildCpuInfo();
|
|||||||
// most common cases.
|
// most common cases.
|
||||||
CONTENT_EXPORT std::string GetLowEntropyCpuArchitecture();
|
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.
|
// 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
|
// On Android, the string will only include the build number and model if
|
||||||
// relevant enums indicate they should be included.
|
// relevant enums indicate they should be included.
|
||||||
|
@ -220,6 +220,8 @@ blink::UserAgentMetadata GetShellUserAgentMetadata() {
|
|||||||
metadata.architecture = BuildCpuInfo();
|
metadata.architecture = BuildCpuInfo();
|
||||||
metadata.model = BuildModelInfo();
|
metadata.model = BuildModelInfo();
|
||||||
|
|
||||||
|
metadata.bitness = GetLowEntropyCpuBitness();
|
||||||
|
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ const char* const kClientHintsNameMapping[] = {"device-memory",
|
|||||||
"sec-ch-ua-mobile",
|
"sec-ch-ua-mobile",
|
||||||
"sec-ch-ua-full-version",
|
"sec-ch-ua-full-version",
|
||||||
"sec-ch-ua-platform-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);
|
const size_t kClientHintsMappingsCount = base::size(kClientHintsNameMapping);
|
||||||
|
|
||||||
|
@ -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
|
// https://tomayac.github.io/user-preference-media-features-headers/#sec-ch-prefers-color-scheme
|
||||||
"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) ==
|
if (std::find(std::begin(safe_names), std::end(safe_names), lower_name) ==
|
||||||
std::end(safe_names))
|
std::end(safe_names))
|
||||||
|
@ -32,6 +32,7 @@ enum WebClientHintsType {
|
|||||||
kUAFullVersion = 13,
|
kUAFullVersion = 13,
|
||||||
kUAPlatformVersion = 14,
|
kUAPlatformVersion = 14,
|
||||||
kPrefersColorScheme = 15,
|
kPrefersColorScheme = 15,
|
||||||
|
kUABitness = 16,
|
||||||
|
|
||||||
// Warning: Before adding a new client hint, read the warning at the top.
|
// Warning: Before adding a new client hint, read the warning at the top.
|
||||||
};
|
};
|
||||||
|
@ -19,24 +19,23 @@
|
|||||||
|
|
||||||
namespace blink {
|
namespace blink {
|
||||||
|
|
||||||
const char* const kClientHintsHeaderMapping[] = {
|
const char* const kClientHintsHeaderMapping[] = {"device-memory",
|
||||||
"device-memory",
|
"dpr",
|
||||||
"dpr",
|
"width",
|
||||||
"width",
|
"viewport-width",
|
||||||
"viewport-width",
|
"rtt",
|
||||||
"rtt",
|
"downlink",
|
||||||
"downlink",
|
"ect",
|
||||||
"ect",
|
"sec-ch-lang",
|
||||||
"sec-ch-lang",
|
"sec-ch-ua",
|
||||||
"sec-ch-ua",
|
"sec-ch-ua-arch",
|
||||||
"sec-ch-ua-arch",
|
"sec-ch-ua-platform",
|
||||||
"sec-ch-ua-platform",
|
"sec-ch-ua-model",
|
||||||
"sec-ch-ua-model",
|
"sec-ch-ua-mobile",
|
||||||
"sec-ch-ua-mobile",
|
"sec-ch-ua-full-version",
|
||||||
"sec-ch-ua-full-version",
|
"sec-ch-ua-platform-version",
|
||||||
"sec-ch-ua-platform-version",
|
"sec-ch-prefers-color-scheme",
|
||||||
"sec-ch-prefers-color-scheme",
|
"sec-ch-ua-bitness"};
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned kClientHintsNumberOfLegacyHints = 4;
|
const unsigned kClientHintsNumberOfLegacyHints = 4;
|
||||||
|
|
||||||
@ -60,6 +59,7 @@ const mojom::PermissionsPolicyFeature kClientHintsPermissionsPolicyMapping[] = {
|
|||||||
mojom::PermissionsPolicyFeature::kClientHintUAFullVersion,
|
mojom::PermissionsPolicyFeature::kClientHintUAFullVersion,
|
||||||
mojom::PermissionsPolicyFeature::kClientHintUAPlatformVersion,
|
mojom::PermissionsPolicyFeature::kClientHintUAPlatformVersion,
|
||||||
mojom::PermissionsPolicyFeature::kClientHintPrefersColorScheme,
|
mojom::PermissionsPolicyFeature::kClientHintPrefersColorScheme,
|
||||||
|
mojom::PermissionsPolicyFeature::kClientHintUABitness,
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t kClientHintsMappingsCount = base::size(kClientHintsHeaderMapping);
|
const size_t kClientHintsMappingsCount = base::size(kClientHintsHeaderMapping);
|
||||||
@ -117,6 +117,7 @@ absl::optional<std::vector<network::mojom::WebClientHintsType>> FilterAcceptCH(
|
|||||||
case network::mojom::WebClientHintsType::kUAModel:
|
case network::mojom::WebClientHintsType::kUAModel:
|
||||||
case network::mojom::WebClientHintsType::kUAMobile:
|
case network::mojom::WebClientHintsType::kUAMobile:
|
||||||
case network::mojom::WebClientHintsType::kUAFullVersion:
|
case network::mojom::WebClientHintsType::kUAFullVersion:
|
||||||
|
case network::mojom::WebClientHintsType::kUABitness:
|
||||||
if (permit_ua_hints)
|
if (permit_ua_hints)
|
||||||
result.push_back(hint);
|
result.push_back(hint);
|
||||||
break;
|
break;
|
||||||
|
@ -127,11 +127,11 @@ TEST(ClientHintsTest, FindClientHintsToRemoveLegacy) {
|
|||||||
std::vector<std::string> removed_headers;
|
std::vector<std::string> removed_headers;
|
||||||
FindClientHintsToRemove(nullptr, GURL(), &removed_headers);
|
FindClientHintsToRemove(nullptr, GURL(), &removed_headers);
|
||||||
EXPECT_THAT(removed_headers,
|
EXPECT_THAT(removed_headers,
|
||||||
UnorderedElementsAre("rtt", "downlink", "ect", "sec-ch-lang",
|
UnorderedElementsAre(
|
||||||
"sec-ch-ua-arch", "sec-ch-ua-platform",
|
"rtt", "downlink", "ect", "sec-ch-lang", "sec-ch-ua-arch",
|
||||||
"sec-ch-ua-model", "sec-ch-ua-full-version",
|
"sec-ch-ua-platform", "sec-ch-ua-model",
|
||||||
"sec-ch-ua-platform-version",
|
"sec-ch-ua-full-version", "sec-ch-ua-platform-version",
|
||||||
"sec-ch-prefers-color-scheme"));
|
"sec-ch-prefers-color-scheme", "sec-ch-ua-bitness"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that the removed header list includes legacy headers but not the
|
// Checks that the removed header list includes legacy headers but not the
|
||||||
@ -142,12 +142,12 @@ TEST(ClientHintsTest, FindClientHintsToRemoveNoLegacy) {
|
|||||||
features::kAllowClientHintsToThirdParty);
|
features::kAllowClientHintsToThirdParty);
|
||||||
std::vector<std::string> removed_headers;
|
std::vector<std::string> removed_headers;
|
||||||
FindClientHintsToRemove(nullptr, GURL(), &removed_headers);
|
FindClientHintsToRemove(nullptr, GURL(), &removed_headers);
|
||||||
EXPECT_THAT(
|
EXPECT_THAT(removed_headers,
|
||||||
removed_headers,
|
UnorderedElementsAre(
|
||||||
UnorderedElementsAre(
|
"device-memory", "dpr", "width", "viewport-width", "rtt",
|
||||||
"device-memory", "dpr", "width", "viewport-width", "rtt", "downlink",
|
"downlink", "ect", "sec-ch-lang", "sec-ch-ua-arch",
|
||||||
"ect", "sec-ch-lang", "sec-ch-ua-arch", "sec-ch-ua-platform",
|
"sec-ch-ua-platform", "sec-ch-ua-model",
|
||||||
"sec-ch-ua-model", "sec-ch-ua-full-version",
|
"sec-ch-ua-full-version", "sec-ch-ua-platform-version",
|
||||||
"sec-ch-ua-platform-version", "sec-ch-prefers-color-scheme"));
|
"sec-ch-prefers-color-scheme", "sec-ch-ua-bitness"));
|
||||||
}
|
}
|
||||||
} // namespace blink
|
} // namespace blink
|
||||||
|
@ -61,6 +61,7 @@ absl::optional<std::string> UserAgentMetadata::Marshal(
|
|||||||
out.WriteString(in->architecture);
|
out.WriteString(in->architecture);
|
||||||
out.WriteString(in->model);
|
out.WriteString(in->model);
|
||||||
out.WriteBool(in->mobile);
|
out.WriteBool(in->mobile);
|
||||||
|
out.WriteString(in->bitness);
|
||||||
return std::string(reinterpret_cast<const char*>(out.data()), out.size());
|
return std::string(reinterpret_cast<const char*>(out.data()), out.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +103,8 @@ absl::optional<UserAgentMetadata> UserAgentMetadata::Demarshal(
|
|||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
if (!in.ReadBool(&out.mobile))
|
if (!in.ReadBool(&out.mobile))
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
|
if (!in.ReadString(&out.bitness))
|
||||||
|
return absl::nullopt;
|
||||||
return absl::make_optional(std::move(out));
|
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.full_version == b.full_version && a.platform == b.platform &&
|
||||||
a.platform_version == b.platform_version &&
|
a.platform_version == b.platform_version &&
|
||||||
a.architecture == b.architecture && a.model == b.model &&
|
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) {
|
bool operator==(const UserAgentOverride& a, const UserAgentOverride& b) {
|
||||||
|
@ -24,6 +24,7 @@ blink::UserAgentMetadata MakeToEncode() {
|
|||||||
to_encode.architecture = "Z80";
|
to_encode.architecture = "Z80";
|
||||||
to_encode.model = "unofficial";
|
to_encode.model = "unofficial";
|
||||||
to_encode.mobile = false;
|
to_encode.mobile = false;
|
||||||
|
to_encode.bitness = "8";
|
||||||
return to_encode;
|
return to_encode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,10 @@ bool StructTraits<blink::mojom::UserAgentMetadataDataView,
|
|||||||
out->model = string;
|
out->model = string;
|
||||||
out->mobile = data.mobile();
|
out->mobile = data.mobile();
|
||||||
|
|
||||||
|
if (!data.ReadBitness(&string))
|
||||||
|
return false;
|
||||||
|
out->bitness = string;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ struct BLINK_COMMON_EXPORT UserAgentMetadata {
|
|||||||
std::string architecture;
|
std::string architecture;
|
||||||
std::string model;
|
std::string model;
|
||||||
bool mobile = false;
|
bool mobile = false;
|
||||||
|
std::string bitness;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used when customizing the sent User-Agent and Sec-CH-UA-* for
|
// Used when customizing the sent User-Agent and Sec-CH-UA-* for
|
||||||
|
@ -63,6 +63,10 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::UserAgentMetadataDataView,
|
|||||||
return data.mobile;
|
return data.mobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const std::string& bitness(const ::blink::UserAgentMetadata& data) {
|
||||||
|
return data.bitness;
|
||||||
|
}
|
||||||
|
|
||||||
static bool Read(blink::mojom::UserAgentMetadataDataView data,
|
static bool Read(blink::mojom::UserAgentMetadataDataView data,
|
||||||
::blink::UserAgentMetadata* out);
|
::blink::UserAgentMetadata* out);
|
||||||
};
|
};
|
||||||
|
@ -6546,6 +6546,7 @@ domain Page
|
|||||||
ch-rtt
|
ch-rtt
|
||||||
ch-ua
|
ch-ua
|
||||||
ch-ua-arch
|
ch-ua-arch
|
||||||
|
ch-ua-bitness
|
||||||
ch-ua-platform
|
ch-ua-platform
|
||||||
ch-ua-model
|
ch-ua-model
|
||||||
ch-ua-mobile
|
ch-ua-mobile
|
||||||
|
@ -144,6 +144,8 @@ enum PermissionsPolicyFeature {
|
|||||||
// Controls use of Multi-Screen Window Placement API.
|
// Controls use of Multi-Screen Window Placement API.
|
||||||
kWindowPlacement = 86,
|
kWindowPlacement = 86,
|
||||||
|
|
||||||
|
kClientHintUABitness = 87,
|
||||||
|
|
||||||
// Don't change assigned numbers of any item, and don't reuse removed slots.
|
// Don't change assigned numbers of any item, and don't reuse removed slots.
|
||||||
// Add new features at the end of the enum.
|
// Add new features at the end of the enum.
|
||||||
// Also, run update_permissions_policy_enum.py in
|
// Also, run update_permissions_policy_enum.py in
|
||||||
|
@ -20,6 +20,7 @@ struct UserAgentMetadata {
|
|||||||
string architecture;
|
string architecture;
|
||||||
string model;
|
string model;
|
||||||
bool mobile;
|
bool mobile;
|
||||||
|
string bitness;
|
||||||
};
|
};
|
||||||
|
|
||||||
// See UserAgentOverride in
|
// See UserAgentOverride in
|
||||||
|
@ -3257,6 +3257,7 @@ enum WebFeature {
|
|||||||
kExplicitPointerCaptureClickTargetDiff = 3942,
|
kExplicitPointerCaptureClickTargetDiff = 3942,
|
||||||
kControlledNonBlobURLWorkerWillBeUncontrolled = 3943,
|
kControlledNonBlobURLWorkerWillBeUncontrolled = 3943,
|
||||||
kMediaMetaThemeColor = 3944,
|
kMediaMetaThemeColor = 3944,
|
||||||
|
kClientHintsUABitness = 3945,
|
||||||
|
|
||||||
// Add new features immediately above this line. Don't change assigned
|
// Add new features immediately above this line. Don't change assigned
|
||||||
// numbers of any item, and don't reuse removed slots.
|
// numbers of any item, and don't reuse removed slots.
|
||||||
|
@ -334,6 +334,16 @@ void BaseFetchContext::AddClientHintsIfNecessary(
|
|||||||
network::mojom::blink::WebClientHintsType::kUAFullVersion)],
|
network::mojom::blink::WebClientHintsType::kUAFullVersion)],
|
||||||
SerializeHeaderString(ua->full_version));
|
SerializeHeaderString(ua->full_version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ShouldSendClientHint(
|
||||||
|
ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin,
|
||||||
|
network::mojom::blink::WebClientHintsType::kUABitness,
|
||||||
|
hints_preferences)) {
|
||||||
|
request.SetHttpHeaderField(
|
||||||
|
blink::kClientHintsHeaderMapping[static_cast<size_t>(
|
||||||
|
network::mojom::blink::WebClientHintsType::kUABitness)],
|
||||||
|
SerializeHeaderString(ua->bitness));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldSendClientHint(
|
if (ShouldSendClientHint(
|
||||||
|
@ -33,6 +33,7 @@ static constexpr WebFeature kWebFeatureMapping[] = {
|
|||||||
WebFeature::kClientHintsUAFullVersion,
|
WebFeature::kClientHintsUAFullVersion,
|
||||||
WebFeature::kClientHintsUAPlatformVersion,
|
WebFeature::kClientHintsUAPlatformVersion,
|
||||||
WebFeature::kClientHintsPrefersColorScheme,
|
WebFeature::kClientHintsPrefersColorScheme,
|
||||||
|
WebFeature::kClientHintsUABitness,
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) +
|
static_assert(static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) +
|
||||||
|
@ -95,6 +95,11 @@
|
|||||||
permissions_policy_name: "ch-ua-arch",
|
permissions_policy_name: "ch-ua-arch",
|
||||||
depends_on: ["FeaturePolicyForClientHints"],
|
depends_on: ["FeaturePolicyForClientHints"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ClientHintUABitness",
|
||||||
|
permissions_policy_name: "ch-ua-bitness",
|
||||||
|
depends_on: ["FeaturePolicyForClientHints"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ClientHintUAPlatform",
|
name: "ClientHintUAPlatform",
|
||||||
permissions_policy_name: "ch-ua-platform",
|
permissions_policy_name: "ch-ua-platform",
|
||||||
|
1
third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt
vendored
1
third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt
vendored
@ -13,6 +13,7 @@ ch-prefers-color-scheme
|
|||||||
ch-rtt
|
ch-rtt
|
||||||
ch-ua
|
ch-ua
|
||||||
ch-ua-arch
|
ch-ua-arch
|
||||||
|
ch-ua-bitness
|
||||||
ch-ua-full-version
|
ch-ua-full-version
|
||||||
ch-ua-mobile
|
ch-ua-mobile
|
||||||
ch-ua-model
|
ch-ua-model
|
||||||
|
@ -15,6 +15,7 @@ ch-prefers-color-scheme
|
|||||||
ch-rtt
|
ch-rtt
|
||||||
ch-ua
|
ch-ua
|
||||||
ch-ua-arch
|
ch-ua-arch
|
||||||
|
ch-ua-bitness
|
||||||
ch-ua-full-version
|
ch-ua-full-version
|
||||||
ch-ua-mobile
|
ch-ua-mobile
|
||||||
ch-ua-model
|
ch-ua-model
|
||||||
|
@ -32981,6 +32981,7 @@ Called by update_use_counter_feature_enum.py.-->
|
|||||||
<int value="3942" label="ExplicitPointerCaptureClickTargetDiff"/>
|
<int value="3942" label="ExplicitPointerCaptureClickTargetDiff"/>
|
||||||
<int value="3943" label="ControlledNonBlobURLWorkerWillBeUncontrolled"/>
|
<int value="3943" label="ControlledNonBlobURLWorkerWillBeUncontrolled"/>
|
||||||
<int value="3944" label="MediaMetaThemeColor"/>
|
<int value="3944" label="MediaMetaThemeColor"/>
|
||||||
|
<int value="3945" label="ClientHintsUABitness"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<enum name="FeaturePolicyAllowlistType">
|
<enum name="FeaturePolicyAllowlistType">
|
||||||
@ -33087,6 +33088,7 @@ Called by update_permissions_policy_enum.py.-->
|
|||||||
<int value="84" label="DirectSockets"/>
|
<int value="84" label="DirectSockets"/>
|
||||||
<int value="85" label="ClientHintPrefersColorScheme"/>
|
<int value="85" label="ClientHintPrefersColorScheme"/>
|
||||||
<int value="86" label="WindowPlacement"/>
|
<int value="86" label="WindowPlacement"/>
|
||||||
|
<int value="87" label="ClientHintUABitness"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<enum name="FeaturePolicyImageCompressionFormat">
|
<enum name="FeaturePolicyImageCompressionFormat">
|
||||||
|
Reference in New Issue
Block a user