Reland "Add Sec-CH-UA-Reduced client hint header when Origin Trial token present"
This reverts commit f6370c35ee4f448247485c6e875d3c60679d0454.
Reason for revert: The original CL (crrev.com/c/3042810) started the EmbeddedTestServer on a specific port in the UaReducedOriginTrialBrowserTest, since the test used an Origin Trial token that is bound to a specific origin. This caused the test to fail on CI for linux-chromeos-chrome, due to being unable to start EmbeddedTestServer as the specific port was already in-use, and the original CL was reverted in crrev.com/c/3061119. This CL relands the original CL and fixes the problem by using URLLoaderInterceptor instead of EmbeddedTestServer in the UaReducedOriginTrialBrowserTest tests.
Original change's description:
> Revert "Add Sec-CH-UA-Reduced client hint header when Origin Trial token present"
>
> This reverts commit d9c057ea37355847f0c9530eada84aca335c96b4.
>
> Reason for revert: Browser tests is failing on linux-chromeos-chrome.
> See [1].
>
> [1] https://ci.chromium.org/ui/p/chrome/builders/ci/linux-chromeos-chrome/16242/overview
>
> Original change's description:
> > Add Sec-CH-UA-Reduced client hint header when Origin Trial token present
> >
> > In this CL, we add logic to parse and accept the Sec-CH-UA-Reduced
> > client hint in the Accept-CH header and and only send the
> > Sec-CH-UA-Reduced client hint only in the presence of a valid
> > UserAgentReduction Origin Trial token.
> >
> > If the Origin Trial token is present and valid, and the origin
> > contains Sec-CH-UA-Reduced in the Accept-CH cache, then on all
> > subsequent requests to the origin, the Sec-CH-UA-Reduced request
> > header will be set with a value of "?1" (sh-boolean). If the
> > Accept-CH cache does not contain Sec-CH-UA-Reduced, or the Origin
> > Trial token is not valid, then Sec-CH-UA-Reduced will not be sent
> > in the request headers.
> >
> > NB: A subsequent CL will change the User-Agent request header to
> > the reduced UA string if the Sec-CH-UA-Reduced header is sent.
> >
> > Chrome Platform Status: https://chromestatus.com/feature/5704553745874944
> > Design Doc: https://docs.google.com/document/d/1feIxK9S7oNgT2oGGebbxE9X0O-4wTKcsP_gRaY99tq4
> >
> > Bug: 1222742
> > Change-Id: If855d4bb393540d49de3be80aa9bc7c80f861c50
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3042810
> > Commit-Queue: Ali Beyad <[email protected]>
> > Reviewed-by: Aaron Tagliaboschi <[email protected]>
> > Reviewed-by: Robert Kroeger <[email protected]>
> > Reviewed-by: Mike West <[email protected]>
> > Cr-Commit-Position: refs/heads/master@{#906810}
>
> Bug: 1222742
> Change-Id: I0d8aab1d56d78f8323d4a3e3ed88b6eef370e1b9
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3061119
> Auto-Submit: Daniel Hosseinian <[email protected]>
> Commit-Queue: Rubber Stamper <[email protected]>
> Bot-Commit: Rubber Stamper <[email protected]>
> Owners-Override: Daniel Hosseinian <[email protected]>
> Cr-Commit-Position: refs/heads/master@{#906884}
Bug: 1222742
Change-Id: I3ed39697255116fe1f2ab5203331e8786e9d66a3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3064532
Commit-Queue: Ali Beyad <[email protected]>
Reviewed-by: Kinuko Yasuda <[email protected]>
Reviewed-by: Aaron Tagliaboschi <[email protected]>
Reviewed-by: Daniel Hosseinian <[email protected]>
Cr-Commit-Position: refs/heads/master@{#909169}
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index c44f7f87..5f3ef9fd 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -11,8 +11,10 @@
#include "base/containers/contains.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/run_loop.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
+#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
@@ -28,17 +30,22 @@
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/pref_names.h"
+#include "components/embedder_support/switches.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "net/dns/mock_host_resolver.h"
@@ -51,8 +58,11 @@
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
@@ -692,8 +702,10 @@
continue;
}
- // TODO(crbug.com/1226193): Remove this block when support for
- // `Sec-CH-UA-Reduced` has been added.
+ // Skip over the `Sec-CH-UA-Reduced` client hint because it is only added
+ // in the presence of a valid "UserAgentReduction" Origin Trial token.
+ // `Sec-CH-UA-Reduced` is tested via UaReducedOriginTrialBrowserTest
+ // below.
if (std::string(blink::kClientHintsHeaderMapping[i]) ==
"sec-ch-ua-reduced") {
continue;
@@ -2475,3 +2487,184 @@
ui_test_utils::NavigateToURL(browser(), test_url());
EXPECT_EQ(prefers_color_scheme_observed(), "dark");
}
+
+// Tests that the Sec-CH-UA-Reduced client hint is sent if and only if the
+// UserAgentReduction Origin Trial token is present and valid in the response
+// headers.
+//
+// The test Origin Trial token found in the test files was generated by running
+// (in tools/origin_trials):
+// generate_token.py https://127.0.0.1:44444 UserAgentReduction
+// --expire-timestamp=2000000000
+//
+// The Origin Trial token expires in 2033. Generate a new token by then, or
+// find a better way to re-generate a test trial token.
+class UaReducedOriginTrialBrowserTest : public InProcessBrowserTest {
+ public:
+ UaReducedOriginTrialBrowserTest() = default;
+
+ // The URL that was used to register for the Origin Trial token.
+ static constexpr const char kOriginUrl[] = "https://127.0.0.1:44444";
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // The public key for the default privatey key used by the
+ // tools/origin_trials/generate_token.py tool.
+ static constexpr char kOriginTrialTestPublicKey[] =
+ "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=";
+ command_line->AppendSwitchASCII(embedder_support::kOriginTrialPublicKey,
+ kOriginTrialTestPublicKey);
+ }
+
+ void SetUp() override {
+ std::unique_ptr<base::FeatureList> feature_list =
+ std::make_unique<base::FeatureList>();
+ feature_list->InitializeFromCommandLine("CriticalClientHint", "");
+ scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
+
+ InProcessBrowserTest::SetUp();
+ }
+
+ void SetUpOnMainThread() override {
+ InProcessBrowserTest::SetUpOnMainThread();
+
+ // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since
+ // the origin trial token in the response is associated with a fixed
+ // origin, whereas EmbeddedTestServer serves content on a random port.
+ url_loader_interceptor_ =
+ content::URLLoaderInterceptor::ServeFilesFromDirectoryAtOrigin(
+ "chrome/test/data/client_hints", GURL(kOriginUrl));
+ }
+
+ void TearDownOnMainThread() override {
+ url_loader_interceptor_.reset();
+ InProcessBrowserTest::TearDownOnMainThread();
+ }
+
+ GURL ua_reduced_with_valid_origin_trial_token_url() const {
+ return GURL(base::StrCat(
+ {kOriginUrl, "/accept_ch_ua_reduced_with_valid_origin_trial.html"}));
+ }
+
+ GURL ua_reduced_with_invalid_origin_trial_token_url() const {
+ return GURL(base::StrCat(
+ {kOriginUrl, "/accept_ch_ua_reduced_with_invalid_origin_trial.html"}));
+ }
+
+ GURL ua_reduced_with_no_origin_trial_token_url() const {
+ return GURL(base::StrCat(
+ {kOriginUrl, "/accept_ch_ua_reduced_with_no_origin_trial.html"}));
+ }
+
+ GURL ua_reduced_missing_with_valid_origin_trial_token_url() const {
+ return GURL(base::StrCat(
+ {kOriginUrl, "/accept_ch_ua_reduced_missing_valid_origin_trial.html"}));
+ }
+
+ GURL critical_ch_ua_reduced_with_valid_origin_trial_token_url() const {
+ return GURL(base::StrCat(
+ {kOriginUrl, "/critical_ch_ua_reduced_with_valid_origin_trial.html"}));
+ }
+
+ GURL critical_ch_ua_reduced_with_invalid_origin_trial_token_url() const {
+ return GURL(base::StrCat(
+ {kOriginUrl,
+ "/critical_ch_ua_reduced_with_invalid_origin_trial.html"}));
+ }
+
+ void NavigateAndCheckHeader(const GURL& url,
+ const bool ch_ua_reduced_expected) {
+ ui_test_utils::NavigateToURL(browser(), url);
+ base::RunLoop().RunUntilIdle();
+
+ std::string header_value;
+ const bool ch_ua_reduced =
+ url_loader_interceptor_->GetLastRequestHeaders().GetHeader(
+ "sec-ch-ua-reduced", &header_value);
+
+ EXPECT_EQ(ch_ua_reduced, ch_ua_reduced_expected);
+ if (ch_ua_reduced_expected) {
+ EXPECT_EQ(header_value, "?1");
+ }
+ }
+
+ void NavigateTwiceAndCheckHeader(const GURL& url,
+ const bool ch_ua_reduced_expected,
+ const bool critical_ch_ua_reduced_expected) {
+ // If Critical-CH is set, we expect Sec-CH-UA-Reduced in the first
+ // navigation request header. If Critical-CH is not set, we don't expect
+ // Sec-CH-UA-Reduced in the first navigation request.
+ NavigateAndCheckHeader(
+ url, critical_ch_ua_reduced_expected && ch_ua_reduced_expected);
+
+ // Regardless of the Critical-CH setting, we expect the Sec-CH-UA-Reduced
+ // client hint sent on the second request, if Sec-CH-UA-Reduced is set and
+ // the Origin Trial token is valid.
+ NavigateAndCheckHeader(url, ch_ua_reduced_expected);
+ }
+
+ private:
+ std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+constexpr const char UaReducedOriginTrialBrowserTest::kOriginUrl[];
+
+IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest,
+ AcceptChUaReducedWithValidOriginTrialToken) {
+ NavigateTwiceAndCheckHeader(ua_reduced_with_valid_origin_trial_token_url(),
+ /*ch_ua_reduced_expected=*/true,
+ /*critical_ch_ua_reduced_expected=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest,
+ AcceptChUaReducedWithInvalidOriginTrialToken) {
+ // The response contained Sec-CH-UA-Reduced in the Accept-CH header, but the
+ // origin trial token is invalid.
+ NavigateTwiceAndCheckHeader(ua_reduced_with_invalid_origin_trial_token_url(),
+ /*ch_ua_reduced_expected=*/false,
+ /*critical_ch_ua_reduced_expected=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest,
+ AcceptChUaReducedWithNoOriginTrialToken) {
+ // The response contained Sec-CH-UA-Reduced in the Accept-CH header, but the
+ // origin trial token is not present.
+ NavigateTwiceAndCheckHeader(ua_reduced_with_no_origin_trial_token_url(),
+ /*ch_ua_reduced_expected=*/false,
+ /*critical_ch_ua_reduced_expected=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest,
+ NoAcceptChUaReducedWithValidOriginTrialToken) {
+ // The response contained a valid Origin Trial token, but no Sec-CH-UA-Reduced
+ // in the Accept-CH header.
+ NavigateTwiceAndCheckHeader(
+ ua_reduced_missing_with_valid_origin_trial_token_url(),
+ /*ch_ua_reduced_expected=*/false,
+ /*critical_ch_ua_reduced_expected=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest,
+ CriticalChUaReducedWithValidOriginTrialToken) {
+ // The initial navigation also contains the Critical-CH header, so the
+ // Sec-CH-UA-Reduced header should be set after the first navigation.
+ NavigateTwiceAndCheckHeader(
+ critical_ch_ua_reduced_with_valid_origin_trial_token_url(),
+ /*ch_ua_reduced_expected=*/true,
+ /*critical_ch_ua_reduced_expected=*/true);
+}
+
+IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest,
+ CriticalChUaReducedWithInvalidOriginTrialToken) {
+ // The Origin Trial token is invalid, so the Critical-CH should not have
+ // resulted in the Sec-CH-UA-Reduced header being sent.
+ NavigateTwiceAndCheckHeader(
+ critical_ch_ua_reduced_with_invalid_origin_trial_token_url(),
+ /*ch_ua_reduced_expected=*/false,
+ /*critical_ch_ua_reduced_expected=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest,
+ ThirdPartyUaReducedWithValidOriginTrialToken) {
+ // TODO(crbug.com/1222742): Implement this test.
+}