Commit 5dcc99ca authored by Maks Orlovich's avatar Maks Orlovich Committed by Commit Bot

[client hints] Send sec-ch-ua-mobile by default

This is basically Aaron Tagliaboschi's:
https://chromium-review.googlesource.com/c/chromium/src/+/2012902
just with a bit of additional updated of tests.

See https://github.com/WICG/ua-client-hints/issues/15 for rationale.

Change-Id: I6562cf1a78ceb4eff18baf793cb89143782f9b7b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2047410
Commit-Queue: Maksim Orlovich <morlovich@chromium.org>
Reviewed-by: default avatarYoav Weiss <yoavweiss@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#741152}
parent afcb4156
...@@ -498,6 +498,10 @@ void AddNavigationRequestClientHintsHeaders( ...@@ -498,6 +498,10 @@ void AddNavigationRequestClientHintsHeaders(
version.empty() ? ua.brand version.empty() ? ua.brand
: base::StringPrintf("%s %s", ua.brand.c_str(), : base::StringPrintf("%s %s", ua.brand.c_str(),
version.c_str())); version.c_str()));
// The `Sec-CH-UA-Mobile client hint was also deemed "low entropy" and can
// safely be sent with every request.
AddUAHeader(headers, blink::mojom::WebClientHintsType::kUAMobile,
ua.mobile ? "?1" : "?0");
if (ShouldAddClientHint( if (ShouldAddClientHint(
web_client_hints, feature_policy, resource_origin, web_client_hints, feature_policy, resource_origin,
...@@ -522,14 +526,6 @@ void AddNavigationRequestClientHintsHeaders( ...@@ -522,14 +526,6 @@ void AddNavigationRequestClientHintsHeaders(
AddUAHeader(headers, blink::mojom::WebClientHintsType::kUAModel, AddUAHeader(headers, blink::mojom::WebClientHintsType::kUAModel,
ua.model); 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 // Static assert that triggers if a new client hint header is added. If a
......
...@@ -554,6 +554,15 @@ void FrameFetchContext::AddClientHintsIfNecessary( ...@@ -554,6 +554,15 @@ void FrameFetchContext::AddClientHintsIfNecessary(
blink::kClientHintsHeaderMapping[static_cast<size_t>( blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kUA)], mojom::WebClientHintsType::kUA)],
AddQuotes(result.ToString().Ascii())); AddQuotes(result.ToString().Ascii()));
// We also send Sec-CH-UA-Mobile to all hints. It is a one-bit header
// identifying if the browser has opted for a "mobile" experience
// Formatted using the "sh-boolean" format from:
// https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html#boolean
request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kUAMobile)],
ua.mobile ? "?1" : "?0");
} }
// If the frame is detached, then don't send any hints other than UA. // If the frame is detached, then don't send any hints other than UA.
...@@ -755,19 +764,6 @@ void FrameFetchContext::AddClientHintsIfNecessary( ...@@ -755,19 +764,6 @@ void FrameFetchContext::AddClientHintsIfNecessary(
mojom::WebClientHintsType::kUAModel)], mojom::WebClientHintsType::kUAModel)],
AddQuotes(ua.model)); AddQuotes(ua.model));
} }
if ((can_always_send_hints ||
(RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled() &&
policy->IsFeatureEnabledForOrigin(
mojom::blink::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( void FrameFetchContext::PopulateResourceRequest(
......
...@@ -56,7 +56,6 @@ promise_test(t => { ...@@ -56,7 +56,6 @@ promise_test(t => {
assert_false(r.headers.has("rtt-received"), "rtt-received"); assert_false(r.headers.has("rtt-received"), "rtt-received");
assert_false(r.headers.has("downlink-received"), "downlink-received"); assert_false(r.headers.has("downlink-received"), "downlink-received");
assert_false(r.headers.has("ect-received"), "ect-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"); }, "Cross-Origin Accept-CH header test");
......
This is a testharness.js-based test. This is a testharness.js-based test.
PASS initialize global state PASS initialize global state
FAIL event.request has the expected headers for same-origin GET. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for same-origin GET. lengths differ, expected array ["accept"] length 1, got ["accept", "sec-ch-ua", "user-agent"] length 3" FAIL event.request has the expected headers for same-origin GET. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for same-origin GET. lengths differ, expected array ["accept"] length 1, got ["accept", "sec-ch-ua", "sec-ch-ua-mobile", "user-agent"] length 4"
FAIL event.request has the expected headers for same-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for same-origin POST. lengths differ, expected array ["accept", "content-type"] length 2, got ["accept", "content-type", "sec-ch-ua", "user-agent"] length 4" FAIL event.request has the expected headers for same-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for same-origin POST. lengths differ, expected array ["accept", "content-type"] length 2, got ["accept", "content-type", "sec-ch-ua", "sec-ch-ua-mobile", "user-agent"] length 5"
FAIL event.request has the expected headers for cross-origin GET. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for cross-origin GET. lengths differ, expected array ["accept"] length 1, got ["accept", "sec-ch-ua", "user-agent"] length 3" FAIL event.request has the expected headers for cross-origin GET. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for cross-origin GET. lengths differ, expected array ["accept"] length 1, got ["accept", "sec-ch-ua", "sec-ch-ua-mobile", "user-agent"] length 4"
FAIL event.request has the expected headers for cross-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for cross-origin POST. lengths differ, expected array ["accept", "content-type"] length 2, got ["accept", "content-type", "sec-ch-ua", "user-agent"] length 4" FAIL event.request has the expected headers for cross-origin POST. promise_test: Unhandled rejection with value: object "Error: assert_array_equals: event.request has the expected headers for cross-origin POST. lengths differ, expected array ["accept", "content-type"] length 2, got ["accept", "content-type", "sec-ch-ua", "sec-ch-ua-mobile", "user-agent"] length 5"
PASS FetchEvent#request.body contains XHR request data (string) PASS FetchEvent#request.body contains XHR request data (string)
PASS FetchEvent#request.body contains XHR request data (blob) PASS FetchEvent#request.body contains XHR request data (blob)
PASS FetchEvent#request.method is set to XHR method PASS FetchEvent#request.method is set to XHR method
......
...@@ -15,6 +15,7 @@ HTTP_CONNECTION = keep-alive ...@@ -15,6 +15,7 @@ HTTP_CONNECTION = keep-alive
HTTP_HOST = localhost:8080 HTTP_HOST = localhost:8080
HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-get.html HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-get.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = iframe HTTP_SEC_FETCH_DEST = iframe
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = cross-site HTTP_SEC_FETCH_SITE = cross-site
......
...@@ -16,6 +16,7 @@ HTTP_CONNECTION = keep-alive ...@@ -16,6 +16,7 @@ HTTP_CONNECTION = keep-alive
HTTP_HOST = localhost:8080 HTTP_HOST = localhost:8080
HTTP_ORIGIN = null HTTP_ORIGIN = null
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = iframe HTTP_SEC_FETCH_DEST = iframe
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = cross-site HTTP_SEC_FETCH_SITE = cross-site
......
...@@ -17,6 +17,7 @@ HTTP_HOST = localhost:8080 ...@@ -17,6 +17,7 @@ HTTP_HOST = localhost:8080
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-post.html HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-post.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = iframe HTTP_SEC_FETCH_DEST = iframe
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = cross-site HTTP_SEC_FETCH_SITE = cross-site
......
...@@ -17,6 +17,7 @@ HTTP_HOST = localhost:8080 ...@@ -17,6 +17,7 @@ HTTP_HOST = localhost:8080
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/navigation/form-with-enctype-targets-cross-site-frame.html HTTP_REFERER = http://127.0.0.1:8000/navigation/form-with-enctype-targets-cross-site-frame.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = iframe HTTP_SEC_FETCH_DEST = iframe
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = cross-site HTTP_SEC_FETCH_SITE = cross-site
......
...@@ -13,6 +13,7 @@ HTTP_HOST = 127.0.0.1:8000 ...@@ -13,6 +13,7 @@ HTTP_HOST = 127.0.0.1:8000
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -18,6 +18,7 @@ HTTP_HOST = 127.0.0.1:8000 ...@@ -18,6 +18,7 @@ HTTP_HOST = 127.0.0.1:8000
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = iframe HTTP_SEC_FETCH_DEST = iframe
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -17,6 +17,7 @@ HTTP_HOST = 127.0.0.1:8000 ...@@ -17,6 +17,7 @@ HTTP_HOST = 127.0.0.1:8000
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/navigation/post-frames-goback1.html HTTP_REFERER = http://127.0.0.1:8000/navigation/post-frames-goback1.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = iframe HTTP_SEC_FETCH_DEST = iframe
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -13,6 +13,7 @@ HTTP_HOST = 127.0.0.1:8000 ...@@ -13,6 +13,7 @@ HTTP_HOST = 127.0.0.1:8000
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -21,6 +21,7 @@ HTTP_HOST = 127.0.0.1:8000 ...@@ -21,6 +21,7 @@ HTTP_HOST = 127.0.0.1:8000
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html HTTP_REFERER = http://127.0.0.1:8000/navigation/resources/page-that-posts.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = iframe HTTP_SEC_FETCH_DEST = iframe
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive ...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive
HTTP_HOST = 127.0.0.1:8000 HTTP_HOST = 127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-leak-path-on-redirect.html HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-leak-path-on-redirect.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -12,6 +12,7 @@ HTTP_HOST = 127.0.0.1:8000 ...@@ -12,6 +12,7 @@ HTTP_HOST = 127.0.0.1:8000
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-allowed.html HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-allowed.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive ...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive
HTTP_HOST = 127.0.0.1:8000 HTTP_HOST = 127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-allowed-with-redirect.html HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-allowed-with-redirect.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -12,6 +12,7 @@ HTTP_HOST = 127.0.0.1:8000 ...@@ -12,6 +12,7 @@ HTTP_HOST = 127.0.0.1:8000
HTTP_ORIGIN = http://127.0.0.1:8000 HTTP_ORIGIN = http://127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-default-ignored.html HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-default-ignored.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive ...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive
HTTP_HOST = 127.0.0.1:8000 HTTP_HOST = 127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect.html HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -10,6 +10,7 @@ HTTP_CONNECTION = keep-alive ...@@ -10,6 +10,7 @@ HTTP_CONNECTION = keep-alive
HTTP_HOST = 127.0.0.1:8000 HTTP_HOST = 127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-get-allowed.html HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-get-allowed.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive ...@@ -9,6 +9,7 @@ HTTP_CONNECTION = keep-alive
HTTP_HOST = 127.0.0.1:8000 HTTP_HOST = 127.0.0.1:8000
HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-with-redirect.html HTTP_REFERER = http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-with-redirect.html
HTTP_SEC_CH_UA = content_shell 99 HTTP_SEC_CH_UA = content_shell 99
HTTP_SEC_CH_UA_MOBILE = ?0
HTTP_SEC_FETCH_DEST = document HTTP_SEC_FETCH_DEST = document
HTTP_SEC_FETCH_MODE = navigate HTTP_SEC_FETCH_MODE = navigate
HTTP_SEC_FETCH_SITE = same-origin HTTP_SEC_FETCH_SITE = same-origin
......
...@@ -31,7 +31,8 @@ promise_test(function(t) { ...@@ -31,7 +31,8 @@ promise_test(function(t) {
header_names.sort(); header_names.sort();
assert_array_equals( assert_array_equals(
header_names, header_names,
["accept", "sec-ch-ua", "upgrade-insecure-requests", "user-agent"], ["accept", "sec-ch-ua", "sec-ch-ua-mobile",
"upgrade-insecure-requests", "user-agent"],
'event.request has the expected headers.'); 'event.request has the expected headers.');
return service_worker_unregister_and_done(t, scope); return service_worker_unregister_and_done(t, scope);
......
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