Commit be775e1c authored by Aaron Tagliaboschi's avatar Aaron Tagliaboschi Committed by Commit Bot

Implement `Sec-CH-UA-Mobile`

Mobile is a boolean client hint that informs whether a "mobile" or
"desktop" user experience should be supplied.

Relevant changes to the spec can be found here:
https://github.com/WICG/ua-client-hints/pull/8
That was manually added via this commit:
https://github.com/WICG/ua-client-hints/commit/db6fab2569b78666c40e84e4d0458dbdf59d336b

Bug: 928669
Change-Id: Ia983cfa516c28b6a747b270abcc44e71ed39e1b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1829793
Commit-Queue: Aaron Tagliaboschi <aarontag@chromium.org>
Reviewed-by: default avatarYoav Weiss <yoavweiss@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarTakashi Toyoshima <toyoshim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#723037}
parent d53b5a93
......@@ -1115,6 +1115,13 @@ blink::UserAgentMetadata GetUserAgentMetadata() {
metadata.architecture = content::BuildCpuInfo();
metadata.model = content::BuildModelInfo();
// TODO(crbug.com/1031511): Integrate DevTools and "Request Desktop Site"
metadata.mobile = false;
#if defined(OS_ANDROID)
metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMobileUserAgent);
#endif
return metadata;
}
......
HTTP/1.1 200 OK
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model,mobile
Accept-CH-Lifetime: 3600
HTTP/1.1 200 OK
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model,mobile
Accept-CH-Lifetime: 1
HTTP/1.1 200 OK
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model,mobile
HTTP/1.1 200 OK
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model
Accept-CH: dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model,mobile
<html>
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model">
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model,mobile">
<meta http-equiv="Accept-CH-Lifetime" content="3600">
<link rel="icon" href="data:;base64,=">
</html>
<html>
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model">
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model,mobile">
<link rel="icon" href="data:;base64,=">
<head></head>
Empty file which uses link-rel to disable favicon fetches. The corresponding
......
<html>
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model">
<meta http-equiv="Accept-CH" content="dpr,device-memory,viewport-width,rtt,downlink,ect,lang,ua,arch,platform,model,mobile">
<link rel="icon" href="data:;base64,=">
<head></head>
Empty file which uses link-rel to disable favicon fetches. The corresponding
......
......@@ -522,6 +522,14 @@ void AddNavigationRequestClientHintsHeaders(
AddUAHeader(headers, blink::mojom::WebClientHintsType::kUAModel,
ua.model);
}
if (ShouldAddClientHint(
web_client_hints, feature_policy, resource_origin,
blink::mojom::WebClientHintsType::kUAMobile,
blink::mojom::FeaturePolicyFeature::kClientHintUAMobile)) {
AddUAHeader(headers, blink::mojom::WebClientHintsType::kUAMobile,
ua.mobile ? "?1" : "?0");
}
}
// Static assert that triggers if a new client hint header is added. If a
......@@ -529,7 +537,7 @@ void AddNavigationRequestClientHintsHeaders(
// 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(
blink::mojom::WebClientHintsType::kUAModel ==
blink::mojom::WebClientHintsType::kUAMobile ==
blink::mojom::WebClientHintsType::kMaxValue,
"Consider adding client hint request headers from the browser process");
......
......@@ -465,6 +465,7 @@ bool IsCorsSafelistedHeader(
"sec-ch-ua-platform",
"sec-ch-ua-arch",
"sec-ch-ua-model",
"sec-ch-ua-mobile",
};
if (std::find(std::begin(safe_names), std::end(safe_names), lower_name) ==
std::end(safe_names))
......
......@@ -12,7 +12,7 @@ namespace blink {
const char* const kClientHintsNameMapping[] = {
"device-memory", "dpr", "width", "viewport-width", "rtt", "downlink",
"ect", "lang", "ua", "arch", "platform", "model",
};
"mobile"};
const char* const kClientHintsHeaderMapping[] = {
"device-memory",
......@@ -27,6 +27,7 @@ const char* const kClientHintsHeaderMapping[] = {
"sec-ch-ua-arch",
"sec-ch-ua-platform",
"sec-ch-ua-model",
"sec-ch-ua-mobile",
};
const size_t kClientHintsMappingsCount = base::size(kClientHintsNameMapping);
......
......@@ -407,6 +407,9 @@ const FeaturePolicy::FeatureList& FeaturePolicy::GetDefaultFeatureList() {
{mojom::FeaturePolicyFeature::kClientHintUAModel,
FeatureDefaultValue(FeaturePolicy::FeatureDefault::EnableForSelf,
mojom::PolicyValueType::kBool)},
{mojom::FeaturePolicyFeature::kClientHintUAMobile,
FeatureDefaultValue(FeaturePolicy::FeatureDefault::EnableForSelf,
mojom::PolicyValueType::kBool)},
{mojom::FeaturePolicyFeature::kClientHintViewportWidth,
FeatureDefaultValue(FeaturePolicy::FeatureDefault::EnableForSelf,
mojom::PolicyValueType::kBool)},
......
......@@ -18,6 +18,7 @@ struct BLINK_COMMON_EXPORT UserAgentMetadata {
std::string platform;
std::string architecture;
std::string model;
bool mobile = false;
};
} // namespace blink
......
......@@ -40,6 +40,10 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::UserAgentMetadataDataView,
return data.model;
}
static const bool& mobile(const ::blink::UserAgentMetadata& data) {
return data.mobile;
}
static bool Read(blink::mojom::UserAgentMetadataDataView data,
::blink::UserAgentMetadata* out);
};
......
......@@ -138,6 +138,9 @@ enum FeaturePolicyFeature {
// Controls use of Clipboard API.
kClipboard = 68,
//Additional Client Hint
kClientHintUAMobile = 69,
// Don't change assigned numbers of any item, and don't reuse removed slots.
// Add new features at the end of the enum.
// Also, run update_feature_policy_enum.py in
......
......@@ -11,4 +11,5 @@ struct UserAgentMetadata {
string platform;
string architecture;
string model;
bool mobile;
};
......@@ -28,6 +28,7 @@ enum WebClientHintsType {
kUAArch = 9,
kUAPlatform = 10,
kUAModel = 11,
kUAMobile = 12,
// Warning: Before adding a new client hint, read the warning at the top.
};
......@@ -2491,7 +2491,7 @@ enum WebFeature {
kNonWebbyMixedContent = 3113,
kV8SharedArrayBufferConstructed = 3114,
kScrollSnapCausesScrollOnInitialLayout = 3115,
kClientHintsUAMobile = 3116,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
// Also, run update_use_counter_feature_enum.py in
......
......@@ -93,6 +93,11 @@
feature_policy_name: "ch-ua-model",
depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintUAMobile",
feature_policy_name: "ch-ua-mobile",
depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintViewportWidth",
feature_policy_name: "ch-viewport-width",
......
......@@ -753,6 +753,19 @@ void FrameFetchContext::AddClientHintsIfNecessary(
mojom::WebClientHintsType::kUAModel)],
AddQuotes(ua.model));
}
if ((can_always_send_hints ||
(RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled() &&
policy->IsFeatureEnabledForOrigin(
mojom::FeaturePolicyFeature::kClientHintUAMobile,
resource_origin))) &&
ShouldSendClientHint(mojom::WebClientHintsType::kUAMobile,
hints_preferences, enabled_hints)) {
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kUAMobile)],
ua.mobile ? "?1" : "?0");
}
}
void FrameFetchContext::PopulateResourceRequest(
......
......@@ -28,6 +28,7 @@ static constexpr WebFeature kWebFeatureMapping[] = {
WebFeature::kClientHintsUAArch,
WebFeature::kClientHintsUAPlatform,
WebFeature::kClientHintsUAModel,
WebFeature::kClientHintsUAMobile,
};
static_assert(static_cast<int>(mojom::WebClientHintsType::kMaxValue) + 1 ==
......
......@@ -68,6 +68,11 @@ void ParseAcceptChHeader(const String& header_value,
mojom::WebClientHintsType::kUAModel,
enabled_hints.IsEnabled(mojom::WebClientHintsType::kUAModel) &&
RuntimeEnabledFeatures::UserAgentClientHintEnabled());
enabled_hints.SetIsEnabled(
mojom::WebClientHintsType::kUAMobile,
enabled_hints.IsEnabled(mojom::WebClientHintsType::kUAMobile) &&
RuntimeEnabledFeatures::UserAgentClientHintEnabled());
}
} // namespace
......
......@@ -38,6 +38,9 @@ promise_test(t => {
assert_in_array(r.headers.get("ect-received"), ["slow-2g", "2g",
"3g", "4g"], 'ect-received is unexpected');
assert_true(r.headers.has("mobile-received"));
assert_in_array(r.headers.get("mobile-received"), ["?0", "?1"], 'mobile is unexpected');
});
}, "Accept-CH header test");
......@@ -53,6 +56,7 @@ promise_test(t => {
assert_false(r.headers.has("rtt-received"), "rtt-received");
assert_false(r.headers.has("downlink-received"), "downlink-received");
assert_false(r.headers.has("ect-received"), "ect-received");
assert_false(r.headers.has("mobile-received"), "mobile-received");
});
}, "Cross-Origin Accept-CH header test");
......
Accept-CH: device-memory, dpr, viewport-width, rtt, downlink, ect, lang
Feature-Policy: ch-device-memory *; ch-dpr 'none'; ch-viewport-width 'self'; ch-lang 'none'
Accept-CH: device-memory, dpr, viewport-width, rtt, downlink, ect, lang, mobile
Feature-Policy: ch-device-memory *; ch-dpr 'none'; ch-viewport-width 'self'; ch-lang 'none'; ch-mobile
......@@ -22,3 +22,5 @@ def main(request, response):
response.headers.set("ect-received", request.headers.get("ect"))
if "Sec-CH-Lang" in request.headers:
response.headers.set("lang-received", request.headers.get("Sec-CH-Lang"))
if "sec-ch-ua-mobile" in request.headers:
response.headers.set("mobile-received", request.headers.get("sec-ch-ua-mobile"))
......@@ -13,6 +13,7 @@ ch-lang
ch-rtt
ch-ua
ch-ua-arch
ch-ua-mobile
ch-ua-model
ch-ua-platform
ch-viewport-width
......
......@@ -25672,6 +25672,7 @@ Called by update_net_error_codes.py.-->
<int value="3113" label="NonWebbyMixedContent"/>
<int value="3114" label="V8SharedArrayBufferConstructed"/>
<int value="3115" label="ScrollSnapCausesScrollOnInitialLayout"/>
<int value="3116" label="ClientHintsUAMobile"/>
</enum>
<enum name="FeaturePolicyAllowlistType">
......@@ -25760,6 +25761,7 @@ Called by update_net_error_codes.py.-->
<int value="66" label="WebXr"/>
<int value="67" label="PublicKeyCredentials"/>
<int value="68" label="Clipboard"/>
<int value="69" label="ClientHintUAMobile"/>
</enum>
<enum name="FeaturePolicyImageCompressionFormat">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment