blob: 3ea2395e082d10b2cfa020d89e4fe74d530fd275 [file] [log] [blame]
Tarun Bansal0b8b7afd2017-08-25 03:52:161// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Tarun Bansal62efba12018-05-04 22:58:355#include <cctype>
6
Mike West2fddeeb72019-02-15 11:29:487#include "base/base_switches.h"
Tarun Bansal229647bd002018-02-27 17:33:368#include "base/bind.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:169#include "base/command_line.h"
Tarun Bansalbef6d652018-10-02 18:41:0110#include "base/metrics/field_trial_param_associator.h"
Gabriel Charetteb71eec892017-09-14 22:52:5611#include "base/run_loop.h"
Tarun Bansal6bf54302017-10-02 07:39:1412#include "base/stl_util.h"
Mike Weste555be862019-02-20 16:17:3013#include "base/strings/string_util.h"
Callum May7d88ff3e2019-11-12 18:21:4614#include "base/synchronization/lock.h"
Devlin Cronin626d80c2018-06-01 01:08:3615#include "base/test/metrics/histogram_tester.h"
Tarun Bansal5c28afb2018-03-17 02:55:2016#include "build/build_config.h"
Mike Weste555be862019-02-20 16:17:3017#include "chrome/browser/chrome_content_browser_client.h"
Tarun Bansala61f0f62017-10-24 23:53:0518#include "chrome/browser/content_settings/cookie_settings_factory.h"
Tarun Bansal1965b042017-09-07 04:59:1919#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
Aaron Tagliaboschi8f3a28302020-06-24 03:08:2620#include "chrome/browser/policy/policy_test_utils.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1621#include "chrome/browser/profiles/profile.h"
Tarun Bansal1965b042017-09-07 04:59:1922#include "chrome/browser/ui/browser.h"
Maks Orlovich73f374d2020-04-02 12:46:1323#include "chrome/browser/ui/browser_commands.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1624#include "chrome/test/base/in_process_browser_test.h"
25#include "chrome/test/base/ui_test_utils.h"
Carlos Caballerob4283202020-08-10 14:40:4626#include "components/content_settings/browser/page_specific_content_settings.h"
Tarun Bansala61f0f62017-10-24 23:53:0527#include "components/content_settings/core/browser/cookie_settings.h"
Tarun Bansal1965b042017-09-07 04:59:1928#include "components/content_settings/core/browser/host_content_settings_map.h"
Tarun Bansala61f0f62017-10-24 23:53:0529#include "components/content_settings/core/common/pref_names.h"
John Abd-El-Malek161073c2020-06-12 20:40:2830#include "components/metrics/content/subprocess_metrics_provider.h"
Aaron Tagliaboschi8f3a28302020-06-24 03:08:2631#include "components/policy/core/common/policy_map.h"
32#include "components/policy/core/common/policy_pref_names.h"
33#include "components/policy/policy_constants.h"
Tarun Bansala61f0f62017-10-24 23:53:0534#include "components/prefs/pref_service.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1635#include "content/public/browser/browser_thread.h"
Maks Orlovich73f374d2020-04-02 12:46:1336#include "content/public/browser/navigation_entry.h"
Changwan Ryu434c3a32019-07-30 23:42:5837#include "content/public/browser/render_view_host.h"
Tarun Bansalbef6d652018-10-02 18:41:0138#include "content/public/common/content_features.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1639#include "content/public/common/content_switches.h"
Changwan Ryu434c3a32019-07-30 23:42:5840#include "content/public/common/web_preferences.h"
Peter Kasting919ce652020-05-07 10:22:3641#include "content/public/test/browser_test.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1642#include "content/public/test/browser_test_utils.h"
43#include "content/public/test/test_utils.h"
Tarun Bansal229647bd002018-02-27 17:33:3644#include "content/public/test/url_loader_interceptor.h"
45#include "net/dns/mock_host_resolver.h"
46#include "net/http/http_request_headers.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4747#include "net/nqe/effective_connection_type.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1648#include "net/test/embedded_test_server/embedded_test_server.h"
Tarun Bansal1965b042017-09-07 04:59:1949#include "net/test/embedded_test_server/http_request.h"
Tarun Bansal229647bd002018-02-27 17:33:3650#include "net/test/embedded_test_server/http_response.h"
Tarun Bansal74e189d2018-05-07 19:07:3551#include "services/network/public/cpp/cors/cors.h"
Tarun Bansalceab9592018-05-01 18:57:3552#include "services/network/public/cpp/features.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4753#include "services/network/public/cpp/network_switches.h"
Blink Reformata30d4232018-04-07 15:31:0654#include "third_party/blink/public/common/client_hints/client_hints.h"
Tarun Bansal229647bd002018-02-27 17:33:3655
56namespace {
57
Yoav Weissfd1d19f2020-05-05 09:23:0358const unsigned expected_client_hints_number = 12u;
Yoav Weiss76e1afb762020-05-14 19:28:1259const int32_t uma_histogram_max_value = 1471228928;
Yoav Weissd33bacb2020-03-12 06:42:2160
Tarun Bansal229647bd002018-02-27 17:33:3661// An interceptor that records count of fetches and client hint headers for
62// requests to https://foo.com/non-existing-image.jpg.
Jay Civelli1ff872d2018-03-09 21:52:1663class ThirdPartyURLLoaderInterceptor {
Tarun Bansal229647bd002018-02-27 17:33:3664 public:
Jay Civelli1ff872d2018-03-09 21:52:1665 explicit ThirdPartyURLLoaderInterceptor(const GURL intercepted_url)
66 : intercepted_url_(intercepted_url),
67 interceptor_(base::BindRepeating(
68 &ThirdPartyURLLoaderInterceptor::InterceptURLRequest,
69 base::Unretained(this))) {}
Tarun Bansal229647bd002018-02-27 17:33:3670
Jay Civelli1ff872d2018-03-09 21:52:1671 ~ThirdPartyURLLoaderInterceptor() = default;
Tarun Bansal229647bd002018-02-27 17:33:3672
73 size_t request_count_seen() const { return request_count_seen_; }
74
75 size_t client_hints_count_seen() const { return client_hints_count_seen_; }
76
77 private:
Jay Civelli1ff872d2018-03-09 21:52:1678 bool InterceptURLRequest(
79 content::URLLoaderInterceptor::RequestParams* params) {
80 if (params->url_request.url != intercepted_url_)
81 return false;
Tarun Bansal229647bd002018-02-27 17:33:3682
Jay Civelli1ff872d2018-03-09 21:52:1683 request_count_seen_++;
Mike West14c11102019-02-04 16:16:4784 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansalf9cf9892018-04-06 04:38:0185 if (params->url_request.headers.HasHeader(
86 blink::kClientHintsHeaderMapping[i])) {
87 client_hints_count_seen_++;
88 }
Tarun Bansal5c28afb2018-03-17 02:55:2089 }
Jay Civelli1ff872d2018-03-09 21:52:1690 return false;
91 }
Tarun Bansal229647bd002018-02-27 17:33:3692
Jay Civelli1ff872d2018-03-09 21:52:1693 GURL intercepted_url_;
94
95 size_t request_count_seen_ = 0u;
96
97 size_t client_hints_count_seen_ = 0u;
98
99 content::URLLoaderInterceptor interceptor_;
100
101 DISALLOW_COPY_AND_ASSIGN(ThirdPartyURLLoaderInterceptor);
Tarun Bansal229647bd002018-02-27 17:33:36102};
103
Tarun Bansal62efba12018-05-04 22:58:35104// Returns true only if |header_value| satisfies ABNF: 1*DIGIT [ "." 1*DIGIT ]
105bool IsSimilarToDoubleABNF(const std::string& header_value) {
106 if (header_value.empty())
107 return false;
108 char first_char = header_value.at(0);
109 if (!isdigit(first_char))
110 return false;
111
112 bool period_found = false;
113 bool digit_found_after_period = false;
114 for (char ch : header_value) {
115 if (isdigit(ch)) {
116 if (period_found) {
117 digit_found_after_period = true;
118 }
119 continue;
120 }
121 if (ch == '.') {
122 if (period_found)
123 return false;
124 period_found = true;
125 continue;
126 }
127 return false;
128 }
129 if (period_found)
130 return digit_found_after_period;
131 return true;
132}
133
134// Returns true only if |header_value| satisfies ABNF: 1*DIGIT
135bool IsSimilarToIntABNF(const std::string& header_value) {
136 if (header_value.empty())
137 return false;
138
139 for (char ch : header_value) {
140 if (!isdigit(ch))
141 return false;
142 }
143 return true;
144}
145
Tarun Bansal229647bd002018-02-27 17:33:36146} // namespace
Tarun Bansal0b8b7afd2017-08-25 03:52:16147
Aaron Tagliaboschi8f3a28302020-06-24 03:08:26148class ClientHintsBrowserTest : public policy::PolicyTest,
Tarun Bansal9a7051f2018-07-10 18:30:05149 public testing::WithParamInterface<bool> {
Tarun Bansal0b8b7afd2017-08-25 03:52:16150 public:
151 ClientHintsBrowserTest()
Mikel Astiz2de748d2019-11-16 10:39:36152 : http_server_(net::EmbeddedTestServer::TYPE_HTTP),
Tarun Bansal3b330b02017-11-09 19:03:14153 https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal345418632018-06-29 11:07:04154 https_cross_origin_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal229647bd002018-02-27 17:33:36155 expect_client_hints_on_main_frame_(false),
156 expect_client_hints_on_subresources_(false),
Mike West2fddeeb72019-02-15 11:29:48157 count_user_agent_hint_headers_seen_(0),
Maks Orlovich5dcc99c2020-02-13 19:07:46158 count_ua_mobile_client_hints_headers_seen_(0),
Tarun Bansal229647bd002018-02-27 17:33:36159 count_client_hints_headers_seen_(0),
160 request_interceptor_(nullptr) {
Tarun Bansal3b330b02017-11-09 19:03:14161 http_server_.ServeFilesFromSourceDirectory("chrome/test/data/client_hints");
Tarun Bansal0b8b7afd2017-08-25 03:52:16162 https_server_.ServeFilesFromSourceDirectory(
163 "chrome/test/data/client_hints");
Tarun Bansal345418632018-06-29 11:07:04164 https_cross_origin_server_.ServeFilesFromSourceDirectory(
165 "chrome/test/data/client_hints");
Tarun Bansal1965b042017-09-07 04:59:19166
Tarun Bansal3b330b02017-11-09 19:03:14167 http_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04168 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
169 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19170 https_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04171 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
172 base::Unretained(this)));
173 https_cross_origin_server_.RegisterRequestMonitor(
174 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
175 base::Unretained(this)));
Tarun Bansal293a7b6c2018-12-05 17:41:12176 https_cross_origin_server_.RegisterRequestHandler(
177 base::BindRepeating(&ClientHintsBrowserTest::RequestHandlerToRedirect,
178 base::Unretained(this)));
Tarun Bansal345418632018-06-29 11:07:04179 https_server_.RegisterRequestHandler(base::BindRepeating(
180 &ClientHintsBrowserTest::RequestHandlerToFetchCrossOriginIframe,
181 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19182
Tarun Bansal3b330b02017-11-09 19:03:14183 EXPECT_TRUE(http_server_.Start());
Tarun Bansal0b8b7afd2017-08-25 03:52:16184 EXPECT_TRUE(https_server_.Start());
Tarun Bansal345418632018-06-29 11:07:04185 EXPECT_TRUE(https_cross_origin_server_.Start());
186
187 EXPECT_NE(https_server_.base_url(), https_cross_origin_server_.base_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16188
Tarun Bansal3b330b02017-11-09 19:03:14189 accept_ch_with_lifetime_http_local_url_ =
190 http_server_.GetURL("/accept_ch_with_lifetime.html");
Tarun Bansal9a7051f2018-07-10 18:30:05191 http_equiv_accept_ch_with_lifetime_http_local_url_ =
192 http_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal3b330b02017-11-09 19:03:14193 EXPECT_TRUE(accept_ch_with_lifetime_http_local_url_.SchemeIsHTTPOrHTTPS());
194 EXPECT_FALSE(
195 accept_ch_with_lifetime_http_local_url_.SchemeIsCryptographic());
196
Tarun Bansal1965b042017-09-07 04:59:19197 accept_ch_with_lifetime_url_ =
198 https_server_.GetURL("/accept_ch_with_lifetime.html");
Tarun Bansal73502f92019-04-16 21:21:19199 accept_ch_with_short_lifetime_url_ =
200 https_server_.GetURL("/accept_ch_with_short_lifetime.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16201
Tarun Bansal1965b042017-09-07 04:59:19202 accept_ch_without_lifetime_url_ =
203 https_server_.GetURL("/accept_ch_without_lifetime.html");
204 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
205 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal9a7051f2018-07-10 18:30:05206 http_equiv_accept_ch_without_lifetime_url_ =
207 https_server_.GetURL("/http_equiv_accept_ch_without_lifetime.html");
Tarun Bansal1965b042017-09-07 04:59:19208
209 without_accept_ch_without_lifetime_url_ =
210 https_server_.GetURL("/without_accept_ch_without_lifetime.html");
211 EXPECT_TRUE(without_accept_ch_without_lifetime_url_.SchemeIsHTTPOrHTTPS());
212 EXPECT_TRUE(
213 without_accept_ch_without_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal3b330b02017-11-09 19:03:14214
215 without_accept_ch_without_lifetime_local_url_ =
216 http_server_.GetURL("/without_accept_ch_without_lifetime.html");
217 EXPECT_TRUE(
218 without_accept_ch_without_lifetime_local_url_.SchemeIsHTTPOrHTTPS());
219 EXPECT_FALSE(
220 without_accept_ch_without_lifetime_local_url_.SchemeIsCryptographic());
Tarun Bansaladd5e1812018-02-09 19:07:58221
222 without_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
223 "/without_accept_ch_without_lifetime_img_localhost.html");
224 without_accept_ch_without_lifetime_img_foo_com_ = https_server_.GetURL(
225 "/without_accept_ch_without_lifetime_img_foo_com.html");
226 accept_ch_without_lifetime_with_iframe_url_ =
227 https_server_.GetURL("/accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05228 http_equiv_accept_ch_without_lifetime_with_iframe_url_ =
229 https_server_.GetURL(
230 "/http_equiv_accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal62cc3542018-06-27 23:53:30231 accept_ch_without_lifetime_with_subresource_url_ = https_server_.GetURL(
232 "/accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal9a7051f2018-07-10 18:30:05233 http_equiv_accept_ch_without_lifetime_with_subresource_url_ =
234 https_server_.GetURL(
235 "/http_equiv_accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal62cc3542018-06-27 23:53:30236 accept_ch_without_lifetime_with_subresource_iframe_url_ =
237 https_server_.GetURL(
238 "/accept_ch_without_lifetime_with_subresource_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05239 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_ =
240 https_server_.GetURL(
241 "/http_equiv_accept_ch_without_lifetime_with_subresource_iframe."
242 "html");
Tarun Bansal229647bd002018-02-27 17:33:36243 accept_ch_without_lifetime_img_localhost_ =
244 https_server_.GetURL("/accept_ch_without_lifetime_img_localhost.html");
Tarun Bansal9a7051f2018-07-10 18:30:05245 http_equiv_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
246 "/http_equiv_accept_ch_without_lifetime_img_localhost.html");
247 http_equiv_accept_ch_with_lifetime_ =
248 https_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal293a7b6c2018-12-05 17:41:12249
250 redirect_url_ = https_cross_origin_server_.GetURL("/redirect.html");
Maks Orlovich7a588d82020-05-06 15:17:24251
252 accept_ch_empty_ = https_server_.GetURL("/accept_ch_empty.html");
253 http_equiv_accept_ch_merge_ =
254 https_server_.GetURL("/http_equiv_accept_ch_merge.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16255 }
256
257 ~ClientHintsBrowserTest() override {}
258
Mike West2fddeeb72019-02-15 11:29:48259 virtual std::unique_ptr<base::FeatureList> EnabledFeatures() {
260 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
Maks Orlovichc66745a2020-06-30 17:40:02261 feature_list->InitializeFromCommandLine(
262 "UserAgentClientHint,LangClientHintHeader", "");
Mike West2fddeeb72019-02-15 11:29:48263 return feature_list;
264 }
265
266 void SetUp() override {
Maksim Sisov (GMT+3)830244f2020-08-10 12:52:24267 scoped_feature_list_.InitWithFeatureList(EnabledFeatures());
Mike West2fddeeb72019-02-15 11:29:48268 InProcessBrowserTest::SetUp();
269 }
270
Tarun Bansal0b8b7afd2017-08-25 03:52:16271 void SetUpOnMainThread() override {
Tarun Bansal229647bd002018-02-27 17:33:36272 host_resolver()->AddRule("*", "127.0.0.1");
Tarun Bansal229647bd002018-02-27 17:33:36273
Jay Civelli1ff872d2018-03-09 21:52:16274 request_interceptor_ = std::make_unique<ThirdPartyURLLoaderInterceptor>(
275 GURL("https://foo.com/non-existing-image.jpg"));
Tarun Bansal229647bd002018-02-27 17:33:36276 base::RunLoop().RunUntilIdle();
Tarun Bansal0b8b7afd2017-08-25 03:52:16277 }
278
Jay Civelli1ff872d2018-03-09 21:52:16279 void TearDownOnMainThread() override { request_interceptor_.reset(); }
280
Tarun Bansal0b8b7afd2017-08-25 03:52:16281 void SetUpCommandLine(base::CommandLine* cmd) override {
Tarun Bansal7f3fe8c2018-04-06 22:37:47282 cmd->AppendSwitchASCII(network::switches::kForceEffectiveConnectionType,
283 net::kEffectiveConnectionType2G);
Tarun Bansal0b8b7afd2017-08-25 03:52:16284 }
285
Tarun Bansal229647bd002018-02-27 17:33:36286 void SetClientHintExpectationsOnMainFrame(bool expect_client_hints) {
287 expect_client_hints_on_main_frame_ = expect_client_hints;
Tarun Bansal1965b042017-09-07 04:59:19288 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16289
Tarun Bansal229647bd002018-02-27 17:33:36290 void SetClientHintExpectationsOnSubresources(bool expect_client_hints) {
Callum May1d939742020-03-02 17:51:30291 base::AutoLock lock(expect_client_hints_on_subresources_lock_);
Tarun Bansal229647bd002018-02-27 17:33:36292 expect_client_hints_on_subresources_ = expect_client_hints;
Tarun Bansala61f0f62017-10-24 23:53:05293 }
294
Callum May1d939742020-03-02 17:51:30295 bool expect_client_hints_on_subresources() {
296 base::AutoLock lock(expect_client_hints_on_subresources_lock_);
297 return expect_client_hints_on_subresources_;
298 }
299
Tarun Bansalc211d8b2018-03-19 19:21:58300 // Verify that the user is not notified that cookies or JavaScript were
301 // blocked on the webpage due to the checks done by client hints.
302 void VerifyContentSettingsNotNotified() const {
Carlos Caballerob4283202020-08-10 14:40:46303 auto* pscs = content_settings::PageSpecificContentSettings::GetForFrame(
Carlos Caballerod7b759412020-07-31 18:00:08304 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
Carlos Caballerob4283202020-08-10 14:40:46305 EXPECT_FALSE(pscs->IsContentBlocked(ContentSettingsType::COOKIES));
306 EXPECT_FALSE(pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
Tarun Bansalc211d8b2018-03-19 19:21:58307 }
308
Tarun Bansalbef6d652018-10-02 18:41:01309 void SetExpectedEffectiveConnectionType(
310 net::EffectiveConnectionType effective_connection_type) {
311 expected_ect = effective_connection_type;
312 }
313
Changwan Ryu434c3a32019-07-30 23:42:58314 void SetJsEnabledForActiveView(bool enabled) {
Rakina Zata Amni347b70902020-07-22 10:49:04315 content::WebContents* web_contents =
316 browser()->tab_strip_model()->GetActiveWebContents();
317 content::WebPreferences prefs = web_contents->GetOrCreateWebPreferences();
Changwan Ryu434c3a32019-07-30 23:42:58318 prefs.javascript_enabled = enabled;
Rakina Zata Amni347b70902020-07-22 10:49:04319 web_contents->SetWebPreferences(prefs);
Changwan Ryu434c3a32019-07-30 23:42:58320 }
321
Maks Orlovich7227ce0d2020-02-28 17:13:16322 void TestProfilesIndependent(Browser* browser_a, Browser* browser_b);
323
Tarun Bansal3b330b02017-11-09 19:03:14324 const GURL& accept_ch_with_lifetime_http_local_url() const {
325 return accept_ch_with_lifetime_http_local_url_;
326 }
Tarun Bansal9a7051f2018-07-10 18:30:05327 const GURL& http_equiv_accept_ch_with_lifetime_http_local_url() const {
328 return http_equiv_accept_ch_with_lifetime_http_local_url_;
329 }
Tarun Bansal3b330b02017-11-09 19:03:14330
Tarun Bansal1965b042017-09-07 04:59:19331 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
332 // headers.
333 const GURL& accept_ch_with_lifetime_url() const {
334 return accept_ch_with_lifetime_url_;
335 }
Tarun Bansal9a7051f2018-07-10 18:30:05336 const GURL& http_equiv_accept_ch_with_lifetime() {
337 return http_equiv_accept_ch_with_lifetime_;
338 }
Tarun Bansal1965b042017-09-07 04:59:19339
Tarun Bansal73502f92019-04-16 21:21:19340 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
341 // headers. The Accept-CH-Lifetime duration is set very short to 1 second.
342 const GURL& accept_ch_with_short_lifetime() const {
343 return accept_ch_with_short_lifetime_url_;
344 }
345
Tarun Bansal1965b042017-09-07 04:59:19346 // A URL whose response headers include only Accept-CH header.
347 const GURL& accept_ch_without_lifetime_url() const {
348 return accept_ch_without_lifetime_url_;
349 }
Tarun Bansal9a7051f2018-07-10 18:30:05350 const GURL& http_equiv_accept_ch_without_lifetime_url() const {
351 return http_equiv_accept_ch_without_lifetime_url_;
352 }
Tarun Bansal1965b042017-09-07 04:59:19353
354 // A URL whose response headers do not include either Accept-CH or
355 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
356 const GURL& without_accept_ch_without_lifetime_url() const {
357 return without_accept_ch_without_lifetime_url_;
358 }
359
Tarun Bansal3b330b02017-11-09 19:03:14360 // A URL whose response headers do not include either Accept-CH or
361 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
362 const GURL& without_accept_ch_without_lifetime_local_url() const {
363 return without_accept_ch_without_lifetime_local_url_;
364 }
365
Tarun Bansaladd5e1812018-02-09 19:07:58366 // A URL whose response headers do not include either Accept-CH or
367 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
368 // from localhost.
369 const GURL& without_accept_ch_without_lifetime_img_localhost() const {
370 return without_accept_ch_without_lifetime_img_localhost_;
371 }
372
373 // A URL whose response headers do not include either Accept-CH or
374 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
375 // from foo.com.
376 const GURL& without_accept_ch_without_lifetime_img_foo_com() const {
377 return without_accept_ch_without_lifetime_img_foo_com_;
378 }
379
380 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
381 // headers. The response loads accept_ch_with_lifetime_url() in an iframe.
382 const GURL& accept_ch_without_lifetime_with_iframe_url() const {
383 return accept_ch_without_lifetime_with_iframe_url_;
384 }
Tarun Bansal9a7051f2018-07-10 18:30:05385 const GURL& http_equiv_accept_ch_without_lifetime_with_iframe_url() const {
386 return http_equiv_accept_ch_without_lifetime_with_iframe_url_;
387 }
Tarun Bansaladd5e1812018-02-09 19:07:58388
Tarun Bansal62cc3542018-06-27 23:53:30389 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
390 // headers. The response loads accept_ch_with_lifetime_url() as a subresource
391 // in the main frame.
392 const GURL& accept_ch_without_lifetime_with_subresource_url() const {
393 return accept_ch_without_lifetime_with_subresource_url_;
394 }
Tarun Bansal9a7051f2018-07-10 18:30:05395 const GURL& http_equiv_accept_ch_without_lifetime_with_subresource_url()
396 const {
397 return http_equiv_accept_ch_without_lifetime_with_subresource_url_;
398 }
Tarun Bansal62cc3542018-06-27 23:53:30399
400 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
Tarun Bansal9a7051f2018-07-10 18:30:05401 // headers. The response loads accept_ch_with_lifetime_url() or
402 // http_equiv_accept_ch_with_lifetime_url() as a subresource in the iframe.
Tarun Bansal62cc3542018-06-27 23:53:30403 const GURL& accept_ch_without_lifetime_with_subresource_iframe_url() const {
404 return accept_ch_without_lifetime_with_subresource_iframe_url_;
405 }
Tarun Bansal9a7051f2018-07-10 18:30:05406 const GURL&
407 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url() const {
408 return http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
409 }
Tarun Bansal62cc3542018-06-27 23:53:30410
Tarun Bansal9a7051f2018-07-10 18:30:05411 // A URL whose response includes only Accept-CH header. Navigating to
Tarun Bansal229647bd002018-02-27 17:33:36412 // this URL also fetches two images: One from the localhost, and one from
413 // foo.com.
414 const GURL& accept_ch_without_lifetime_img_localhost() const {
415 return accept_ch_without_lifetime_img_localhost_;
416 }
Tarun Bansal9a7051f2018-07-10 18:30:05417 const GURL& http_equiv_accept_ch_without_lifetime_img_localhost() const {
418 return http_equiv_accept_ch_without_lifetime_img_localhost_;
419 }
Tarun Bansal229647bd002018-02-27 17:33:36420
Tarun Bansal293a7b6c2018-12-05 17:41:12421 const GURL& redirect_url() const { return redirect_url_; }
422
Maks Orlovich7a588d82020-05-06 15:17:24423 // A URL to a page with a response containing an empty accept_ch header.
424 const GURL& accept_ch_empty() const { return accept_ch_empty_; }
425
426 // A page where some hints are in accept-ch header, some in http-equiv.
427 const GURL& http_equiv_accept_ch_merge() const {
428 return http_equiv_accept_ch_merge_;
429 }
430
Mike West2fddeeb72019-02-15 11:29:48431 size_t count_user_agent_hint_headers_seen() const {
Callum May7d88ff3e2019-11-12 18:21:46432 base::AutoLock lock(count_headers_lock_);
Mike West2fddeeb72019-02-15 11:29:48433 return count_user_agent_hint_headers_seen_;
434 }
435
Maks Orlovich5dcc99c2020-02-13 19:07:46436 size_t count_ua_mobile_client_hints_headers_seen() const {
437 base::AutoLock lock(count_headers_lock_);
438 return count_ua_mobile_client_hints_headers_seen_;
439 }
440
Tarun Bansal1965b042017-09-07 04:59:19441 size_t count_client_hints_headers_seen() const {
Callum May7d88ff3e2019-11-12 18:21:46442 base::AutoLock lock(count_headers_lock_);
Tarun Bansal1965b042017-09-07 04:59:19443 return count_client_hints_headers_seen_;
444 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16445
Tarun Bansal229647bd002018-02-27 17:33:36446 size_t third_party_request_count_seen() const {
447 return request_interceptor_->request_count_seen();
448 }
449
450 size_t third_party_client_hints_count_seen() const {
451 return request_interceptor_->client_hints_count_seen();
452 }
453
Mike Weste555be862019-02-20 16:17:30454 const std::string& main_frame_ua_observed() const {
455 return main_frame_ua_observed_;
456 }
457
Yoav Weissd33bacb2020-03-12 06:42:21458 const std::string& main_frame_ua_full_version_observed() const {
459 return main_frame_ua_full_version_observed_;
460 }
461
Maks Orlovich73f374d2020-04-02 12:46:13462 const std::string& main_frame_ua_mobile_observed() const {
463 return main_frame_ua_mobile_observed_;
464 }
465
466 const std::string& main_frame_ua_platform_observed() const {
467 return main_frame_ua_platform_observed_;
468 }
469
Tarun Bansalea0d8262018-05-21 16:11:50470 base::test::ScopedFeatureList scoped_feature_list_;
471
Tarun Bansal345418632018-06-29 11:07:04472 std::string intercept_iframe_resource_;
Tarun Bansal9a7051f2018-07-10 18:30:05473 bool intercept_to_http_equiv_iframe_ = false;
Callum May7d88ff3e2019-11-12 18:21:46474 mutable base::Lock count_headers_lock_;
Tarun Bansal345418632018-06-29 11:07:04475
Tarun Bansal0b8b7afd2017-08-25 03:52:16476 private:
Tarun Bansal345418632018-06-29 11:07:04477 // Intercepts only the main frame requests that contain
Tarun Bansal293a7b6c2018-12-05 17:41:12478 // "redirect" in the resource path. The intercepted requests
479 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
480 // server.
481 std::unique_ptr<net::test_server::HttpResponse> RequestHandlerToRedirect(
482 const net::test_server::HttpRequest& request) {
483 // Check if it's a main frame request.
484 if (request.relative_url.find(".html") == std::string::npos)
485 return nullptr;
486
487 if (request.GetURL().spec().find("redirect") == std::string::npos)
488 return nullptr;
489
490 std::unique_ptr<net::test_server::BasicHttpResponse> response;
491 response.reset(new net::test_server::BasicHttpResponse);
492 response->set_code(net::HTTP_FOUND);
493 response->AddCustomHeader("Location",
494 without_accept_ch_without_lifetime_url().spec());
495 return std::move(response);
496 }
497
498 // Intercepts only the main frame requests that contain
Tarun Bansal345418632018-06-29 11:07:04499 // |intercept_iframe_resource_| in the resource path. The intercepted requests
500 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
501 // server.
502 std::unique_ptr<net::test_server::HttpResponse>
503 RequestHandlerToFetchCrossOriginIframe(
504 const net::test_server::HttpRequest& request) {
505 if (intercept_iframe_resource_.empty())
506 return nullptr;
507
508 // Check if it's a main frame request.
509 if (request.relative_url.find(".html") == std::string::npos)
510 return nullptr;
511
512 if (request.relative_url.find(intercept_iframe_resource_) ==
513 std::string::npos) {
514 return nullptr;
515 }
516
517 const std::string iframe_url =
Tarun Bansal9a7051f2018-07-10 18:30:05518 intercept_to_http_equiv_iframe_
519 ? https_cross_origin_server_
520 .GetURL("/http_equiv_accept_ch_with_lifetime.html")
521 .spec()
522 : https_cross_origin_server_.GetURL("/accept_ch_with_lifetime.html")
523 .spec();
Tarun Bansal345418632018-06-29 11:07:04524
525 std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
526 new net::test_server::BasicHttpResponse());
527 http_response->set_code(net::HTTP_OK);
528 http_response->set_content_type("text/html");
529 http_response->set_content(
530 "<html>"
531 "<link rel='icon' href='data:;base64,='><head></head>"
532 "Empty file which uses link-rel to disable favicon fetches. "
533 "<iframe src='" +
534 iframe_url + "'></iframe></html>");
535
536 return std::move(http_response);
537 }
538
Maks Orlovich73f374d2020-04-02 12:46:13539 static std::string UpdateHeaderObservation(
540 const net::test_server::HttpRequest& request,
541 const std::string& header) {
542 if (request.headers.find(header) != request.headers.end())
543 return request.headers.find(header)->second;
544 else
545 return "";
546 }
547
Tarun Bansal1965b042017-09-07 04:59:19548 // Called by |https_server_|.
549 void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
Tarun Bansal6bf54302017-10-02 07:39:14550 bool is_main_frame_navigation =
551 request.GetURL().spec().find(".html") != std::string::npos;
552
Tarun Bansal293a7b6c2018-12-05 17:41:12553 if (is_main_frame_navigation &&
554 request.GetURL().spec().find("redirect") != std::string::npos) {
555 return;
556 }
557
Tarun Bansal229647bd002018-02-27 17:33:36558 if (is_main_frame_navigation) {
Maks Orlovich73f374d2020-04-02 12:46:13559 main_frame_ua_observed_ = UpdateHeaderObservation(request, "sec-ch-ua");
560 main_frame_ua_full_version_observed_ =
561 UpdateHeaderObservation(request, "sec-ch-ua-full-version");
562 main_frame_ua_mobile_observed_ =
563 UpdateHeaderObservation(request, "sec-ch-ua-mobile");
564 main_frame_ua_platform_observed_ =
565 UpdateHeaderObservation(request, "sec-ch-ua-platform");
Yoav Weissd33bacb2020-03-12 06:42:21566
Tarun Bansalf9cf9892018-04-06 04:38:01567 VerifyClientHintsReceived(expect_client_hints_on_main_frame_, request);
Tarun Bansal5c28afb2018-03-17 02:55:20568 if (expect_client_hints_on_main_frame_) {
569 double value = 0.0;
570 EXPECT_TRUE(base::StringToDouble(
571 request.headers.find("device-memory")->second, &value));
572 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35573 EXPECT_TRUE(IsSimilarToDoubleABNF(
574 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42575 main_frame_device_memory_observed_ = value;
Tarun Bansal5c28afb2018-03-17 02:55:20576
577 EXPECT_TRUE(
578 base::StringToDouble(request.headers.find("dpr")->second, &value));
579 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35580 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42581 main_frame_dpr_observed_ = value;
582
Tarun Bansal5c28afb2018-03-17 02:55:20583 EXPECT_TRUE(base::StringToDouble(
584 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35585 EXPECT_TRUE(
586 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36587#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20588 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36589#else
590 EXPECT_EQ(980, value);
Tarun Bansal5c28afb2018-03-17 02:55:20591#endif
Tarun Bansal44ad96882018-03-28 17:47:42592 main_frame_viewport_width_observed_ = value;
Mike Weste555be862019-02-20 16:17:30593
Tarun Bansal7f3fe8c2018-04-06 22:37:47594 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20595 }
Tarun Bansala61f0f62017-10-24 23:53:05596 }
Tarun Bansal6bf54302017-10-02 07:39:14597
Tarun Bansal229647bd002018-02-27 17:33:36598 if (!is_main_frame_navigation) {
Callum May1d939742020-03-02 17:51:30599 VerifyClientHintsReceived(expect_client_hints_on_subresources(), request);
Tarun Bansal5c28afb2018-03-17 02:55:20600
Callum May1d939742020-03-02 17:51:30601 if (expect_client_hints_on_subresources()) {
Tarun Bansal5c28afb2018-03-17 02:55:20602 double value = 0.0;
603 EXPECT_TRUE(base::StringToDouble(
604 request.headers.find("device-memory")->second, &value));
605 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35606 EXPECT_TRUE(IsSimilarToDoubleABNF(
607 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42608 if (main_frame_device_memory_observed_ > 0) {
609 EXPECT_EQ(main_frame_device_memory_observed_, value);
610 }
Tarun Bansal5c28afb2018-03-17 02:55:20611
612 EXPECT_TRUE(
613 base::StringToDouble(request.headers.find("dpr")->second, &value));
614 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35615 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42616 if (main_frame_dpr_observed_ > 0) {
617 EXPECT_EQ(main_frame_dpr_observed_, value);
618 }
Tarun Bansal5c28afb2018-03-17 02:55:20619
620 EXPECT_TRUE(base::StringToDouble(
621 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35622 EXPECT_TRUE(
623 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36624#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20625 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36626#else
627 EXPECT_EQ(980, value);
628#endif
Tarun Bansal44ad96882018-03-28 17:47:42629#if defined(OS_ANDROID)
630 // TODO(tbansal): https://crbug.com/825892: Viewport width on main
631 // frame requests may be incorrect when the Chrome window is not
632 // maximized.
633 if (main_frame_viewport_width_observed_ > 0) {
634 EXPECT_EQ(main_frame_viewport_width_observed_, value);
635 }
636#endif
Tarun Bansal7f3fe8c2018-04-06 22:37:47637 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20638 }
Tarun Bansala61f0f62017-10-24 23:53:05639 }
Tarun Bansal6bf54302017-10-02 07:39:14640
Mike West14c11102019-02-04 16:16:47641 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Jan Wilken Dörriea8cb56302019-06-06 18:59:36642 if (base::Contains(request.headers,
643 blink::kClientHintsHeaderMapping[i])) {
Callum May7d88ff3e2019-11-12 18:21:46644 base::AutoLock lock(count_headers_lock_);
Mike West2fddeeb72019-02-15 11:29:48645 // The user agent hint is special:
646 if (std::string(blink::kClientHintsHeaderMapping[i]) == "sec-ch-ua") {
647 count_user_agent_hint_headers_seen_++;
Maks Orlovich5dcc99c2020-02-13 19:07:46648 } else if (std::string(blink::kClientHintsHeaderMapping[i]) ==
649 "sec-ch-ua-mobile") {
650 count_ua_mobile_client_hints_headers_seen_++;
Mike West2fddeeb72019-02-15 11:29:48651 } else {
652 count_client_hints_headers_seen_++;
653 }
Tarun Bansalf9cf9892018-04-06 04:38:01654 }
655 }
656 }
Tarun Bansal1965b042017-09-07 04:59:19657
Tarun Bansalf9cf9892018-04-06 04:38:01658 void VerifyClientHintsReceived(bool expect_client_hints,
659 const net::test_server::HttpRequest& request) {
Mike West14c11102019-02-04 16:16:47660 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
661 SCOPED_TRACE(testing::Message()
662 << std::string(blink::kClientHintsHeaderMapping[i]));
Tarun Bansalf9cf9892018-04-06 04:38:01663 // Resource width client hint is only attached on image subresources.
664 if (std::string(blink::kClientHintsHeaderMapping[i]) == "width") {
665 continue;
666 }
Mike West2fddeeb72019-02-15 11:29:48667
Maks Orlovich5dcc99c2020-02-13 19:07:46668 // `Sec-CH-UA` and `Sec-CH-UA-Mobile` is attached on all requests.
669 if (std::string(blink::kClientHintsHeaderMapping[i]) == "sec-ch-ua" ||
670 std::string(blink::kClientHintsHeaderMapping[i]) ==
671 "sec-ch-ua-mobile") {
Mike West2fddeeb72019-02-15 11:29:48672 continue;
673 }
674
Jan Wilken Dörriea8cb56302019-06-06 18:59:36675 EXPECT_EQ(
676 expect_client_hints,
677 base::Contains(request.headers, blink::kClientHintsHeaderMapping[i]));
Tarun Bansalf9cf9892018-04-06 04:38:01678 }
Tarun Bansal1965b042017-09-07 04:59:19679 }
680
Tarun Bansal7f3fe8c2018-04-06 22:37:47681 void VerifyNetworkQualityClientHints(
682 const net::test_server::HttpRequest& request) const {
683 // Effective connection type is forced to 2G using command line in these
684 // tests.
Tarun Bansal509a8dd2018-04-10 17:19:16685 int rtt_value = 0.0;
Tarun Bansal7f3fe8c2018-04-06 22:37:47686 EXPECT_TRUE(
Tarun Bansal509a8dd2018-04-10 17:19:16687 base::StringToInt(request.headers.find("rtt")->second, &rtt_value));
688 EXPECT_LE(0, rtt_value);
Tarun Bansal62efba12018-05-04 22:58:35689 EXPECT_TRUE(IsSimilarToIntABNF(request.headers.find("rtt")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16690 // Verify that RTT value is a multiple of 50 milliseconds.
691 EXPECT_EQ(0, rtt_value % 50);
Tarun Bansalbef6d652018-10-02 18:41:01692 EXPECT_GE(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? 3000 : 500,
693 rtt_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47694
Tarun Bansal509a8dd2018-04-10 17:19:16695 double mbps_value = 0.0;
696 EXPECT_TRUE(base::StringToDouble(request.headers.find("downlink")->second,
697 &mbps_value));
698 EXPECT_LE(0, mbps_value);
Tarun Bansal62efba12018-05-04 22:58:35699 EXPECT_TRUE(
700 IsSimilarToDoubleABNF(request.headers.find("downlink")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16701 // Verify that the mbps value is a multiple of 0.050 mbps.
702 // Allow for small amount of noise due to double to integer conversions.
703 EXPECT_NEAR(0, (static_cast<int>(mbps_value * 1000)) % 50, 1);
704 EXPECT_GE(10.0, mbps_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47705
706 EXPECT_FALSE(request.headers.find("ect")->second.empty());
Tarun Bansalceab9592018-05-01 18:57:35707
708 // TODO(tbansal): https://crbug.com/819244: When network servicification is
Tarun Bansal5ac533542018-08-10 19:45:52709 // enabled, the renderer processes do not receive notifications on
710 // change in the network quality. Hence, the network quality client hints
711 // are not set to the correct value on subresources.
712 bool is_main_frame_navigation =
713 request.GetURL().spec().find(".html") != std::string::npos;
John Abd-El-Malek67facbe82019-06-06 22:37:08714 if (is_main_frame_navigation) {
Tarun Bansalceab9592018-05-01 18:57:35715 // Effective connection type is forced to 2G using command line in these
716 // tests. RTT is expected to be 1800 msec but leave some gap to account
717 // for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01718 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
719 EXPECT_NEAR(1800, rtt_value, 360);
720 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
721 EXPECT_NEAR(450, rtt_value, 90);
722 } else {
723 NOTREACHED();
724 }
Tarun Bansalceab9592018-05-01 18:57:35725
726 // Effective connection type is forced to 2G using command line in these
727 // tests. downlink is expected to be 0.075 Mbps but leave some gap to
728 // account for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01729 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
730 EXPECT_NEAR(0.075, mbps_value, 0.05);
731 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
732 EXPECT_NEAR(0.4, mbps_value, 0.1);
733 } else {
734 NOTREACHED();
735 }
Tarun Bansalceab9592018-05-01 18:57:35736
Tarun Bansalbef6d652018-10-02 18:41:01737 EXPECT_EQ(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? "2g" : "3g",
738 request.headers.find("ect")->second);
Tarun Bansalceab9592018-05-01 18:57:35739 }
Tarun Bansal7f3fe8c2018-04-06 22:37:47740 }
741
Tarun Bansal3b330b02017-11-09 19:03:14742 net::EmbeddedTestServer http_server_;
Tarun Bansal0b8b7afd2017-08-25 03:52:16743 net::EmbeddedTestServer https_server_;
Tarun Bansal345418632018-06-29 11:07:04744 net::EmbeddedTestServer https_cross_origin_server_;
Tarun Bansal3b330b02017-11-09 19:03:14745 GURL accept_ch_with_lifetime_http_local_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05746 GURL http_equiv_accept_ch_with_lifetime_http_local_url_;
Tarun Bansal1965b042017-09-07 04:59:19747 GURL accept_ch_with_lifetime_url_;
Tarun Bansal73502f92019-04-16 21:21:19748 GURL accept_ch_with_short_lifetime_url_;
Tarun Bansal1965b042017-09-07 04:59:19749 GURL accept_ch_without_lifetime_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05750 GURL http_equiv_accept_ch_without_lifetime_url_;
Tarun Bansal1965b042017-09-07 04:59:19751 GURL without_accept_ch_without_lifetime_url_;
Tarun Bansal3b330b02017-11-09 19:03:14752 GURL without_accept_ch_without_lifetime_local_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58753 GURL accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05754 GURL http_equiv_accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal62cc3542018-06-27 23:53:30755 GURL accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05756 GURL http_equiv_accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal62cc3542018-06-27 23:53:30757 GURL accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05758 GURL http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58759 GURL without_accept_ch_without_lifetime_img_foo_com_;
760 GURL without_accept_ch_without_lifetime_img_localhost_;
Tarun Bansal229647bd002018-02-27 17:33:36761 GURL accept_ch_without_lifetime_img_localhost_;
Tarun Bansal9a7051f2018-07-10 18:30:05762 GURL http_equiv_accept_ch_without_lifetime_img_localhost_;
763 GURL http_equiv_accept_ch_with_lifetime_;
Tarun Bansal293a7b6c2018-12-05 17:41:12764 GURL redirect_url_;
Maks Orlovich7a588d82020-05-06 15:17:24765 GURL accept_ch_empty_;
766 GURL http_equiv_accept_ch_merge_;
Tarun Bansal1965b042017-09-07 04:59:19767
Mike Weste555be862019-02-20 16:17:30768 std::string main_frame_ua_observed_;
Yoav Weissd33bacb2020-03-12 06:42:21769 std::string main_frame_ua_full_version_observed_;
Maks Orlovich73f374d2020-04-02 12:46:13770 std::string main_frame_ua_mobile_observed_;
771 std::string main_frame_ua_platform_observed_;
Mike Weste555be862019-02-20 16:17:30772
Tarun Bansal44ad96882018-03-28 17:47:42773 double main_frame_dpr_observed_ = -1;
774 double main_frame_viewport_width_observed_ = -1;
775 double main_frame_device_memory_observed_ = -1;
776
Tarun Bansal229647bd002018-02-27 17:33:36777 // Expect client hints on all the main frame request.
778 bool expect_client_hints_on_main_frame_;
779 // Expect client hints on all the subresource requests.
Callum May1d939742020-03-02 17:51:30780 bool expect_client_hints_on_subresources_
781 GUARDED_BY(expect_client_hints_on_subresources_lock_);
782
783 base::Lock expect_client_hints_on_subresources_lock_;
Tarun Bansal229647bd002018-02-27 17:33:36784
Mike West2fddeeb72019-02-15 11:29:48785 size_t count_user_agent_hint_headers_seen_;
Maks Orlovich5dcc99c2020-02-13 19:07:46786 size_t count_ua_mobile_client_hints_headers_seen_;
Tarun Bansal1965b042017-09-07 04:59:19787 size_t count_client_hints_headers_seen_;
Tarun Bansala61f0f62017-10-24 23:53:05788
Jay Civelli1ff872d2018-03-09 21:52:16789 std::unique_ptr<ThirdPartyURLLoaderInterceptor> request_interceptor_;
Tarun Bansal229647bd002018-02-27 17:33:36790
Tarun Bansalbef6d652018-10-02 18:41:01791 // Set to 2G in SetUpCommandLine().
792 net::EffectiveConnectionType expected_ect = net::EFFECTIVE_CONNECTION_TYPE_2G;
793
Tarun Bansala61f0f62017-10-24 23:53:05794 DISALLOW_COPY_AND_ASSIGN(ClientHintsBrowserTest);
Tarun Bansal0b8b7afd2017-08-25 03:52:16795};
796
Tarun Bansal9a7051f2018-07-10 18:30:05797// True if testing for http-equiv correctness. When set to true, the tests
798// use webpages that may contain http-equiv Accept-CH and Accept-CH-Lifetime
799// headers. When set to false, the tests use webpages that set the headers in
800// the HTTP response headers.
Ilia Samsonov282c38412019-12-09 08:15:10801INSTANTIATE_TEST_SUITE_P(All,
Victor Costane5e91512019-02-13 08:24:02802 ClientHintsBrowserTest,
803 testing::Bool());
Tarun Bansal9a7051f2018-07-10 18:30:05804
Tarun Bansalea0d8262018-05-21 16:11:50805class ClientHintsAllowThirdPartyBrowserTest : public ClientHintsBrowserTest {
Mike West2fddeeb72019-02-15 11:29:48806 std::unique_ptr<base::FeatureList> EnabledFeatures() override {
807 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
808 feature_list->InitializeFromCommandLine(
Maks Orlovichc66745a2020-06-30 17:40:02809 "AllowClientHintsToThirdParty,UserAgentClientHint,LangClientHintHeader",
810 "");
Mike West2fddeeb72019-02-15 11:29:48811 return feature_list;
Tarun Bansalea0d8262018-05-21 16:11:50812 }
813};
814
Ilia Samsonov282c38412019-12-09 08:15:10815INSTANTIATE_TEST_SUITE_P(All,
Aaron Tagliaboschia09ec442019-09-18 15:29:03816 ClientHintsAllowThirdPartyBrowserTest,
817 testing::Bool());
818
Tarun Bansal74e189d2018-05-07 19:07:35819IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, CorsChecks) {
Mike West14c11102019-02-04 16:16:47820 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansal74e189d2018-05-07 19:07:35821 // Do not test for headers that have not been enabled on the blink "stable"
822 // yet.
823 if (std::string(blink::kClientHintsHeaderMapping[i]) == "rtt" ||
824 std::string(blink::kClientHintsHeaderMapping[i]) == "downlink" ||
825 std::string(blink::kClientHintsHeaderMapping[i]) == "ect") {
826 continue;
827 }
Takashi Toyoshima2e01e692018-11-16 03:23:27828 EXPECT_TRUE(network::cors::IsCorsSafelistedHeader(
Tarun Bansal74e189d2018-05-07 19:07:35829 blink::kClientHintsHeaderMapping[i], "42" /* value */));
830 }
Takashi Toyoshima2e01e692018-11-16 03:23:27831 EXPECT_FALSE(network::cors::IsCorsSafelistedHeader("not-a-client-hint-header",
Tarun Bansal74e189d2018-05-07 19:07:35832 "" /* value */));
833 EXPECT_TRUE(
Takashi Toyoshima2e01e692018-11-16 03:23:27834 network::cors::IsCorsSafelistedHeader("save-data", "on" /* value */));
Tarun Bansal74e189d2018-05-07 19:07:35835}
836
Maks Orlovichf0a2eed2020-05-02 20:08:21837IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, HttpEquivWorks) {
838 const GURL gurl = http_equiv_accept_ch_without_lifetime_img_localhost();
839 base::HistogramTester histogram_tester;
840
841 SetClientHintExpectationsOnMainFrame(false);
842 SetClientHintExpectationsOnSubresources(true);
843
844 ui_test_utils::NavigateToURL(browser(), gurl);
845 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
846}
847
Tarun Bansal0b8b7afd2017-08-25 03:52:16848// Loads a webpage that requests persisting of client hints. Verifies that
849// the browser receives the mojo notification from the renderer and persists the
Maks Orlovichf0a2eed2020-05-02 20:08:21850// client hints to the disk --- unless it's using http-equiv which shouldn't
851// persist.
Tarun Bansal9a7051f2018-07-10 18:30:05852IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, ClientHintsHttps) {
Tarun Bansal0b8b7afd2017-08-25 03:52:16853 base::HistogramTester histogram_tester;
Tarun Bansal9a7051f2018-07-10 18:30:05854 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
855 : accept_ch_with_lifetime_url();
856 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal0b8b7afd2017-08-25 03:52:16857
Maks Orlovichf0a2eed2020-05-02 20:08:21858 if (GetParam())
859 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
860 else
861 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
Tarun Bansal0b8b7afd2017-08-25 03:52:16862
863 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:28864 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal0b8b7afd2017-08-25 03:52:16865
Maks Orlovichf0a2eed2020-05-02 20:08:21866 if (GetParam()) {
867 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
868 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
869 } else {
870 // client_hints_url() sets the expected number of client hints.
871 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
872 expected_client_hints_number, 1);
873 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
Yoav Weiss76e1afb762020-05-14 19:28:12874 // seconds, but a maximum value is registered instead.
Maks Orlovichf0a2eed2020-05-02 20:08:21875 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:12876 uma_histogram_max_value, 1);
Maks Orlovichf0a2eed2020-05-02 20:08:21877 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16878}
879
Aaron Tagliaboschi8ef04eca2020-05-12 23:16:44880IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, PRE_ClientHintsClearSession) {
881 const GURL gurl = accept_ch_with_lifetime_url();
882
883 base::HistogramTester histogram_tester;
884 ContentSettingsForOneType host_settings;
885
886 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
887 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
888 &host_settings);
889 EXPECT_EQ(0u, host_settings.size());
890
891 // Fetching |gurl| should persist the request for client hints iff using
892 // headers and not http-equiv.
893 ui_test_utils::NavigateToURL(browser(), gurl);
894
895 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
896
897 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:28898 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Aaron Tagliaboschi8ef04eca2020-05-12 23:16:44899 base::RunLoop().RunUntilIdle();
900
901 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
902 expected_client_hints_number, 1);
903 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
Yoav Weiss76e1afb762020-05-14 19:28:12904 // seconds, but a maximum value is registered instead.
Aaron Tagliaboschi8ef04eca2020-05-12 23:16:44905 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:12906 uma_histogram_max_value, 1);
Aaron Tagliaboschi8ef04eca2020-05-12 23:16:44907
908 // Clients hints preferences for one origin should be persisted.
909 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
910 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
911 &host_settings);
912 EXPECT_EQ(1u, host_settings.size());
913
914 SetClientHintExpectationsOnMainFrame(true);
915 SetClientHintExpectationsOnSubresources(true);
916 ui_test_utils::NavigateToURL(browser(),
917 without_accept_ch_without_lifetime_url());
918
919 // The user agent hint is attached to all three requests:
920 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
921 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
922
923 // Expected number of hints attached to the image request, and the same number
924 // to the main frame request.
925 EXPECT_EQ(expected_client_hints_number * 2,
926 count_client_hints_headers_seen());
927}
928
929IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsClearSession) {
930 const GURL gurl = accept_ch_with_lifetime_url();
931
932 base::HistogramTester histogram_tester;
933 ContentSettingsForOneType host_settings;
934
935 // Clients hints preferences for one origin should be persisted.
936 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
937 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
938 &host_settings);
939 EXPECT_EQ(0u, host_settings.size());
940
941 SetClientHintExpectationsOnMainFrame(false);
942 SetClientHintExpectationsOnSubresources(false);
943 ui_test_utils::NavigateToURL(browser(),
944 without_accept_ch_without_lifetime_url());
945
946 // The user agent hint is attached to all three requests:
947 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
948 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
949
950 // Expected number of hints attached to the image request, and the same number
951 // to the main frame request.
952 EXPECT_EQ(0u, count_client_hints_headers_seen());
953}
954
Tarun Bansaladd5e1812018-02-09 19:07:58955// Test that client hints are attached to subresources only if they belong
956// to the same host as document host.
Maks Orlovichf0a2eed2020-05-02 20:08:21957IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansaladd5e1812018-02-09 19:07:58958 ClientHintsHttpsSubresourceDifferentOrigin) {
Maks Orlovichf0a2eed2020-05-02 20:08:21959 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:05960
Tarun Bansaladd5e1812018-02-09 19:07:58961 base::HistogramTester histogram_tester;
962
963 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:05964 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:58965 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
966
967 // Verify that the client hints settings for localhost have been saved.
968 ContentSettingsForOneType client_hints_settings;
969 HostContentSettingsMap* host_content_settings_map =
970 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
971 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:45972 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansaladd5e1812018-02-09 19:07:58973 ASSERT_EQ(1U, client_hints_settings.size());
974
975 // Copy the client hints setting for localhost to foo.com.
976 host_content_settings_map->SetWebsiteSettingDefaultScope(
Darin Fisher42f5e7d2019-10-30 07:15:45977 GURL("https://foo.com/"), GURL(), ContentSettingsType::CLIENT_HINTS,
Tarun Bansaladd5e1812018-02-09 19:07:58978 std::string(),
Jeremy Romanec48d7a2018-03-01 17:35:09979 std::make_unique<base::Value>(
Oksana Zhuravlovab14dc882018-04-12 17:34:57980 client_hints_settings.at(0).setting_value.Clone()));
Tarun Bansaladd5e1812018-02-09 19:07:58981
982 // Verify that client hints for the two hosts has been saved.
983 host_content_settings_map =
984 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
985 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:45986 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansaladd5e1812018-02-09 19:07:58987 ASSERT_EQ(2U, client_hints_settings.size());
988
989 // Navigating to without_accept_ch_without_lifetime_img_localhost() should
990 // attach client hints to the image subresouce contained in that page since
991 // the image is located on the same server as the document origin.
Tarun Bansal229647bd002018-02-27 17:33:36992 SetClientHintExpectationsOnMainFrame(true);
993 SetClientHintExpectationsOnSubresources(true);
Tarun Bansaladd5e1812018-02-09 19:07:58994 ui_test_utils::NavigateToURL(
995 browser(), without_accept_ch_without_lifetime_img_localhost());
996 base::RunLoop().RunUntilIdle();
997 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:28998 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansaladd5e1812018-02-09 19:07:58999
Maks Orlovich5dcc99c2020-02-13 19:07:461000 // The user agent hint is attached to all three requests, as is UA-mobile:
Mike West2fddeeb72019-02-15 11:29:481001 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461002 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481003
Yoav Weissd33bacb2020-03-12 06:42:211004 // Expected number of hints attached to the image request, and the same number
1005 // to the main frame request.
1006 EXPECT_EQ(expected_client_hints_number * 2,
1007 count_client_hints_headers_seen());
Tarun Bansaladd5e1812018-02-09 19:07:581008
1009 // Navigating to without_accept_ch_without_lifetime_img_foo_com() should not
1010 // attach client hints to the image subresouce contained in that page since
1011 // the image is located on a different server as the document origin.
Tarun Bansaladd5e1812018-02-09 19:07:581012 ui_test_utils::NavigateToURL(
1013 browser(), without_accept_ch_without_lifetime_img_foo_com());
1014 base::RunLoop().RunUntilIdle();
1015 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281016 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansaladd5e1812018-02-09 19:07:581017
Tarun Bansalb30b7532018-03-14 21:50:381018 // The device-memory and dprheader is attached to the main frame request.
Tarun Bansal5c28afb2018-03-17 02:55:201019#if defined(OS_ANDROID)
Yoav Weissd33bacb2020-03-12 06:42:211020 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:201021#else
Yoav Weissd33bacb2020-03-12 06:42:211022 EXPECT_EQ(expected_client_hints_number * 3,
1023 count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:201024#endif
Mike West2fddeeb72019-02-15 11:29:481025
1026 // Requests to third party servers should have only one client hint attached
1027 // (`Sec-CH-UA`).
Tarun Bansal229647bd002018-02-27 17:33:361028 EXPECT_EQ(1u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461029 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansaladd5e1812018-02-09 19:07:581030}
1031
Maks Orlovich7227ce0d2020-02-28 17:13:161032// Test that client hints are attached to subresources checks the right setting
1033// for OTR profile.
Maks Orlovichf0a2eed2020-05-02 20:08:211034IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Maks Orlovich7227ce0d2020-02-28 17:13:161035 ClientHintsHttpsSubresourceOffTheRecord) {
Maks Orlovichf0a2eed2020-05-02 20:08:211036 const GURL gurl = accept_ch_with_lifetime_url();
Maks Orlovich7227ce0d2020-02-28 17:13:161037
1038 base::HistogramTester histogram_tester;
1039
1040 // Add client hints for the embedded test server.
1041 ui_test_utils::NavigateToURL(browser(), gurl);
1042 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1043
1044 // Main profile should get hints for both page and subresources.
1045 SetClientHintExpectationsOnMainFrame(true);
1046 SetClientHintExpectationsOnSubresources(true);
1047 ui_test_utils::NavigateToURL(
1048 browser(), without_accept_ch_without_lifetime_img_localhost());
1049 base::RunLoop().RunUntilIdle();
1050 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281051 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Maks Orlovich7227ce0d2020-02-28 17:13:161052
1053 // The user agent hint is attached to all three requests:
1054 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
1055 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
1056
Yoav Weissd33bacb2020-03-12 06:42:211057 // Expected number of hints attached to the image request, and the same number
1058 // to the main frame request.
1059 EXPECT_EQ(expected_client_hints_number * 2,
1060 count_client_hints_headers_seen());
Maks Orlovich7227ce0d2020-02-28 17:13:161061
1062 // OTR profile should get neither.
1063 Browser* otr_browser = CreateIncognitoBrowser(browser()->profile());
1064 SetClientHintExpectationsOnMainFrame(false);
1065 SetClientHintExpectationsOnSubresources(false);
1066 ui_test_utils::NavigateToURL(
1067 otr_browser, without_accept_ch_without_lifetime_img_localhost());
1068}
1069
Mike Weste555be862019-02-20 16:17:301070// Verify that we send only major version information in the `Sec-CH-UA` header
Yoav Weissd33bacb2020-03-12 06:42:211071// by default, regardless of opt-in.
Maks Orlovichf0a2eed2020-05-02 20:08:211072IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentVersion) {
1073 const GURL gurl = accept_ch_with_lifetime_url();
Mike Weste555be862019-02-20 16:17:301074
1075 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
1076
1077 // Navigate to a page that opts-into the header: the value should end with
1078 // the major version, and not contain the full version.
1079 SetClientHintExpectationsOnMainFrame(false);
1080 ui_test_utils::NavigateToURL(browser(), gurl);
Aaron Tagliaboschi9f01b682020-05-05 21:03:171081 std::string expected_ua = ua.SerializeBrandVersionList();
Yoav Weissd33bacb2020-03-12 06:42:211082 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1083 EXPECT_TRUE(main_frame_ua_full_version_observed().empty());
Mike Weste555be862019-02-20 16:17:301084
Yoav Weissd33bacb2020-03-12 06:42:211085 // Navigate again, after the opt-in: the value should stay the major
Mike Weste555be862019-02-20 16:17:301086 // version.
1087 SetClientHintExpectationsOnMainFrame(true);
1088 ui_test_utils::NavigateToURL(browser(), gurl);
Yoav Weissd33bacb2020-03-12 06:42:211089 std::string expected_full_version = "\"" + ua.full_version + "\"";
1090 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1091 EXPECT_EQ(main_frame_ua_full_version_observed(), expected_full_version);
Mike Weste555be862019-02-20 16:17:301092}
1093
Maks Orlovichf0a2eed2020-05-02 20:08:211094IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UAHintsTabletMode) {
1095 const GURL gurl = accept_ch_with_lifetime_url();
Maks Orlovich73f374d2020-04-02 12:46:131096
1097 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
1098
1099 // First request: only minimal hints, no tablet override.
1100 SetClientHintExpectationsOnMainFrame(false);
1101 ui_test_utils::NavigateToURL(browser(), gurl);
Aaron Tagliaboschi9f01b682020-05-05 21:03:171102 std::string expected_ua = ua.SerializeBrandVersionList();
Maks Orlovich73f374d2020-04-02 12:46:131103 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1104 EXPECT_EQ(main_frame_ua_full_version_observed(), "");
1105 EXPECT_EQ(main_frame_ua_mobile_observed(), "?0");
1106 EXPECT_EQ(main_frame_ua_platform_observed(), "");
1107
1108 // Second request: table override, all hints.
1109 chrome::ToggleRequestTabletSite(browser());
1110 SetClientHintExpectationsOnMainFrame(true);
1111 ui_test_utils::NavigateToURL(browser(), gurl);
1112 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1113 std::string expected_full_version = "\"" + ua.full_version + "\"";
1114 EXPECT_EQ(main_frame_ua_full_version_observed(), expected_full_version);
1115 EXPECT_EQ(main_frame_ua_mobile_observed(), "?1");
1116 EXPECT_EQ(main_frame_ua_platform_observed(), "\"Android\"");
1117}
1118
1119// TODO(morlovich): Move this into WebContentsImplBrowserTest once things are
1120// refactored enough that UA client hints actually work in content/
1121IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentOverrideClientHints) {
1122 content::WebContents* web_contents =
1123 browser()->tab_strip_model()->GetActiveWebContents();
1124
1125 ASSERT_TRUE(embedded_test_server()->Start());
1126 const std::string kHeaderPath = std::string("/echoheader?") +
1127 net::HttpRequestHeaders::kUserAgent +
1128 "&sec-ch-ua&sec-ch-ua-mobile";
1129 const GURL kUrl(embedded_test_server()->GetURL(kHeaderPath));
1130
1131 web_contents->SetUserAgentOverride(
1132 blink::UserAgentOverride::UserAgentOnly("foo"), false);
1133 // Not enabled first.
1134 ui_test_utils::NavigateToURL(browser(), kUrl);
1135 std::string header_value;
1136 EXPECT_TRUE(ExecuteScriptAndExtractString(
1137 web_contents,
1138 "window.domAutomationController.send(document.body.textContent);",
1139 &header_value));
1140 EXPECT_EQ(std::string::npos, header_value.find("foo")) << header_value;
1141
1142 // Actually turn it on.
1143 web_contents->GetController()
1144 .GetLastCommittedEntry()
1145 ->SetIsOverridingUserAgent(true);
1146
1147 ui_test_utils::NavigateToURL(browser(), kUrl);
1148 EXPECT_TRUE(ExecuteScriptAndExtractString(
1149 web_contents,
1150 "window.domAutomationController.send(document.body.textContent);",
1151 &header_value));
1152 // Since no value was provided for client hints, they are not sent.
1153 EXPECT_EQ("foo\nNone\nNone", header_value);
1154
1155 // Now actually provide values for the hints.
1156 blink::UserAgentOverride ua_override;
1157 ua_override.ua_string_override = "foobar";
1158 ua_override.ua_metadata_override.emplace();
1159 ua_override.ua_metadata_override->mobile = true;
Aaron Tagliaboschi9f01b682020-05-05 21:03:171160 ua_override.ua_metadata_override->brand_version_list.emplace_back(
1161 "Foobarnator", "3.14");
Maks Orlovich73f374d2020-04-02 12:46:131162 web_contents->SetUserAgentOverride(ua_override, false);
1163 ui_test_utils::NavigateToURL(browser(), kUrl);
1164 EXPECT_TRUE(ExecuteScriptAndExtractString(
1165 web_contents,
1166 "window.domAutomationController.send(document.body.textContent);",
1167 &header_value));
Aaron Tagliaboschi9f01b682020-05-05 21:03:171168 EXPECT_EQ("foobar\n\"Foobarnator\";v=\"3.14\"\n?1", header_value);
Maks Orlovich73f374d2020-04-02 12:46:131169}
1170
Maks Orlovich7a588d82020-05-06 15:17:241171IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, EmptyAcceptCH) {
1172 // First navigate to a page that enables hints. No CH for it yet, since
1173 // nothing opted in.
1174 GURL gurl = accept_ch_with_lifetime_url();
1175 SetClientHintExpectationsOnMainFrame(false);
1176 ui_test_utils::NavigateToURL(browser(), gurl);
1177
1178 // Now go to a page with blank Accept-CH. Should get hints from previous
1179 // visit.
1180 gurl = accept_ch_empty();
1181 SetClientHintExpectationsOnMainFrame(true);
1182 ui_test_utils::NavigateToURL(browser(), gurl);
1183
1184 // Visiting again should not expect them since we opted out again.
1185 SetClientHintExpectationsOnMainFrame(false);
1186 ui_test_utils::NavigateToURL(browser(), gurl);
1187}
1188
1189IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH) {
1190 // Go to page where some hints are enabled by headers, some by
1191 // http-equiv. It shouldn't get hints itself (due to first visit),
1192 // but subresources should get all the client hints.
1193 GURL gurl = http_equiv_accept_ch_merge();
1194 SetClientHintExpectationsOnMainFrame(false);
1195 SetClientHintExpectationsOnSubresources(true);
1196 ui_test_utils::NavigateToURL(browser(), gurl);
1197 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
1198}
1199
Maks Orlovich7227ce0d2020-02-28 17:13:161200void ClientHintsBrowserTest::TestProfilesIndependent(Browser* browser_a,
1201 Browser* browser_b) {
Maks Orlovichf0a2eed2020-05-02 20:08:211202 const GURL gurl = accept_ch_with_lifetime_url();
Maks Orlovich7227ce0d2020-02-28 17:13:161203
1204 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
1205
1206 // Navigate |browser_a| to a page that opts-into the header: the value should
1207 // end with the major version, and not contain the full version.
1208 SetClientHintExpectationsOnMainFrame(false);
1209 ui_test_utils::NavigateToURL(browser_a, gurl);
Aaron Tagliaboschi9f01b682020-05-05 21:03:171210 std::string expected_ua = ua.SerializeBrandVersionList();
Yoav Weissd33bacb2020-03-12 06:42:211211 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1212 EXPECT_TRUE(main_frame_ua_full_version_observed().empty());
Maks Orlovich7227ce0d2020-02-28 17:13:161213
1214 // Try again on |browser_a|, the header should have an effect there.
1215 SetClientHintExpectationsOnMainFrame(true);
1216 ui_test_utils::NavigateToURL(browser_a, gurl);
Yoav Weissd33bacb2020-03-12 06:42:211217 std::string expected_full_version = "\"" + ua.full_version + "\"";
1218 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1219 EXPECT_EQ(main_frame_ua_full_version_observed(), expected_full_version);
Maks Orlovich7227ce0d2020-02-28 17:13:161220
1221 // Navigate on |browser_b|. That should still only have the major
1222 // version.
1223 SetClientHintExpectationsOnMainFrame(false);
1224 ui_test_utils::NavigateToURL(browser_b, gurl);
Yoav Weissd33bacb2020-03-12 06:42:211225 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1226 EXPECT_TRUE(main_frame_ua_full_version_observed().empty());
Maks Orlovich7227ce0d2020-02-28 17:13:161227}
1228
1229// Check that client hints attached to navigation inside OTR profiles
1230// use the right settings, regular -> OTR direction.
Maks Orlovichf0a2eed2020-05-02 20:08:211231IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent) {
Maks Orlovich7227ce0d2020-02-28 17:13:161232 TestProfilesIndependent(browser(),
1233 CreateIncognitoBrowser(browser()->profile()));
1234}
1235
1236// Check that client hints attached to navigation inside OTR profiles
1237// use the right settings, OTR -> regular direction.
Maks Orlovichf0a2eed2020-05-02 20:08:211238IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent2) {
Maks Orlovich7227ce0d2020-02-28 17:13:161239 TestProfilesIndependent(CreateIncognitoBrowser(browser()->profile()),
1240 browser());
1241}
1242
Tarun Bansalea0d8262018-05-21 16:11:501243// Test that client hints are attached to third party subresources if
1244// AllowClientHintsToThirdParty feature is enabled.
Tarun Bansal9a7051f2018-07-10 18:30:051245IN_PROC_BROWSER_TEST_P(ClientHintsAllowThirdPartyBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:501246 ClientHintsThirdPartyAllowed) {
Yoav Weiss76e1afb762020-05-14 19:28:121247 GURL gurl;
1248 unsigned update_event_count = 0;
1249 if (GetParam()) {
1250 gurl = http_equiv_accept_ch_without_lifetime_img_localhost();
1251 } else {
1252 gurl = accept_ch_without_lifetime_img_localhost();
1253 update_event_count = 1;
1254 }
Tarun Bansal9a7051f2018-07-10 18:30:051255
Tarun Bansalea0d8262018-05-21 16:11:501256 base::HistogramTester histogram_tester;
1257
1258 SetClientHintExpectationsOnMainFrame(false);
1259 SetClientHintExpectationsOnSubresources(true);
1260
1261 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:051262 ui_test_utils::NavigateToURL(browser(), gurl);
Yoav Weiss76e1afb762020-05-14 19:28:121263 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount",
1264 update_event_count);
Tarun Bansalea0d8262018-05-21 16:11:501265
Yoav Weissd33bacb2020-03-12 06:42:211266 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:501267
1268 // Requests to third party servers should not have client hints attached.
1269 EXPECT_EQ(1u, third_party_request_count_seen());
1270
Aaron Tagliaboschia09ec442019-09-18 15:29:031271 // Device memory, viewport width, DRP, and UA client hints should be sent to
1272 // the third-party when feature "AllowClientHintsToThirdParty" is enabled.
Maks Orlovich5dcc99c2020-02-13 19:07:461273 EXPECT_EQ(5u, third_party_client_hints_count_seen());
Tarun Bansalea0d8262018-05-21 16:11:501274}
1275
1276// Test that client hints are not attached to third party subresources if
1277// AllowClientHintsToThirdParty feature is not enabled.
Tarun Bansal9a7051f2018-07-10 18:30:051278IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:501279 ClientHintsThirdPartyNotAllowed) {
Yoav Weiss76e1afb762020-05-14 19:28:121280 GURL gurl;
1281 unsigned update_event_count = 0;
1282 if (GetParam()) {
1283 gurl = http_equiv_accept_ch_without_lifetime_img_localhost();
1284 } else {
1285 gurl = accept_ch_without_lifetime_img_localhost();
1286 update_event_count = 1;
1287 }
Tarun Bansal9a7051f2018-07-10 18:30:051288
Tarun Bansalea0d8262018-05-21 16:11:501289 base::HistogramTester histogram_tester;
1290
1291 SetClientHintExpectationsOnMainFrame(false);
1292 SetClientHintExpectationsOnSubresources(true);
1293
1294 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:051295 ui_test_utils::NavigateToURL(browser(), gurl);
Yoav Weiss76e1afb762020-05-14 19:28:121296 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount",
1297 update_event_count);
Tarun Bansalea0d8262018-05-21 16:11:501298
Mike West2fddeeb72019-02-15 11:29:481299 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461300 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:211301 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:501302
1303 // Requests to third party servers should not have client hints attached.
1304 EXPECT_EQ(1u, third_party_request_count_seen());
1305
1306 // Client hints should not be sent to the third-party when feature
Mike West2fddeeb72019-02-15 11:29:481307 // "AllowClientHintsToThirdParty" is not enabled, with the exception of the
1308 // `Sec-CH-UA` hint, which is sent with every request.
Maks Orlovich5dcc99c2020-02-13 19:07:461309 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansalea0d8262018-05-21 16:11:501310}
1311
Tarun Bansaladd5e1812018-02-09 19:07:581312// Loads a HTTPS webpage that does not request persisting of client hints.
Tarun Bansal345418632018-06-29 11:07:041313// A same-origin iframe loaded by the webpage requests persistence of client
Maks Orlovich46619c732020-05-07 10:40:531314// hints. Since that's not a main frame, persistence should not happen.
Maks Orlovichf0a2eed2020-05-02 20:08:211315IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:041316 PersistenceRequestIframe_SameOrigin) {
Maks Orlovichf0a2eed2020-05-02 20:08:211317 const GURL gurl = accept_ch_without_lifetime_with_iframe_url();
Tarun Bansal345418632018-06-29 11:07:041318 base::HistogramTester histogram_tester;
1319 ContentSettingsForOneType host_settings;
1320
1321 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451322 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal345418632018-06-29 11:07:041323 &host_settings);
1324 EXPECT_EQ(0u, host_settings.size());
1325
Tarun Bansal9a7051f2018-07-10 18:30:051326 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal345418632018-06-29 11:07:041327
Maks Orlovich46619c732020-05-07 10:40:531328 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
Tarun Bansal345418632018-06-29 11:07:041329
1330 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281331 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal345418632018-06-29 11:07:041332
1333 // accept_ch_without_lifetime_with_iframe_url() loads
1334 // accept_ch_with_lifetime() in an iframe. The request to persist client
Maks Orlovich46619c732020-05-07 10:40:531335 // hints from accept_ch_with_lifetime() should not be persisted.
1336 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1337 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
Tarun Bansal345418632018-06-29 11:07:041338}
1339
1340// Loads a HTTPS webpage that does not request persisting of client hints.
1341// An iframe loaded by the webpage from an cross origin server requests
1342// persistence of client hints.
1343// Verify that the request from the cross origin iframe is not honored, and
1344// client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051345IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:041346 DisregardPersistenceRequestIframe_CrossOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:051347 const GURL gurl =
1348 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
1349 : accept_ch_without_lifetime_with_iframe_url();
1350
1351 intercept_iframe_resource_ = gurl.path();
1352 intercept_to_http_equiv_iframe_ = GetParam();
1353
Tarun Bansaladd5e1812018-02-09 19:07:581354 base::HistogramTester histogram_tester;
1355 ContentSettingsForOneType host_settings;
1356
1357 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451358 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansaladd5e1812018-02-09 19:07:581359 &host_settings);
1360 EXPECT_EQ(0u, host_settings.size());
1361
Tarun Bansal9a7051f2018-07-10 18:30:051362 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:581363
1364 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1365
1366 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281367 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansaladd5e1812018-02-09 19:07:581368
1369 // accept_ch_without_lifetime_with_iframe_url() loads
Tarun Bansal345418632018-06-29 11:07:041370 // accept_ch_with_lifetime() in a cross origin iframe. The request to persist
1371 // client hints from accept_ch_with_lifetime() should be disregarded.
Tarun Bansaladd5e1812018-02-09 19:07:581372 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1373 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1374}
1375
Tarun Bansal62cc3542018-06-27 23:53:301376// Loads a HTTPS webpage that does not request persisting of client hints.
1377// A subresource loaded by the webpage requests persistence of client hints.
1378// Verify that the request from the subresource is not honored, and client hints
1379// preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051380IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:301381 DisregardPersistenceRequestSubresource) {
Tarun Bansal9a7051f2018-07-10 18:30:051382 const GURL gurl =
1383 GetParam() ? http_equiv_accept_ch_without_lifetime_with_subresource_url()
1384 : accept_ch_without_lifetime_with_subresource_url();
1385
Tarun Bansal62cc3542018-06-27 23:53:301386 base::HistogramTester histogram_tester;
1387 ContentSettingsForOneType host_settings;
1388
1389 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451390 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal62cc3542018-06-27 23:53:301391 &host_settings);
1392 EXPECT_EQ(0u, host_settings.size());
1393
Tarun Bansal9a7051f2018-07-10 18:30:051394 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:301395
1396 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1397
1398 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281399 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal62cc3542018-06-27 23:53:301400
1401 // accept_ch_without_lifetime_with_subresource_url() loads
1402 // accept_ch_with_lifetime() as a subresource. The request to persist client
1403 // hints from accept_ch_with_lifetime() should be disregarded.
1404 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1405 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1406}
1407
1408// Loads a HTTPS webpage that does not request persisting of client hints.
1409// A subresource loaded by the webpage in an iframe requests persistence of
1410// client hints. Verify that the request from the subresource in the iframe
1411// is not honored, and client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051412IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:301413 DisregardPersistenceRequestSubresourceIframe) {
Tarun Bansal9a7051f2018-07-10 18:30:051414 const GURL gurl =
1415 GetParam()
1416 ? http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url()
1417 : accept_ch_without_lifetime_with_subresource_iframe_url();
1418
Tarun Bansal62cc3542018-06-27 23:53:301419 base::HistogramTester histogram_tester;
1420 ContentSettingsForOneType host_settings;
1421
1422 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451423 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal62cc3542018-06-27 23:53:301424 &host_settings);
1425 EXPECT_EQ(0u, host_settings.size());
1426
Tarun Bansal9a7051f2018-07-10 18:30:051427 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:301428
1429 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1430
1431 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281432 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal62cc3542018-06-27 23:53:301433
Tarun Bansal9a7051f2018-07-10 18:30:051434 // |gurl| loads accept_ch_with_lifetime() or
1435 // http_equiv_accept_ch_with_lifetime() as a subresource in an iframe. The
1436 // request to persist client hints from accept_ch_with_lifetime() or
1437 // http_equiv_accept_ch_with_lifetime() should be disregarded.
Tarun Bansal62cc3542018-06-27 23:53:301438 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1439 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1440}
1441
Tarun Bansal3b330b02017-11-09 19:03:141442// Loads a HTTP local webpage (which qualifies as a secure context) that
1443// requests persisting of client hints. Verifies that the browser receives the
1444// mojo notification from the renderer and persists the client hints to the
1445// disk.
Maks Orlovichf0a2eed2020-05-02 20:08:211446IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal3b330b02017-11-09 19:03:141447 ClientHintsLifetimeFollowedByNoClientHintHttpLocal) {
Maks Orlovichf0a2eed2020-05-02 20:08:211448 const GURL gurl = accept_ch_with_lifetime_http_local_url();
Tarun Bansal9a7051f2018-07-10 18:30:051449
Tarun Bansal3b330b02017-11-09 19:03:141450 base::HistogramTester histogram_tester;
1451 ContentSettingsForOneType host_settings;
1452
1453 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451454 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3b330b02017-11-09 19:03:141455 &host_settings);
1456 EXPECT_EQ(0u, host_settings.size());
1457
Tarun Bansal9a7051f2018-07-10 18:30:051458 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal3b330b02017-11-09 19:03:141459
1460 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1461
1462 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281463 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal3b330b02017-11-09 19:03:141464
Yoav Weissd33bacb2020-03-12 06:42:211465 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1466 expected_client_hints_number, 1);
Yoav Weiss76e1afb762020-05-14 19:28:121467 // |gurl| sets client hints persist duration to 3600 seconds, but a maximum
1468 // value is registered instead.
Tarun Bansal3b330b02017-11-09 19:03:141469 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:121470 uma_histogram_max_value, 1);
Tarun Bansal3b330b02017-11-09 19:03:141471
1472 base::RunLoop().RunUntilIdle();
1473
1474 // Clients hints preferences for one origin should be persisted.
1475 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451476 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3b330b02017-11-09 19:03:141477 &host_settings);
1478 EXPECT_EQ(1u, host_settings.size());
1479
Tarun Bansal229647bd002018-02-27 17:33:361480 SetClientHintExpectationsOnMainFrame(true);
1481 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal3b330b02017-11-09 19:03:141482 ui_test_utils::NavigateToURL(browser(),
1483 without_accept_ch_without_lifetime_local_url());
1484
Mike West2fddeeb72019-02-15 11:29:481485 // The user agent hint is attached to all three requests:
1486 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461487 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481488
Yoav Weissd33bacb2020-03-12 06:42:211489 // Expected number of hints attached to the image request, and the same number
1490 // to the main frame request.
1491 EXPECT_EQ(expected_client_hints_number * 2,
1492 count_client_hints_headers_seen());
Tarun Bansal3b330b02017-11-09 19:03:141493}
1494
Tarun Bansal0b8b7afd2017-08-25 03:52:161495// Loads a webpage that does not request persisting of client hints.
1496IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {
1497 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:191498 ui_test_utils::NavigateToURL(browser(),
1499 without_accept_ch_without_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:161500
1501 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1502
1503 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281504 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal0b8b7afd2017-08-25 03:52:161505
1506 // no_client_hints_url() does not sets the client hints.
1507 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1508 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1509}
1510
Tarun Bansal9a7051f2018-07-10 18:30:051511IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal1965b042017-09-07 04:59:191512 ClientHintsLifetimeFollowedByNoClientHint) {
Tarun Bansal9a7051f2018-07-10 18:30:051513 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1514 : accept_ch_with_lifetime_url();
1515
Tarun Bansal1965b042017-09-07 04:59:191516 base::HistogramTester histogram_tester;
1517 ContentSettingsForOneType host_settings;
1518
1519 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451520 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191521 &host_settings);
1522 EXPECT_EQ(0u, host_settings.size());
1523
Maks Orlovichf0a2eed2020-05-02 20:08:211524 // Fetching |gurl| should persist the request for client hints iff using
1525 // headers and not http-equiv.
Tarun Bansal9a7051f2018-07-10 18:30:051526 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal1965b042017-09-07 04:59:191527
Maks Orlovichf0a2eed2020-05-02 20:08:211528 if (GetParam())
1529 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1530 else
1531 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
Tarun Bansal1965b042017-09-07 04:59:191532
1533 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281534 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal1965b042017-09-07 04:59:191535 base::RunLoop().RunUntilIdle();
1536
Maks Orlovichf0a2eed2020-05-02 20:08:211537 if (GetParam()) {
1538 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1539 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1540 } else {
1541 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1542 expected_client_hints_number, 1);
1543 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
Yoav Weiss76e1afb762020-05-14 19:28:121544 // seconds, but a maximum value is registered instead.
Maks Orlovichf0a2eed2020-05-02 20:08:211545 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:121546 uma_histogram_max_value, 1);
Tarun Bansal1965b042017-09-07 04:59:191547
Maks Orlovichf0a2eed2020-05-02 20:08:211548 // Clients hints preferences for one origin should be persisted.
1549 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1550 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
1551 std::string(), &host_settings);
1552 EXPECT_EQ(1u, host_settings.size());
1553 }
1554
1555 SetClientHintExpectationsOnMainFrame(!GetParam());
1556 SetClientHintExpectationsOnSubresources(!GetParam());
Tarun Bansal1965b042017-09-07 04:59:191557 ui_test_utils::NavigateToURL(browser(),
1558 without_accept_ch_without_lifetime_url());
Tarun Bansal6bf54302017-10-02 07:39:141559
Mike West2fddeeb72019-02-15 11:29:481560 // The user agent hint is attached to all three requests:
1561 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461562 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481563
Yoav Weissd33bacb2020-03-12 06:42:211564 // Expected number of hints attached to the image request, and the same number
1565 // to the main frame request.
Maks Orlovichf0a2eed2020-05-02 20:08:211566 EXPECT_EQ(GetParam() ? 0 : expected_client_hints_number * 2,
Yoav Weissd33bacb2020-03-12 06:42:211567 count_client_hints_headers_seen());
Tarun Bansal1965b042017-09-07 04:59:191568}
1569
Tarun Bansal293a7b6c2018-12-05 17:41:121570// The test first fetches a page that sets Accept-CH-Lifetime. Next, it fetches
1571// a URL from a different origin. However, that URL response redirects to the
1572// same origin from where the first page was fetched. The test verifies that
1573// on receiving redirect to an origin for which the browser has persisted client
1574// hints prefs, the browser attaches the client hints headers when fetching the
1575// redirected URL.
Maks Orlovichf0a2eed2020-05-02 20:08:211576IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal293a7b6c2018-12-05 17:41:121577 ClientHintsLifetimeFollowedByRedirectToNoClientHint) {
Maks Orlovichf0a2eed2020-05-02 20:08:211578 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal293a7b6c2018-12-05 17:41:121579
1580 base::HistogramTester histogram_tester;
1581 ContentSettingsForOneType host_settings;
1582
1583 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451584 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal293a7b6c2018-12-05 17:41:121585 &host_settings);
1586 EXPECT_EQ(0u, host_settings.size());
1587
1588 // Fetching |gurl| should persist the request for client hints.
1589 ui_test_utils::NavigateToURL(browser(), gurl);
1590
1591 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1592
1593 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281594 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal293a7b6c2018-12-05 17:41:121595
Yoav Weissd33bacb2020-03-12 06:42:211596 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1597 expected_client_hints_number, 1);
Tarun Bansal293a7b6c2018-12-05 17:41:121598 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
Yoav Weiss76e1afb762020-05-14 19:28:121599 // seconds, but a maximum value is registered instead.
Tarun Bansal293a7b6c2018-12-05 17:41:121600 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:121601 uma_histogram_max_value, 1);
Tarun Bansal293a7b6c2018-12-05 17:41:121602 base::RunLoop().RunUntilIdle();
1603
1604 // Clients hints preferences for one origin should be persisted.
1605 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451606 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal293a7b6c2018-12-05 17:41:121607 &host_settings);
1608 EXPECT_EQ(1u, host_settings.size());
1609
1610 SetClientHintExpectationsOnMainFrame(true);
1611 SetClientHintExpectationsOnSubresources(true);
1612 ui_test_utils::NavigateToURL(browser(), redirect_url());
1613
Mike West2fddeeb72019-02-15 11:29:481614 // The user agent hint is attached to all three requests:
1615 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461616 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481617
Yoav Weissd33bacb2020-03-12 06:42:211618 // Expected number of hints attached to the image request, and the same number
1619 // to the main frame request.
1620 EXPECT_EQ(expected_client_hints_number * 2,
1621 count_client_hints_headers_seen());
Tarun Bansal293a7b6c2018-12-05 17:41:121622}
1623
Tarun Bansala0c1fc32018-10-03 16:14:521624// Ensure that even when cookies are blocked, client hint preferences are
Tarun Bansala61f0f62017-10-24 23:53:051625// persisted.
Maks Orlovichf0a2eed2020-05-02 20:08:211626IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521627 ClientHintsLifetimePersistedCookiesBlocked) {
Maks Orlovichf0a2eed2020-05-02 20:08:211628 const GURL gurl_with = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:051629
Tarun Bansala61f0f62017-10-24 23:53:051630 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1631 CookieSettingsFactory::GetForProfile(browser()->profile());
1632 base::HistogramTester histogram_tester;
1633 ContentSettingsForOneType host_settings;
1634
1635 // Block cookies.
1636 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansala0c1fc32018-10-03 16:14:521637 ->SetContentSettingDefaultScope(gurl_with, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451638 ContentSettingsType::COOKIES,
Tarun Bansala61f0f62017-10-24 23:53:051639 std::string(), CONTENT_SETTING_BLOCK);
1640
Tarun Bansala0c1fc32018-10-03 16:14:521641 // Fetching |gurl_with| should persist the request for client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051642 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala0c1fc32018-10-03 16:14:521643 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
Tarun Bansala61f0f62017-10-24 23:53:051644 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451645 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051646 &host_settings);
1647 EXPECT_EQ(1u, host_settings.size());
Tarun Bansala0c1fc32018-10-03 16:14:521648 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051649}
1650
Maks Orlovichf0a2eed2020-05-02 20:08:211651IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521652 ClientHintsLifetimeAttachedCookiesBlocked) {
Maks Orlovichf0a2eed2020-05-02 20:08:211653 const GURL gurl_with = accept_ch_with_lifetime_url();
1654 const GURL gurl_without = accept_ch_without_lifetime_url();
Tarun Bansala61f0f62017-10-24 23:53:051655 base::HistogramTester histogram_tester;
1656 ContentSettingsForOneType host_settings;
1657
1658 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451659 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051660 &host_settings);
1661 EXPECT_EQ(0u, host_settings.size());
1662
Tarun Bansal9a7051f2018-07-10 18:30:051663 // Fetching |gurl_with| should persist the request for client hints.
1664 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala61f0f62017-10-24 23:53:051665 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1666 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281667 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Maks Orlovichf0a2eed2020-05-02 20:08:211668 base::RunLoop().RunUntilIdle();
Tarun Bansala61f0f62017-10-24 23:53:051669
Yoav Weissd33bacb2020-03-12 06:42:211670 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1671 expected_client_hints_number, 1);
Yoav Weiss76e1afb762020-05-14 19:28:121672 // |gurl_with| tries to set client hints persist duration to 3600 seconds, but
1673 // a maximum value is registered instead.
Tarun Bansala61f0f62017-10-24 23:53:051674 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:121675 uma_histogram_max_value, 1);
Tarun Bansala61f0f62017-10-24 23:53:051676
1677 // Clients hints preferences for one origin should be persisted.
1678 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451679 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051680 &host_settings);
1681 EXPECT_EQ(1u, host_settings.size());
1682
Tarun Bansala0c1fc32018-10-03 16:14:521683 // Block the cookies: Client hints should be attached.
Tarun Bansala61f0f62017-10-24 23:53:051684 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051685 ->SetContentSettingDefaultScope(gurl_without, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451686 ContentSettingsType::COOKIES,
Tarun Bansala61f0f62017-10-24 23:53:051687 std::string(), CONTENT_SETTING_BLOCK);
1688
Tarun Bansal229647bd002018-02-27 17:33:361689 SetClientHintExpectationsOnMainFrame(true);
1690 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051691 ui_test_utils::NavigateToURL(browser(),
1692 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361693
Mike West2fddeeb72019-02-15 11:29:481694 // The user agent hint is attached to all three requests:
1695 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461696 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481697
Yoav Weissd33bacb2020-03-12 06:42:211698 // Expected number of hints attached to the image request, and the same number
1699 // to the main frame request.
1700 EXPECT_EQ(expected_client_hints_number * 2,
1701 count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051702
1703 // Clear settings.
1704 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451705 ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
Tarun Bansala61f0f62017-10-24 23:53:051706}
1707
1708// Ensure that when the JavaScript is blocked, client hint preferences are not
1709// persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051710IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051711 ClientHintsLifetimeNotPersistedJavaScriptBlocked) {
1712 ContentSettingsForOneType host_settings;
1713
1714 // Start a navigation. This navigation makes it possible to block JavaScript
1715 // later.
1716 ui_test_utils::NavigateToURL(browser(),
1717 without_accept_ch_without_lifetime_url());
1718
Tarun Bansal9a7051f2018-07-10 18:30:051719 const GURL gurl =
1720 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
1721 : accept_ch_with_lifetime_url();
1722
Tarun Bansala61f0f62017-10-24 23:53:051723 // Block the JavaScript: Client hint preferences should not be persisted.
1724 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051725 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451726 ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051727 std::string(), CONTENT_SETTING_BLOCK);
1728 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1729 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451730 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051731 &host_settings);
1732 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:581733 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051734
1735 // Allow the JavaScript: Client hint preferences should be persisted.
1736 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051737 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451738 ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051739 std::string(), CONTENT_SETTING_ALLOW);
1740 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1741 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451742 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051743 &host_settings);
1744 EXPECT_EQ(1u, host_settings.size());
Tarun Bansal593790112018-03-20 04:53:341745
1746 // Clear settings.
1747 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451748 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:051749}
1750
1751// Ensure that when the JavaScript is blocked, persisted client hints are not
1752// attached to the request headers.
Maks Orlovichf0a2eed2020-05-02 20:08:211753IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051754 ClientHintsLifetimeNotAttachedJavaScriptBlocked) {
Maks Orlovichf0a2eed2020-05-02 20:08:211755 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:051756
Tarun Bansala61f0f62017-10-24 23:53:051757 base::HistogramTester histogram_tester;
1758 ContentSettingsForOneType host_settings;
1759
1760 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451761 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051762 &host_settings);
1763 EXPECT_EQ(0u, host_settings.size());
1764
1765 // Fetching accept_ch_with_lifetime_url() should persist the request for
1766 // client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051767 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansala61f0f62017-10-24 23:53:051768 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1769 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:281770 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Mike West2fddeeb72019-02-15 11:29:481771 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461772 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051773
Yoav Weissd33bacb2020-03-12 06:42:211774 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1775 expected_client_hints_number, 1);
Tarun Bansala61f0f62017-10-24 23:53:051776 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
Yoav Weiss76e1afb762020-05-14 19:28:121777 // 3600 seconds, but a maximum value is registered instead.
Tarun Bansala61f0f62017-10-24 23:53:051778 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:121779 uma_histogram_max_value, 1);
Tarun Bansala61f0f62017-10-24 23:53:051780 base::RunLoop().RunUntilIdle();
1781
1782 // Clients hints preferences for one origin should be persisted.
1783 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451784 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051785 &host_settings);
1786 EXPECT_EQ(1u, host_settings.size());
1787
Changwan Ryu434c3a32019-07-30 23:42:581788 // Block JavaScript via WebPreferences: Client hints should not be attached.
1789 SetJsEnabledForActiveView(false);
1790
1791 SetClientHintExpectationsOnMainFrame(false);
1792 SetClientHintExpectationsOnSubresources(false);
1793 ui_test_utils::NavigateToURL(browser(),
1794 without_accept_ch_without_lifetime_url());
1795
1796 EXPECT_EQ(0u, count_client_hints_headers_seen());
1797 VerifyContentSettingsNotNotified();
1798 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461799 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Changwan Ryu434c3a32019-07-30 23:42:581800
1801 SetJsEnabledForActiveView(true);
1802
1803 // Block JavaScript via ContentSetting: Client hints should not be attached.
Tarun Bansala61f0f62017-10-24 23:53:051804 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1805 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
Darin Fisher42f5e7d2019-10-30 07:15:451806 GURL(), ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051807 std::string(), CONTENT_SETTING_BLOCK);
1808 ui_test_utils::NavigateToURL(browser(),
1809 without_accept_ch_without_lifetime_url());
1810 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581811 VerifyContentSettingsNotNotified();
Mike West2fddeeb72019-02-15 11:29:481812 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461813 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051814
Changwan Ryu434c3a32019-07-30 23:42:581815 // Allow JavaScript: Client hints should now be attached.
Tarun Bansala61f0f62017-10-24 23:53:051816 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1817 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
Darin Fisher42f5e7d2019-10-30 07:15:451818 GURL(), ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051819 std::string(), CONTENT_SETTING_ALLOW);
1820
Tarun Bansal229647bd002018-02-27 17:33:361821 SetClientHintExpectationsOnMainFrame(true);
1822 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051823 ui_test_utils::NavigateToURL(browser(),
1824 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361825
Mike West2fddeeb72019-02-15 11:29:481826 // The user agent hint is attached to all three requests:
1827 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461828 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481829
Yoav Weissd33bacb2020-03-12 06:42:211830 // Expected number of hints attached to the image request, and the same number
1831 // to the main frame request.
1832 EXPECT_EQ(expected_client_hints_number * 2,
1833 count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051834
1835 // Clear settings.
1836 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451837 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:051838}
1839
Tarun Bansal73502f92019-04-16 21:21:191840// Test that if the content settings are malformed, then the browser does not
1841// crash.
1842IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
1843 ClientHintsMalformedContentSettings) {
1844 ContentSettingsForOneType client_hints_settings;
1845 HostContentSettingsMap* host_content_settings_map =
1846 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
1847
1848 // Add setting for the host.
1849 std::unique_ptr<base::ListValue> expiration_times_list =
1850 std::make_unique<base::ListValue>();
1851 expiration_times_list->AppendInteger(42 /* client hint value */);
1852 auto expiration_times_dictionary = std::make_unique<base::DictionaryValue>();
1853 expiration_times_dictionary->SetList("client_hints",
1854 std::move(expiration_times_list));
Aaron Tagliaboschi3c96a682019-10-29 18:10:281855 expiration_times_dictionary->SetDouble(
1856 "expiration_time",
1857 (base::Time::Now() + base::TimeDelta::FromDays(1)).ToDoubleT());
Tarun Bansal73502f92019-04-16 21:21:191858 host_content_settings_map->SetWebsiteSettingDefaultScope(
1859 without_accept_ch_without_lifetime_url(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451860 ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal73502f92019-04-16 21:21:191861 std::make_unique<base::Value>(expiration_times_dictionary->Clone()));
1862
1863 // Reading the settings should now return one setting.
1864 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:451865 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansal73502f92019-04-16 21:21:191866 EXPECT_EQ(1U, client_hints_settings.size());
1867
1868 SetClientHintExpectationsOnMainFrame(false);
1869 SetClientHintExpectationsOnSubresources(false);
1870 ui_test_utils::NavigateToURL(browser(),
1871 without_accept_ch_without_lifetime_url());
1872}
1873
Tarun Bansal229647bd002018-02-27 17:33:361874// Ensure that when the JavaScript is blocked, client hints requested using
Tarun Bansal3f343d7c2018-03-02 18:48:001875// Accept-CH are not attached to the request headers for subresources.
Tarun Bansal9a7051f2018-07-10 18:30:051876IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal229647bd002018-02-27 17:33:361877 ClientHintsNoLifetimeScriptNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051878 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1879 : accept_ch_with_lifetime_url();
1880
Tarun Bansal1965b042017-09-07 04:59:191881 base::HistogramTester histogram_tester;
1882 ContentSettingsForOneType host_settings;
1883
1884 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451885 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191886 &host_settings);
1887 EXPECT_EQ(0u, host_settings.size());
1888
Tarun Bansal3f343d7c2018-03-02 18:48:001889 // Block the Javascript: Client hints should not be attached.
1890 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361891 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1892 ->SetContentSettingDefaultScope(
1893 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451894 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361895 CONTENT_SETTING_BLOCK);
1896 ui_test_utils::NavigateToURL(browser(),
1897 accept_ch_without_lifetime_img_localhost());
Mike West2fddeeb72019-02-15 11:29:481898 EXPECT_EQ(0u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461899 EXPECT_EQ(0u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001900 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361901 EXPECT_EQ(1u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001902 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal1965b042017-09-07 04:59:191903
Tarun Bansal3f343d7c2018-03-02 18:48:001904 // Allow the Javascript: Client hints should now be attached.
Tarun Bansal229647bd002018-02-27 17:33:361905 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1906 ->SetContentSettingDefaultScope(
1907 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451908 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361909 CONTENT_SETTING_ALLOW);
Tarun Bansal1965b042017-09-07 04:59:191910
Tarun Bansal229647bd002018-02-27 17:33:361911 SetClientHintExpectationsOnSubresources(true);
1912 ui_test_utils::NavigateToURL(browser(),
1913 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:001914
Mike West2fddeeb72019-02-15 11:29:481915 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461916 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Aaron Tagliaboschi150fb9042020-05-14 22:20:371917 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361918 EXPECT_EQ(2u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461919 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581920 VerifyContentSettingsNotNotified();
Tarun Bansal1965b042017-09-07 04:59:191921
Tarun Bansal229647bd002018-02-27 17:33:361922 // Clear settings.
1923 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451924 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansal1965b042017-09-07 04:59:191925
Tarun Bansal229647bd002018-02-27 17:33:361926 // Block the Javascript again: Client hints should not be attached.
Tarun Bansal3f343d7c2018-03-02 18:48:001927 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361928 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1929 ->SetContentSettingDefaultScope(
1930 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451931 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361932 CONTENT_SETTING_BLOCK);
1933 ui_test_utils::NavigateToURL(browser(),
1934 accept_ch_without_lifetime_img_localhost());
Mike West2fddeeb72019-02-15 11:29:481935 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461936 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Aaron Tagliaboschi150fb9042020-05-14 22:20:371937 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361938 EXPECT_EQ(3u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461939 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341940
1941 // Clear settings.
1942 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451943 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansal229647bd002018-02-27 17:33:361944}
1945
Tarun Bansala0c1fc32018-10-03 16:14:521946// Ensure that when the cookies is blocked, client hints are attached to the
Tarun Bansal3f343d7c2018-03-02 18:48:001947// request headers.
Tarun Bansal9a7051f2018-07-10 18:30:051948IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521949 ClientHintsLifetimeCookiesNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051950 const GURL gurl = GetParam()
1951 ? http_equiv_accept_ch_without_lifetime_img_localhost()
1952 : accept_ch_without_lifetime_img_localhost();
1953
Tarun Bansal229647bd002018-02-27 17:33:361954 base::HistogramTester histogram_tester;
1955 ContentSettingsForOneType host_settings;
1956 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1957 CookieSettingsFactory::GetForProfile(browser()->profile());
1958
Tarun Bansal1965b042017-09-07 04:59:191959 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451960 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191961 &host_settings);
1962 EXPECT_EQ(0u, host_settings.size());
1963
Tarun Bansal229647bd002018-02-27 17:33:361964 // Block cookies.
1965 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051966 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451967 ContentSettingsType::COOKIES,
Tarun Bansal9a7051f2018-07-10 18:30:051968 std::string(), CONTENT_SETTING_BLOCK);
Tarun Bansal229647bd002018-02-27 17:33:361969 base::RunLoop().RunUntilIdle();
1970
Tarun Bansal229647bd002018-02-27 17:33:361971 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal9a7051f2018-07-10 18:30:051972 ui_test_utils::NavigateToURL(browser(), gurl);
Mike West2fddeeb72019-02-15 11:29:481973 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461974 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:211975 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansala0c1fc32018-10-03 16:14:521976 EXPECT_EQ(1u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461977 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341978
1979 // Clear settings.
1980 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451981 ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
Tarun Bansal1965b042017-09-07 04:59:191982}
1983
Tarun Bansal3ce0ca42018-06-25 22:52:221984// Verify that client hints are sent in the incognito profiles, and server
1985// client hint opt-ins are honored within the incognito profile.
Maks Orlovichf0a2eed2020-05-02 20:08:211986IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal3ce0ca42018-06-25 22:52:221987 ClientHintsLifetimeFollowedByNoClientHintIncognito) {
Maks Orlovichf0a2eed2020-05-02 20:08:211988 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:051989
Tarun Bansal3ce0ca42018-06-25 22:52:221990 base::HistogramTester histogram_tester;
1991 Browser* incognito = CreateIncognitoBrowser();
1992 ContentSettingsForOneType host_settings;
1993
1994 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451995 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3ce0ca42018-06-25 22:52:221996 &host_settings);
1997 EXPECT_EQ(0u, host_settings.size());
1998
Tarun Bansal9a7051f2018-07-10 18:30:051999 // Fetching |gurl| should persist the request for client hints.
2000 ui_test_utils::NavigateToURL(incognito, gurl);
Tarun Bansal3ce0ca42018-06-25 22:52:222001
2002 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
2003
2004 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:282005 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal3ce0ca42018-06-25 22:52:222006
Yoav Weissd33bacb2020-03-12 06:42:212007 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
2008 expected_client_hints_number, 1);
Tarun Bansal3ce0ca42018-06-25 22:52:222009 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
Yoav Weiss76e1afb762020-05-14 19:28:122010 // seconds, but a maximum value is registered instead.
Tarun Bansal3ce0ca42018-06-25 22:52:222011 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
Yoav Weiss76e1afb762020-05-14 19:28:122012 uma_histogram_max_value, 1);
Tarun Bansal3ce0ca42018-06-25 22:52:222013 base::RunLoop().RunUntilIdle();
2014
2015 // Clients hints preferences for one origin should be persisted.
2016 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
Darin Fisher42f5e7d2019-10-30 07:15:452017 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3ce0ca42018-06-25 22:52:222018 &host_settings);
2019 EXPECT_EQ(1u, host_settings.size());
2020
2021 SetClientHintExpectationsOnMainFrame(true);
2022 SetClientHintExpectationsOnSubresources(true);
2023 ui_test_utils::NavigateToURL(incognito,
2024 without_accept_ch_without_lifetime_url());
2025
Mike West2fddeeb72019-02-15 11:29:482026 // The user agent hint is attached to all three requests:
2027 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:462028 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:482029
Yoav Weissd33bacb2020-03-12 06:42:212030 // Expected number of hints attached to the image request, and the same number
2031 // to the main frame request.
2032 EXPECT_EQ(expected_client_hints_number * 2,
2033 count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:222034
2035 // Navigate using regular profile. Client hints should not be send.
2036 SetClientHintExpectationsOnMainFrame(false);
2037 SetClientHintExpectationsOnSubresources(false);
2038 ui_test_utils::NavigateToURL(browser(),
2039 without_accept_ch_without_lifetime_url());
2040
Mike West2fddeeb72019-02-15 11:29:482041 // The user agent hint is attached to the two new requests.
2042 EXPECT_EQ(5u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:462043 EXPECT_EQ(5u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:482044
2045 // No additional hints are sent.
Yoav Weissd33bacb2020-03-12 06:42:212046 EXPECT_EQ(expected_client_hints_number * 2,
2047 count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:222048}
Tarun Bansalbef6d652018-10-02 18:41:012049
Aaron Tagliaboschi8f3a28302020-06-24 03:08:262050class ClientHintsEnterprisePolicyTest : public ClientHintsBrowserTest {
2051 void SetUpInProcessBrowserTestFixture() override {
2052 policy::PolicyTest::SetUpInProcessBrowserTestFixture();
2053 policy::PolicyMap policies;
2054 SetPolicy(&policies, policy::key::kUserAgentClientHintsEnabled,
Aya ElAttare8811742020-07-20 08:24:372055 base::Value(false));
Aaron Tagliaboschi8f3a28302020-06-24 03:08:262056 provider_.UpdateChromePolicy(policies);
2057 }
2058};
2059
2060// Makes sure that no client hints are sent by default when the
2061// "UserAgentClientHintsEnabled" enterprise polickly is set to
2062// false
2063IN_PROC_BROWSER_TEST_F(ClientHintsEnterprisePolicyTest,
2064 ClientHintsEnterprisePolicy) {
2065 const GURL gurl = accept_ch_without_lifetime_url();
2066 ui_test_utils::NavigateToURL(browser(), gurl);
2067 // These would normally be one each
2068 EXPECT_EQ(0u, count_user_agent_hint_headers_seen());
2069 EXPECT_EQ(0u, count_ua_mobile_client_hints_headers_seen());
2070}
2071
Tarun Bansalbef6d652018-10-02 18:41:012072class ClientHintsWebHoldbackBrowserTest : public ClientHintsBrowserTest {
2073 public:
2074 ClientHintsWebHoldbackBrowserTest() : ClientHintsBrowserTest() {
2075 ConfigureHoldbackExperiment();
2076 }
2077
2078 net::EffectiveConnectionType web_effective_connection_type_override() const {
2079 return web_effective_connection_type_override_;
2080 }
2081
Mike West2fddeeb72019-02-15 11:29:482082 std::unique_ptr<base::FeatureList> EnabledFeatures() override {
Tarun Bansalbef6d652018-10-02 18:41:012083 base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
2084 const std::string kTrialName = "TrialFoo";
2085 const std::string kGroupName = "GroupFoo"; // Value not used
2086
2087 scoped_refptr<base::FieldTrial> trial =
2088 base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
2089
2090 std::map<std::string, std::string> params;
2091
2092 params["web_effective_connection_type_override"] =
2093 net::GetNameForEffectiveConnectionType(
2094 web_effective_connection_type_override_);
Mike West2fddeeb72019-02-15 11:29:482095 EXPECT_TRUE(
Tarun Bansalbef6d652018-10-02 18:41:012096 base::FieldTrialParamAssociator::GetInstance()
2097 ->AssociateFieldTrialParams(kTrialName, kGroupName, params));
2098
2099 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
Maks Orlovichc66745a2020-06-30 17:40:022100 feature_list->InitializeFromCommandLine(
2101 "UserAgentClientHint,LangClientHintHeader", "");
Tarun Bansalbef6d652018-10-02 18:41:012102 feature_list->RegisterFieldTrialOverride(
2103 features::kNetworkQualityEstimatorWebHoldback.name,
2104 base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
Mike West2fddeeb72019-02-15 11:29:482105 return feature_list;
Tarun Bansalbef6d652018-10-02 18:41:012106 }
2107
Mike West2fddeeb72019-02-15 11:29:482108 private:
2109 void ConfigureHoldbackExperiment() {}
2110
Tarun Bansalbef6d652018-10-02 18:41:012111 const net::EffectiveConnectionType web_effective_connection_type_override_ =
2112 net::EFFECTIVE_CONNECTION_TYPE_3G;
Tarun Bansalbef6d652018-10-02 18:41:012113};
2114
2115// Make sure that when NetInfo holdback experiment is enabled, the NetInfo APIs
2116// and client hints return the overridden values. Verify that the client hints
2117// are overridden on both main frame and subresource requests.
2118IN_PROC_BROWSER_TEST_F(ClientHintsWebHoldbackBrowserTest,
2119 EffectiveConnectionTypeChangeNotified) {
2120 SetExpectedEffectiveConnectionType(web_effective_connection_type_override());
2121
2122 SetClientHintExpectationsOnMainFrame(false);
2123 SetClientHintExpectationsOnSubresources(true);
2124
2125 base::RunLoop().RunUntilIdle();
2126
2127 EXPECT_TRUE(embedded_test_server()->Start());
2128 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
2129 EXPECT_EQ(0u, count_client_hints_headers_seen());
2130 EXPECT_EQ(0u, third_party_request_count_seen());
2131 EXPECT_EQ(0u, third_party_client_hints_count_seen());
2132
2133 SetClientHintExpectationsOnMainFrame(true);
2134 SetClientHintExpectationsOnSubresources(true);
2135 ui_test_utils::NavigateToURL(
2136 browser(), accept_ch_without_lifetime_with_subresource_url());
2137 base::RunLoop().RunUntilIdle();
2138 content::FetchHistogramsFromChildProcesses();
John Abd-El-Malek161073c2020-06-12 20:40:282139 metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansalbef6d652018-10-02 18:41:012140
Mike West2fddeeb72019-02-15 11:29:482141 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:462142 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:212143 EXPECT_EQ(expected_client_hints_number * 2,
2144 count_client_hints_headers_seen());
Tarun Bansalbef6d652018-10-02 18:41:012145 EXPECT_EQ(0u, third_party_request_count_seen());
2146 EXPECT_EQ(0u, third_party_client_hints_count_seen());
2147}