blob: f0a19ec90919989051172801bb4a46ace66b35c1 [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"
Tarun Bansalc211d8b2018-03-19 19:21:5820#include "chrome/browser/content_settings/tab_specific_content_settings.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1621#include "chrome/browser/metrics/subprocess_metrics_provider.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1622#include "chrome/browser/profiles/profile.h"
Tarun Bansal1965b042017-09-07 04:59:1923#include "chrome/browser/ui/browser.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"
Tarun Bansala61f0f62017-10-24 23:53:0526#include "components/content_settings/core/browser/cookie_settings.h"
Tarun Bansal1965b042017-09-07 04:59:1927#include "components/content_settings/core/browser/host_content_settings_map.h"
Tarun Bansala61f0f62017-10-24 23:53:0528#include "components/content_settings/core/common/pref_names.h"
29#include "components/prefs/pref_service.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1630#include "content/public/browser/browser_thread.h"
Changwan Ryu434c3a32019-07-30 23:42:5831#include "content/public/browser/render_view_host.h"
Tarun Bansalbef6d652018-10-02 18:41:0132#include "content/public/common/content_features.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1633#include "content/public/common/content_switches.h"
Changwan Ryu434c3a32019-07-30 23:42:5834#include "content/public/common/web_preferences.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1635#include "content/public/test/browser_test_utils.h"
36#include "content/public/test/test_utils.h"
Tarun Bansal229647bd002018-02-27 17:33:3637#include "content/public/test/url_loader_interceptor.h"
38#include "net/dns/mock_host_resolver.h"
39#include "net/http/http_request_headers.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4740#include "net/nqe/effective_connection_type.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1641#include "net/test/embedded_test_server/embedded_test_server.h"
Tarun Bansal1965b042017-09-07 04:59:1942#include "net/test/embedded_test_server/http_request.h"
Tarun Bansal229647bd002018-02-27 17:33:3643#include "net/test/embedded_test_server/http_response.h"
Tarun Bansal74e189d2018-05-07 19:07:3544#include "services/network/public/cpp/cors/cors.h"
Tarun Bansalceab9592018-05-01 18:57:3545#include "services/network/public/cpp/features.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4746#include "services/network/public/cpp/network_switches.h"
Blink Reformata30d4232018-04-07 15:31:0647#include "third_party/blink/public/common/client_hints/client_hints.h"
Tarun Bansal229647bd002018-02-27 17:33:3648
49namespace {
50
51// An interceptor that records count of fetches and client hint headers for
52// requests to https://foo.com/non-existing-image.jpg.
Jay Civelli1ff872d2018-03-09 21:52:1653class ThirdPartyURLLoaderInterceptor {
Tarun Bansal229647bd002018-02-27 17:33:3654 public:
Jay Civelli1ff872d2018-03-09 21:52:1655 explicit ThirdPartyURLLoaderInterceptor(const GURL intercepted_url)
56 : intercepted_url_(intercepted_url),
57 interceptor_(base::BindRepeating(
58 &ThirdPartyURLLoaderInterceptor::InterceptURLRequest,
59 base::Unretained(this))) {}
Tarun Bansal229647bd002018-02-27 17:33:3660
Jay Civelli1ff872d2018-03-09 21:52:1661 ~ThirdPartyURLLoaderInterceptor() = default;
Tarun Bansal229647bd002018-02-27 17:33:3662
63 size_t request_count_seen() const { return request_count_seen_; }
64
65 size_t client_hints_count_seen() const { return client_hints_count_seen_; }
66
67 private:
Jay Civelli1ff872d2018-03-09 21:52:1668 bool InterceptURLRequest(
69 content::URLLoaderInterceptor::RequestParams* params) {
70 if (params->url_request.url != intercepted_url_)
71 return false;
Tarun Bansal229647bd002018-02-27 17:33:3672
Jay Civelli1ff872d2018-03-09 21:52:1673 request_count_seen_++;
Mike West14c11102019-02-04 16:16:4774 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansalf9cf9892018-04-06 04:38:0175 if (params->url_request.headers.HasHeader(
76 blink::kClientHintsHeaderMapping[i])) {
77 client_hints_count_seen_++;
78 }
Tarun Bansal5c28afb2018-03-17 02:55:2079 }
Jay Civelli1ff872d2018-03-09 21:52:1680 return false;
81 }
Tarun Bansal229647bd002018-02-27 17:33:3682
Jay Civelli1ff872d2018-03-09 21:52:1683 GURL intercepted_url_;
84
85 size_t request_count_seen_ = 0u;
86
87 size_t client_hints_count_seen_ = 0u;
88
89 content::URLLoaderInterceptor interceptor_;
90
91 DISALLOW_COPY_AND_ASSIGN(ThirdPartyURLLoaderInterceptor);
Tarun Bansal229647bd002018-02-27 17:33:3692};
93
Tarun Bansal62efba12018-05-04 22:58:3594// Returns true only if |header_value| satisfies ABNF: 1*DIGIT [ "." 1*DIGIT ]
95bool IsSimilarToDoubleABNF(const std::string& header_value) {
96 if (header_value.empty())
97 return false;
98 char first_char = header_value.at(0);
99 if (!isdigit(first_char))
100 return false;
101
102 bool period_found = false;
103 bool digit_found_after_period = false;
104 for (char ch : header_value) {
105 if (isdigit(ch)) {
106 if (period_found) {
107 digit_found_after_period = true;
108 }
109 continue;
110 }
111 if (ch == '.') {
112 if (period_found)
113 return false;
114 period_found = true;
115 continue;
116 }
117 return false;
118 }
119 if (period_found)
120 return digit_found_after_period;
121 return true;
122}
123
124// Returns true only if |header_value| satisfies ABNF: 1*DIGIT
125bool IsSimilarToIntABNF(const std::string& header_value) {
126 if (header_value.empty())
127 return false;
128
129 for (char ch : header_value) {
130 if (!isdigit(ch))
131 return false;
132 }
133 return true;
134}
135
Tarun Bansal229647bd002018-02-27 17:33:36136} // namespace
Tarun Bansal0b8b7afd2017-08-25 03:52:16137
Tarun Bansal9a7051f2018-07-10 18:30:05138class ClientHintsBrowserTest : public InProcessBrowserTest,
139 public testing::WithParamInterface<bool> {
Tarun Bansal0b8b7afd2017-08-25 03:52:16140 public:
141 ClientHintsBrowserTest()
Mikel Astiz2de748d2019-11-16 10:39:36142 : http_server_(net::EmbeddedTestServer::TYPE_HTTP),
Tarun Bansal3b330b02017-11-09 19:03:14143 https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal345418632018-06-29 11:07:04144 https_cross_origin_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal229647bd002018-02-27 17:33:36145 expect_client_hints_on_main_frame_(false),
146 expect_client_hints_on_subresources_(false),
Mike West2fddeeb72019-02-15 11:29:48147 count_user_agent_hint_headers_seen_(0),
Maks Orlovich5dcc99c2020-02-13 19:07:46148 count_ua_mobile_client_hints_headers_seen_(0),
Tarun Bansal229647bd002018-02-27 17:33:36149 count_client_hints_headers_seen_(0),
150 request_interceptor_(nullptr) {
Tarun Bansal3b330b02017-11-09 19:03:14151 http_server_.ServeFilesFromSourceDirectory("chrome/test/data/client_hints");
Tarun Bansal0b8b7afd2017-08-25 03:52:16152 https_server_.ServeFilesFromSourceDirectory(
153 "chrome/test/data/client_hints");
Tarun Bansal345418632018-06-29 11:07:04154 https_cross_origin_server_.ServeFilesFromSourceDirectory(
155 "chrome/test/data/client_hints");
Tarun Bansal1965b042017-09-07 04:59:19156
Tarun Bansal3b330b02017-11-09 19:03:14157 http_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04158 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
159 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19160 https_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04161 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
162 base::Unretained(this)));
163 https_cross_origin_server_.RegisterRequestMonitor(
164 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
165 base::Unretained(this)));
Tarun Bansal293a7b6c2018-12-05 17:41:12166 https_cross_origin_server_.RegisterRequestHandler(
167 base::BindRepeating(&ClientHintsBrowserTest::RequestHandlerToRedirect,
168 base::Unretained(this)));
Tarun Bansal345418632018-06-29 11:07:04169 https_server_.RegisterRequestHandler(base::BindRepeating(
170 &ClientHintsBrowserTest::RequestHandlerToFetchCrossOriginIframe,
171 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19172
Tarun Bansal3b330b02017-11-09 19:03:14173 EXPECT_TRUE(http_server_.Start());
Tarun Bansal0b8b7afd2017-08-25 03:52:16174 EXPECT_TRUE(https_server_.Start());
Tarun Bansal345418632018-06-29 11:07:04175 EXPECT_TRUE(https_cross_origin_server_.Start());
176
177 EXPECT_NE(https_server_.base_url(), https_cross_origin_server_.base_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16178
Tarun Bansal3b330b02017-11-09 19:03:14179 accept_ch_with_lifetime_http_local_url_ =
180 http_server_.GetURL("/accept_ch_with_lifetime.html");
Tarun Bansal9a7051f2018-07-10 18:30:05181 http_equiv_accept_ch_with_lifetime_http_local_url_ =
182 http_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal3b330b02017-11-09 19:03:14183 EXPECT_TRUE(accept_ch_with_lifetime_http_local_url_.SchemeIsHTTPOrHTTPS());
184 EXPECT_FALSE(
185 accept_ch_with_lifetime_http_local_url_.SchemeIsCryptographic());
186
Tarun Bansal1965b042017-09-07 04:59:19187 accept_ch_with_lifetime_url_ =
188 https_server_.GetURL("/accept_ch_with_lifetime.html");
Tarun Bansal73502f92019-04-16 21:21:19189 accept_ch_with_short_lifetime_url_ =
190 https_server_.GetURL("/accept_ch_with_short_lifetime.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16191
Tarun Bansal1965b042017-09-07 04:59:19192 accept_ch_without_lifetime_url_ =
193 https_server_.GetURL("/accept_ch_without_lifetime.html");
194 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
195 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal9a7051f2018-07-10 18:30:05196 http_equiv_accept_ch_without_lifetime_url_ =
197 https_server_.GetURL("/http_equiv_accept_ch_without_lifetime.html");
Tarun Bansal1965b042017-09-07 04:59:19198
199 without_accept_ch_without_lifetime_url_ =
200 https_server_.GetURL("/without_accept_ch_without_lifetime.html");
201 EXPECT_TRUE(without_accept_ch_without_lifetime_url_.SchemeIsHTTPOrHTTPS());
202 EXPECT_TRUE(
203 without_accept_ch_without_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal3b330b02017-11-09 19:03:14204
205 without_accept_ch_without_lifetime_local_url_ =
206 http_server_.GetURL("/without_accept_ch_without_lifetime.html");
207 EXPECT_TRUE(
208 without_accept_ch_without_lifetime_local_url_.SchemeIsHTTPOrHTTPS());
209 EXPECT_FALSE(
210 without_accept_ch_without_lifetime_local_url_.SchemeIsCryptographic());
Tarun Bansaladd5e1812018-02-09 19:07:58211
212 without_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
213 "/without_accept_ch_without_lifetime_img_localhost.html");
214 without_accept_ch_without_lifetime_img_foo_com_ = https_server_.GetURL(
215 "/without_accept_ch_without_lifetime_img_foo_com.html");
216 accept_ch_without_lifetime_with_iframe_url_ =
217 https_server_.GetURL("/accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05218 http_equiv_accept_ch_without_lifetime_with_iframe_url_ =
219 https_server_.GetURL(
220 "/http_equiv_accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal62cc3542018-06-27 23:53:30221 accept_ch_without_lifetime_with_subresource_url_ = https_server_.GetURL(
222 "/accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal9a7051f2018-07-10 18:30:05223 http_equiv_accept_ch_without_lifetime_with_subresource_url_ =
224 https_server_.GetURL(
225 "/http_equiv_accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal62cc3542018-06-27 23:53:30226 accept_ch_without_lifetime_with_subresource_iframe_url_ =
227 https_server_.GetURL(
228 "/accept_ch_without_lifetime_with_subresource_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05229 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_ =
230 https_server_.GetURL(
231 "/http_equiv_accept_ch_without_lifetime_with_subresource_iframe."
232 "html");
Tarun Bansal229647bd002018-02-27 17:33:36233 accept_ch_without_lifetime_img_localhost_ =
234 https_server_.GetURL("/accept_ch_without_lifetime_img_localhost.html");
Tarun Bansal9a7051f2018-07-10 18:30:05235 http_equiv_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
236 "/http_equiv_accept_ch_without_lifetime_img_localhost.html");
237 http_equiv_accept_ch_with_lifetime_ =
238 https_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal293a7b6c2018-12-05 17:41:12239
240 redirect_url_ = https_cross_origin_server_.GetURL("/redirect.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16241 }
242
243 ~ClientHintsBrowserTest() override {}
244
Mike West2fddeeb72019-02-15 11:29:48245 virtual std::unique_ptr<base::FeatureList> EnabledFeatures() {
246 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
247 feature_list->InitializeFromCommandLine("UserAgentClientHint", "");
248 return feature_list;
249 }
250
251 void SetUp() override {
252 scoped_feature_list_.InitWithFeatureList(EnabledFeatures());
253 InProcessBrowserTest::SetUp();
254 }
255
Tarun Bansal0b8b7afd2017-08-25 03:52:16256 void SetUpOnMainThread() override {
Tarun Bansal229647bd002018-02-27 17:33:36257 host_resolver()->AddRule("*", "127.0.0.1");
Tarun Bansal229647bd002018-02-27 17:33:36258
Jay Civelli1ff872d2018-03-09 21:52:16259 request_interceptor_ = std::make_unique<ThirdPartyURLLoaderInterceptor>(
260 GURL("https://foo.com/non-existing-image.jpg"));
Tarun Bansal229647bd002018-02-27 17:33:36261 base::RunLoop().RunUntilIdle();
Tarun Bansal0b8b7afd2017-08-25 03:52:16262 }
263
Jay Civelli1ff872d2018-03-09 21:52:16264 void TearDownOnMainThread() override { request_interceptor_.reset(); }
265
Tarun Bansal0b8b7afd2017-08-25 03:52:16266 void SetUpCommandLine(base::CommandLine* cmd) override {
Tarun Bansal7f3fe8c2018-04-06 22:37:47267 cmd->AppendSwitchASCII(network::switches::kForceEffectiveConnectionType,
268 net::kEffectiveConnectionType2G);
Mike West14c11102019-02-04 16:16:47269 cmd->AppendSwitchASCII(switches::kEnableBlinkFeatures,
270 "LangClientHintHeader");
Tarun Bansal0b8b7afd2017-08-25 03:52:16271 }
272
Tarun Bansal229647bd002018-02-27 17:33:36273 void SetClientHintExpectationsOnMainFrame(bool expect_client_hints) {
274 expect_client_hints_on_main_frame_ = expect_client_hints;
Tarun Bansal1965b042017-09-07 04:59:19275 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16276
Tarun Bansal229647bd002018-02-27 17:33:36277 void SetClientHintExpectationsOnSubresources(bool expect_client_hints) {
Callum May1d939742020-03-02 17:51:30278 base::AutoLock lock(expect_client_hints_on_subresources_lock_);
Tarun Bansal229647bd002018-02-27 17:33:36279 expect_client_hints_on_subresources_ = expect_client_hints;
Tarun Bansala61f0f62017-10-24 23:53:05280 }
281
Callum May1d939742020-03-02 17:51:30282 bool expect_client_hints_on_subresources() {
283 base::AutoLock lock(expect_client_hints_on_subresources_lock_);
284 return expect_client_hints_on_subresources_;
285 }
286
Tarun Bansalc211d8b2018-03-19 19:21:58287 // Verify that the user is not notified that cookies or JavaScript were
288 // blocked on the webpage due to the checks done by client hints.
289 void VerifyContentSettingsNotNotified() const {
290 content::WebContents* web_contents =
291 browser()->tab_strip_model()->GetActiveWebContents();
292 EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents)
Darin Fisher42f5e7d2019-10-30 07:15:45293 ->IsContentBlocked(ContentSettingsType::COOKIES));
Tarun Bansalc211d8b2018-03-19 19:21:58294
295 EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents)
Darin Fisher42f5e7d2019-10-30 07:15:45296 ->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
Tarun Bansalc211d8b2018-03-19 19:21:58297 }
298
Tarun Bansalbef6d652018-10-02 18:41:01299 void SetExpectedEffectiveConnectionType(
300 net::EffectiveConnectionType effective_connection_type) {
301 expected_ect = effective_connection_type;
302 }
303
Changwan Ryu434c3a32019-07-30 23:42:58304 void SetJsEnabledForActiveView(bool enabled) {
305 content::RenderViewHost* view = browser()
306 ->tab_strip_model()
307 ->GetActiveWebContents()
308 ->GetRenderViewHost();
309 content::WebPreferences prefs = view->GetWebkitPreferences();
310 prefs.javascript_enabled = enabled;
311 view->UpdateWebkitPreferences(prefs);
312 }
313
Maks Orlovich7227ce0d2020-02-28 17:13:16314 void TestProfilesIndependent(Browser* browser_a, Browser* browser_b);
315
Tarun Bansal3b330b02017-11-09 19:03:14316 const GURL& accept_ch_with_lifetime_http_local_url() const {
317 return accept_ch_with_lifetime_http_local_url_;
318 }
Tarun Bansal9a7051f2018-07-10 18:30:05319 const GURL& http_equiv_accept_ch_with_lifetime_http_local_url() const {
320 return http_equiv_accept_ch_with_lifetime_http_local_url_;
321 }
Tarun Bansal3b330b02017-11-09 19:03:14322
Tarun Bansal1965b042017-09-07 04:59:19323 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
324 // headers.
325 const GURL& accept_ch_with_lifetime_url() const {
326 return accept_ch_with_lifetime_url_;
327 }
Tarun Bansal9a7051f2018-07-10 18:30:05328 const GURL& http_equiv_accept_ch_with_lifetime() {
329 return http_equiv_accept_ch_with_lifetime_;
330 }
Tarun Bansal1965b042017-09-07 04:59:19331
Tarun Bansal73502f92019-04-16 21:21:19332 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
333 // headers. The Accept-CH-Lifetime duration is set very short to 1 second.
334 const GURL& accept_ch_with_short_lifetime() const {
335 return accept_ch_with_short_lifetime_url_;
336 }
337
Tarun Bansal1965b042017-09-07 04:59:19338 // A URL whose response headers include only Accept-CH header.
339 const GURL& accept_ch_without_lifetime_url() const {
340 return accept_ch_without_lifetime_url_;
341 }
Tarun Bansal9a7051f2018-07-10 18:30:05342 const GURL& http_equiv_accept_ch_without_lifetime_url() const {
343 return http_equiv_accept_ch_without_lifetime_url_;
344 }
Tarun Bansal1965b042017-09-07 04:59:19345
346 // A URL whose response headers do not include either Accept-CH or
347 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
348 const GURL& without_accept_ch_without_lifetime_url() const {
349 return without_accept_ch_without_lifetime_url_;
350 }
351
Tarun Bansal3b330b02017-11-09 19:03:14352 // A URL whose response headers do not include either Accept-CH or
353 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
354 const GURL& without_accept_ch_without_lifetime_local_url() const {
355 return without_accept_ch_without_lifetime_local_url_;
356 }
357
Tarun Bansaladd5e1812018-02-09 19:07:58358 // A URL whose response headers do not include either Accept-CH or
359 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
360 // from localhost.
361 const GURL& without_accept_ch_without_lifetime_img_localhost() const {
362 return without_accept_ch_without_lifetime_img_localhost_;
363 }
364
365 // A URL whose response headers do not include either Accept-CH or
366 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
367 // from foo.com.
368 const GURL& without_accept_ch_without_lifetime_img_foo_com() const {
369 return without_accept_ch_without_lifetime_img_foo_com_;
370 }
371
372 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
373 // headers. The response loads accept_ch_with_lifetime_url() in an iframe.
374 const GURL& accept_ch_without_lifetime_with_iframe_url() const {
375 return accept_ch_without_lifetime_with_iframe_url_;
376 }
Tarun Bansal9a7051f2018-07-10 18:30:05377 const GURL& http_equiv_accept_ch_without_lifetime_with_iframe_url() const {
378 return http_equiv_accept_ch_without_lifetime_with_iframe_url_;
379 }
Tarun Bansaladd5e1812018-02-09 19:07:58380
Tarun Bansal62cc3542018-06-27 23:53:30381 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
382 // headers. The response loads accept_ch_with_lifetime_url() as a subresource
383 // in the main frame.
384 const GURL& accept_ch_without_lifetime_with_subresource_url() const {
385 return accept_ch_without_lifetime_with_subresource_url_;
386 }
Tarun Bansal9a7051f2018-07-10 18:30:05387 const GURL& http_equiv_accept_ch_without_lifetime_with_subresource_url()
388 const {
389 return http_equiv_accept_ch_without_lifetime_with_subresource_url_;
390 }
Tarun Bansal62cc3542018-06-27 23:53:30391
392 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
Tarun Bansal9a7051f2018-07-10 18:30:05393 // headers. The response loads accept_ch_with_lifetime_url() or
394 // http_equiv_accept_ch_with_lifetime_url() as a subresource in the iframe.
Tarun Bansal62cc3542018-06-27 23:53:30395 const GURL& accept_ch_without_lifetime_with_subresource_iframe_url() const {
396 return accept_ch_without_lifetime_with_subresource_iframe_url_;
397 }
Tarun Bansal9a7051f2018-07-10 18:30:05398 const GURL&
399 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url() const {
400 return http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
401 }
Tarun Bansal62cc3542018-06-27 23:53:30402
Tarun Bansal9a7051f2018-07-10 18:30:05403 // A URL whose response includes only Accept-CH header. Navigating to
Tarun Bansal229647bd002018-02-27 17:33:36404 // this URL also fetches two images: One from the localhost, and one from
405 // foo.com.
406 const GURL& accept_ch_without_lifetime_img_localhost() const {
407 return accept_ch_without_lifetime_img_localhost_;
408 }
Tarun Bansal9a7051f2018-07-10 18:30:05409 const GURL& http_equiv_accept_ch_without_lifetime_img_localhost() const {
410 return http_equiv_accept_ch_without_lifetime_img_localhost_;
411 }
Tarun Bansal229647bd002018-02-27 17:33:36412
Tarun Bansal293a7b6c2018-12-05 17:41:12413 const GURL& redirect_url() const { return redirect_url_; }
414
Mike West2fddeeb72019-02-15 11:29:48415 size_t count_user_agent_hint_headers_seen() const {
Callum May7d88ff3e2019-11-12 18:21:46416 base::AutoLock lock(count_headers_lock_);
Mike West2fddeeb72019-02-15 11:29:48417 return count_user_agent_hint_headers_seen_;
418 }
419
Maks Orlovich5dcc99c2020-02-13 19:07:46420 size_t count_ua_mobile_client_hints_headers_seen() const {
421 base::AutoLock lock(count_headers_lock_);
422 return count_ua_mobile_client_hints_headers_seen_;
423 }
424
Tarun Bansal1965b042017-09-07 04:59:19425 size_t count_client_hints_headers_seen() const {
Callum May7d88ff3e2019-11-12 18:21:46426 base::AutoLock lock(count_headers_lock_);
Tarun Bansal1965b042017-09-07 04:59:19427 return count_client_hints_headers_seen_;
428 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16429
Tarun Bansal229647bd002018-02-27 17:33:36430 size_t third_party_request_count_seen() const {
431 return request_interceptor_->request_count_seen();
432 }
433
434 size_t third_party_client_hints_count_seen() const {
435 return request_interceptor_->client_hints_count_seen();
436 }
437
Mike Weste555be862019-02-20 16:17:30438 const std::string& main_frame_ua_observed() const {
439 return main_frame_ua_observed_;
440 }
441
Tarun Bansalea0d8262018-05-21 16:11:50442 base::test::ScopedFeatureList scoped_feature_list_;
443
Tarun Bansal345418632018-06-29 11:07:04444 std::string intercept_iframe_resource_;
Tarun Bansal9a7051f2018-07-10 18:30:05445 bool intercept_to_http_equiv_iframe_ = false;
Callum May7d88ff3e2019-11-12 18:21:46446 mutable base::Lock count_headers_lock_;
Tarun Bansal345418632018-06-29 11:07:04447
Tarun Bansal0b8b7afd2017-08-25 03:52:16448 private:
Tarun Bansal345418632018-06-29 11:07:04449 // Intercepts only the main frame requests that contain
Tarun Bansal293a7b6c2018-12-05 17:41:12450 // "redirect" in the resource path. The intercepted requests
451 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
452 // server.
453 std::unique_ptr<net::test_server::HttpResponse> RequestHandlerToRedirect(
454 const net::test_server::HttpRequest& request) {
455 // Check if it's a main frame request.
456 if (request.relative_url.find(".html") == std::string::npos)
457 return nullptr;
458
459 if (request.GetURL().spec().find("redirect") == std::string::npos)
460 return nullptr;
461
462 std::unique_ptr<net::test_server::BasicHttpResponse> response;
463 response.reset(new net::test_server::BasicHttpResponse);
464 response->set_code(net::HTTP_FOUND);
465 response->AddCustomHeader("Location",
466 without_accept_ch_without_lifetime_url().spec());
467 return std::move(response);
468 }
469
470 // Intercepts only the main frame requests that contain
Tarun Bansal345418632018-06-29 11:07:04471 // |intercept_iframe_resource_| in the resource path. The intercepted requests
472 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
473 // server.
474 std::unique_ptr<net::test_server::HttpResponse>
475 RequestHandlerToFetchCrossOriginIframe(
476 const net::test_server::HttpRequest& request) {
477 if (intercept_iframe_resource_.empty())
478 return nullptr;
479
480 // Check if it's a main frame request.
481 if (request.relative_url.find(".html") == std::string::npos)
482 return nullptr;
483
484 if (request.relative_url.find(intercept_iframe_resource_) ==
485 std::string::npos) {
486 return nullptr;
487 }
488
489 const std::string iframe_url =
Tarun Bansal9a7051f2018-07-10 18:30:05490 intercept_to_http_equiv_iframe_
491 ? https_cross_origin_server_
492 .GetURL("/http_equiv_accept_ch_with_lifetime.html")
493 .spec()
494 : https_cross_origin_server_.GetURL("/accept_ch_with_lifetime.html")
495 .spec();
Tarun Bansal345418632018-06-29 11:07:04496
497 std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
498 new net::test_server::BasicHttpResponse());
499 http_response->set_code(net::HTTP_OK);
500 http_response->set_content_type("text/html");
501 http_response->set_content(
502 "<html>"
503 "<link rel='icon' href='data:;base64,='><head></head>"
504 "Empty file which uses link-rel to disable favicon fetches. "
505 "<iframe src='" +
506 iframe_url + "'></iframe></html>");
507
508 return std::move(http_response);
509 }
510
Tarun Bansal1965b042017-09-07 04:59:19511 // Called by |https_server_|.
512 void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
Tarun Bansal6bf54302017-10-02 07:39:14513 bool is_main_frame_navigation =
514 request.GetURL().spec().find(".html") != std::string::npos;
515
Tarun Bansal293a7b6c2018-12-05 17:41:12516 if (is_main_frame_navigation &&
517 request.GetURL().spec().find("redirect") != std::string::npos) {
518 return;
519 }
520
Tarun Bansal229647bd002018-02-27 17:33:36521 if (is_main_frame_navigation) {
Mike Weste555be862019-02-20 16:17:30522 if (request.headers.find("sec-ch-ua") != request.headers.end())
523 main_frame_ua_observed_ = request.headers.find("sec-ch-ua")->second;
524
Tarun Bansalf9cf9892018-04-06 04:38:01525 VerifyClientHintsReceived(expect_client_hints_on_main_frame_, request);
Tarun Bansal5c28afb2018-03-17 02:55:20526 if (expect_client_hints_on_main_frame_) {
527 double value = 0.0;
528 EXPECT_TRUE(base::StringToDouble(
529 request.headers.find("device-memory")->second, &value));
530 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35531 EXPECT_TRUE(IsSimilarToDoubleABNF(
532 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42533 main_frame_device_memory_observed_ = value;
Tarun Bansal5c28afb2018-03-17 02:55:20534
535 EXPECT_TRUE(
536 base::StringToDouble(request.headers.find("dpr")->second, &value));
537 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35538 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42539 main_frame_dpr_observed_ = value;
540
Tarun Bansal5c28afb2018-03-17 02:55:20541 EXPECT_TRUE(base::StringToDouble(
542 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35543 EXPECT_TRUE(
544 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36545#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20546 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36547#else
548 EXPECT_EQ(980, value);
Tarun Bansal5c28afb2018-03-17 02:55:20549#endif
Tarun Bansal44ad96882018-03-28 17:47:42550 main_frame_viewport_width_observed_ = value;
Mike Weste555be862019-02-20 16:17:30551
Tarun Bansal7f3fe8c2018-04-06 22:37:47552 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20553 }
Tarun Bansala61f0f62017-10-24 23:53:05554 }
Tarun Bansal6bf54302017-10-02 07:39:14555
Tarun Bansal229647bd002018-02-27 17:33:36556 if (!is_main_frame_navigation) {
Callum May1d939742020-03-02 17:51:30557 VerifyClientHintsReceived(expect_client_hints_on_subresources(), request);
Tarun Bansal5c28afb2018-03-17 02:55:20558
Callum May1d939742020-03-02 17:51:30559 if (expect_client_hints_on_subresources()) {
Tarun Bansal5c28afb2018-03-17 02:55:20560 double value = 0.0;
561 EXPECT_TRUE(base::StringToDouble(
562 request.headers.find("device-memory")->second, &value));
563 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35564 EXPECT_TRUE(IsSimilarToDoubleABNF(
565 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42566 if (main_frame_device_memory_observed_ > 0) {
567 EXPECT_EQ(main_frame_device_memory_observed_, value);
568 }
Tarun Bansal5c28afb2018-03-17 02:55:20569
570 EXPECT_TRUE(
571 base::StringToDouble(request.headers.find("dpr")->second, &value));
572 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35573 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42574 if (main_frame_dpr_observed_ > 0) {
575 EXPECT_EQ(main_frame_dpr_observed_, value);
576 }
Tarun Bansal5c28afb2018-03-17 02:55:20577
578 EXPECT_TRUE(base::StringToDouble(
579 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35580 EXPECT_TRUE(
581 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36582#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20583 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36584#else
585 EXPECT_EQ(980, value);
586#endif
Tarun Bansal44ad96882018-03-28 17:47:42587#if defined(OS_ANDROID)
588 // TODO(tbansal): https://crbug.com/825892: Viewport width on main
589 // frame requests may be incorrect when the Chrome window is not
590 // maximized.
591 if (main_frame_viewport_width_observed_ > 0) {
592 EXPECT_EQ(main_frame_viewport_width_observed_, value);
593 }
594#endif
Tarun Bansal7f3fe8c2018-04-06 22:37:47595 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20596 }
Tarun Bansala61f0f62017-10-24 23:53:05597 }
Tarun Bansal6bf54302017-10-02 07:39:14598
Mike West14c11102019-02-04 16:16:47599 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Jan Wilken Dörriea8cb56302019-06-06 18:59:36600 if (base::Contains(request.headers,
601 blink::kClientHintsHeaderMapping[i])) {
Callum May7d88ff3e2019-11-12 18:21:46602 base::AutoLock lock(count_headers_lock_);
Mike West2fddeeb72019-02-15 11:29:48603 // The user agent hint is special:
604 if (std::string(blink::kClientHintsHeaderMapping[i]) == "sec-ch-ua") {
605 count_user_agent_hint_headers_seen_++;
Maks Orlovich5dcc99c2020-02-13 19:07:46606 } else if (std::string(blink::kClientHintsHeaderMapping[i]) ==
607 "sec-ch-ua-mobile") {
608 count_ua_mobile_client_hints_headers_seen_++;
Mike West2fddeeb72019-02-15 11:29:48609 } else {
610 count_client_hints_headers_seen_++;
611 }
Tarun Bansalf9cf9892018-04-06 04:38:01612 }
613 }
614 }
Tarun Bansal1965b042017-09-07 04:59:19615
Tarun Bansalf9cf9892018-04-06 04:38:01616 void VerifyClientHintsReceived(bool expect_client_hints,
617 const net::test_server::HttpRequest& request) {
Mike West14c11102019-02-04 16:16:47618 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
619 SCOPED_TRACE(testing::Message()
620 << std::string(blink::kClientHintsHeaderMapping[i]));
Tarun Bansalf9cf9892018-04-06 04:38:01621 // Resource width client hint is only attached on image subresources.
622 if (std::string(blink::kClientHintsHeaderMapping[i]) == "width") {
623 continue;
624 }
Mike West2fddeeb72019-02-15 11:29:48625
Maks Orlovich5dcc99c2020-02-13 19:07:46626 // `Sec-CH-UA` and `Sec-CH-UA-Mobile` is attached on all requests.
627 if (std::string(blink::kClientHintsHeaderMapping[i]) == "sec-ch-ua" ||
628 std::string(blink::kClientHintsHeaderMapping[i]) ==
629 "sec-ch-ua-mobile") {
Mike West2fddeeb72019-02-15 11:29:48630 continue;
631 }
632
Jan Wilken Dörriea8cb56302019-06-06 18:59:36633 EXPECT_EQ(
634 expect_client_hints,
635 base::Contains(request.headers, blink::kClientHintsHeaderMapping[i]));
Tarun Bansalf9cf9892018-04-06 04:38:01636 }
Tarun Bansal1965b042017-09-07 04:59:19637 }
638
Tarun Bansal7f3fe8c2018-04-06 22:37:47639 void VerifyNetworkQualityClientHints(
640 const net::test_server::HttpRequest& request) const {
641 // Effective connection type is forced to 2G using command line in these
642 // tests.
Tarun Bansal509a8dd2018-04-10 17:19:16643 int rtt_value = 0.0;
Tarun Bansal7f3fe8c2018-04-06 22:37:47644 EXPECT_TRUE(
Tarun Bansal509a8dd2018-04-10 17:19:16645 base::StringToInt(request.headers.find("rtt")->second, &rtt_value));
646 EXPECT_LE(0, rtt_value);
Tarun Bansal62efba12018-05-04 22:58:35647 EXPECT_TRUE(IsSimilarToIntABNF(request.headers.find("rtt")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16648 // Verify that RTT value is a multiple of 50 milliseconds.
649 EXPECT_EQ(0, rtt_value % 50);
Tarun Bansalbef6d652018-10-02 18:41:01650 EXPECT_GE(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? 3000 : 500,
651 rtt_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47652
Tarun Bansal509a8dd2018-04-10 17:19:16653 double mbps_value = 0.0;
654 EXPECT_TRUE(base::StringToDouble(request.headers.find("downlink")->second,
655 &mbps_value));
656 EXPECT_LE(0, mbps_value);
Tarun Bansal62efba12018-05-04 22:58:35657 EXPECT_TRUE(
658 IsSimilarToDoubleABNF(request.headers.find("downlink")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16659 // Verify that the mbps value is a multiple of 0.050 mbps.
660 // Allow for small amount of noise due to double to integer conversions.
661 EXPECT_NEAR(0, (static_cast<int>(mbps_value * 1000)) % 50, 1);
662 EXPECT_GE(10.0, mbps_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47663
664 EXPECT_FALSE(request.headers.find("ect")->second.empty());
Tarun Bansalceab9592018-05-01 18:57:35665
666 // TODO(tbansal): https://crbug.com/819244: When network servicification is
Tarun Bansal5ac533542018-08-10 19:45:52667 // enabled, the renderer processes do not receive notifications on
668 // change in the network quality. Hence, the network quality client hints
669 // are not set to the correct value on subresources.
670 bool is_main_frame_navigation =
671 request.GetURL().spec().find(".html") != std::string::npos;
John Abd-El-Malek67facbe82019-06-06 22:37:08672 if (is_main_frame_navigation) {
Tarun Bansalceab9592018-05-01 18:57:35673 // Effective connection type is forced to 2G using command line in these
674 // tests. RTT is expected to be 1800 msec but leave some gap to account
675 // for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01676 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
677 EXPECT_NEAR(1800, rtt_value, 360);
678 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
679 EXPECT_NEAR(450, rtt_value, 90);
680 } else {
681 NOTREACHED();
682 }
Tarun Bansalceab9592018-05-01 18:57:35683
684 // Effective connection type is forced to 2G using command line in these
685 // tests. downlink is expected to be 0.075 Mbps but leave some gap to
686 // account for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01687 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
688 EXPECT_NEAR(0.075, mbps_value, 0.05);
689 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
690 EXPECT_NEAR(0.4, mbps_value, 0.1);
691 } else {
692 NOTREACHED();
693 }
Tarun Bansalceab9592018-05-01 18:57:35694
Tarun Bansalbef6d652018-10-02 18:41:01695 EXPECT_EQ(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? "2g" : "3g",
696 request.headers.find("ect")->second);
Tarun Bansalceab9592018-05-01 18:57:35697 }
Tarun Bansal7f3fe8c2018-04-06 22:37:47698 }
699
Tarun Bansal3b330b02017-11-09 19:03:14700 net::EmbeddedTestServer http_server_;
Tarun Bansal0b8b7afd2017-08-25 03:52:16701 net::EmbeddedTestServer https_server_;
Tarun Bansal345418632018-06-29 11:07:04702 net::EmbeddedTestServer https_cross_origin_server_;
Tarun Bansal3b330b02017-11-09 19:03:14703 GURL accept_ch_with_lifetime_http_local_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05704 GURL http_equiv_accept_ch_with_lifetime_http_local_url_;
Tarun Bansal1965b042017-09-07 04:59:19705 GURL accept_ch_with_lifetime_url_;
Tarun Bansal73502f92019-04-16 21:21:19706 GURL accept_ch_with_short_lifetime_url_;
Tarun Bansal1965b042017-09-07 04:59:19707 GURL accept_ch_without_lifetime_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05708 GURL http_equiv_accept_ch_without_lifetime_url_;
Tarun Bansal1965b042017-09-07 04:59:19709 GURL without_accept_ch_without_lifetime_url_;
Tarun Bansal3b330b02017-11-09 19:03:14710 GURL without_accept_ch_without_lifetime_local_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58711 GURL accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05712 GURL http_equiv_accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal62cc3542018-06-27 23:53:30713 GURL accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05714 GURL http_equiv_accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal62cc3542018-06-27 23:53:30715 GURL accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05716 GURL http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58717 GURL without_accept_ch_without_lifetime_img_foo_com_;
718 GURL without_accept_ch_without_lifetime_img_localhost_;
Tarun Bansal229647bd002018-02-27 17:33:36719 GURL accept_ch_without_lifetime_img_localhost_;
Tarun Bansal9a7051f2018-07-10 18:30:05720 GURL http_equiv_accept_ch_without_lifetime_img_localhost_;
721 GURL http_equiv_accept_ch_with_lifetime_;
Tarun Bansal293a7b6c2018-12-05 17:41:12722 GURL redirect_url_;
Tarun Bansal1965b042017-09-07 04:59:19723
Mike Weste555be862019-02-20 16:17:30724 std::string main_frame_ua_observed_;
725
Tarun Bansal44ad96882018-03-28 17:47:42726 double main_frame_dpr_observed_ = -1;
727 double main_frame_viewport_width_observed_ = -1;
728 double main_frame_device_memory_observed_ = -1;
729
Tarun Bansal229647bd002018-02-27 17:33:36730 // Expect client hints on all the main frame request.
731 bool expect_client_hints_on_main_frame_;
732 // Expect client hints on all the subresource requests.
Callum May1d939742020-03-02 17:51:30733 bool expect_client_hints_on_subresources_
734 GUARDED_BY(expect_client_hints_on_subresources_lock_);
735
736 base::Lock expect_client_hints_on_subresources_lock_;
Tarun Bansal229647bd002018-02-27 17:33:36737
Mike West2fddeeb72019-02-15 11:29:48738 size_t count_user_agent_hint_headers_seen_;
Maks Orlovich5dcc99c2020-02-13 19:07:46739 size_t count_ua_mobile_client_hints_headers_seen_;
Tarun Bansal1965b042017-09-07 04:59:19740 size_t count_client_hints_headers_seen_;
Tarun Bansala61f0f62017-10-24 23:53:05741
Jay Civelli1ff872d2018-03-09 21:52:16742 std::unique_ptr<ThirdPartyURLLoaderInterceptor> request_interceptor_;
Tarun Bansal229647bd002018-02-27 17:33:36743
Tarun Bansalbef6d652018-10-02 18:41:01744 // Set to 2G in SetUpCommandLine().
745 net::EffectiveConnectionType expected_ect = net::EFFECTIVE_CONNECTION_TYPE_2G;
746
Tarun Bansala61f0f62017-10-24 23:53:05747 DISALLOW_COPY_AND_ASSIGN(ClientHintsBrowserTest);
Tarun Bansal0b8b7afd2017-08-25 03:52:16748};
749
Tarun Bansal9a7051f2018-07-10 18:30:05750// True if testing for http-equiv correctness. When set to true, the tests
751// use webpages that may contain http-equiv Accept-CH and Accept-CH-Lifetime
752// headers. When set to false, the tests use webpages that set the headers in
753// the HTTP response headers.
Ilia Samsonov282c38412019-12-09 08:15:10754INSTANTIATE_TEST_SUITE_P(All,
Victor Costane5e91512019-02-13 08:24:02755 ClientHintsBrowserTest,
756 testing::Bool());
Tarun Bansal9a7051f2018-07-10 18:30:05757
Tarun Bansalea0d8262018-05-21 16:11:50758class ClientHintsAllowThirdPartyBrowserTest : public ClientHintsBrowserTest {
Mike West2fddeeb72019-02-15 11:29:48759 std::unique_ptr<base::FeatureList> EnabledFeatures() override {
760 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
761 feature_list->InitializeFromCommandLine(
762 "AllowClientHintsToThirdParty,UserAgentClientHint", "");
763 return feature_list;
Tarun Bansalea0d8262018-05-21 16:11:50764 }
765};
766
Ilia Samsonov282c38412019-12-09 08:15:10767INSTANTIATE_TEST_SUITE_P(All,
Aaron Tagliaboschia09ec442019-09-18 15:29:03768 ClientHintsAllowThirdPartyBrowserTest,
769 testing::Bool());
770
Tarun Bansal74e189d2018-05-07 19:07:35771IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, CorsChecks) {
Mike West14c11102019-02-04 16:16:47772 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansal74e189d2018-05-07 19:07:35773 // Do not test for headers that have not been enabled on the blink "stable"
774 // yet.
775 if (std::string(blink::kClientHintsHeaderMapping[i]) == "rtt" ||
776 std::string(blink::kClientHintsHeaderMapping[i]) == "downlink" ||
777 std::string(blink::kClientHintsHeaderMapping[i]) == "ect") {
778 continue;
779 }
Takashi Toyoshima2e01e692018-11-16 03:23:27780 EXPECT_TRUE(network::cors::IsCorsSafelistedHeader(
Tarun Bansal74e189d2018-05-07 19:07:35781 blink::kClientHintsHeaderMapping[i], "42" /* value */));
782 }
Takashi Toyoshima2e01e692018-11-16 03:23:27783 EXPECT_FALSE(network::cors::IsCorsSafelistedHeader("not-a-client-hint-header",
Tarun Bansal74e189d2018-05-07 19:07:35784 "" /* value */));
785 EXPECT_TRUE(
Takashi Toyoshima2e01e692018-11-16 03:23:27786 network::cors::IsCorsSafelistedHeader("save-data", "on" /* value */));
Tarun Bansal74e189d2018-05-07 19:07:35787}
788
Tarun Bansal0b8b7afd2017-08-25 03:52:16789// Loads a webpage that requests persisting of client hints. Verifies that
790// the browser receives the mojo notification from the renderer and persists the
791// client hints to the disk.
Tarun Bansal9a7051f2018-07-10 18:30:05792IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, ClientHintsHttps) {
Tarun Bansal0b8b7afd2017-08-25 03:52:16793 base::HistogramTester histogram_tester;
Tarun Bansal9a7051f2018-07-10 18:30:05794 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
795 : accept_ch_with_lifetime_url();
796 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal0b8b7afd2017-08-25 03:52:16797
798 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
799
800 content::FetchHistogramsFromChildProcesses();
801 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
802
Aaron Tagliaboschibe775e12019-12-09 19:33:04803 // client_hints_url() sets twelve client hints.
804 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12, 1);
Tarun Bansal1965b042017-09-07 04:59:19805 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
806 // seconds.
Tarun Bansal0b8b7afd2017-08-25 03:52:16807 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
808 3600 * 1000, 1);
809}
810
Tarun Bansaladd5e1812018-02-09 19:07:58811// Test that client hints are attached to subresources only if they belong
812// to the same host as document host.
Tarun Bansal9a7051f2018-07-10 18:30:05813IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansaladd5e1812018-02-09 19:07:58814 ClientHintsHttpsSubresourceDifferentOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:05815 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
816 : accept_ch_with_lifetime_url();
817
Tarun Bansaladd5e1812018-02-09 19:07:58818 base::HistogramTester histogram_tester;
819
820 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:05821 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:58822 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
823
824 // Verify that the client hints settings for localhost have been saved.
825 ContentSettingsForOneType client_hints_settings;
826 HostContentSettingsMap* host_content_settings_map =
827 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
828 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:45829 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansaladd5e1812018-02-09 19:07:58830 ASSERT_EQ(1U, client_hints_settings.size());
831
832 // Copy the client hints setting for localhost to foo.com.
833 host_content_settings_map->SetWebsiteSettingDefaultScope(
Darin Fisher42f5e7d2019-10-30 07:15:45834 GURL("https://foo.com/"), GURL(), ContentSettingsType::CLIENT_HINTS,
Tarun Bansaladd5e1812018-02-09 19:07:58835 std::string(),
Jeremy Romanec48d7a2018-03-01 17:35:09836 std::make_unique<base::Value>(
Oksana Zhuravlovab14dc882018-04-12 17:34:57837 client_hints_settings.at(0).setting_value.Clone()));
Tarun Bansaladd5e1812018-02-09 19:07:58838
839 // Verify that client hints for the two hosts has been saved.
840 host_content_settings_map =
841 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
842 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:45843 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansaladd5e1812018-02-09 19:07:58844 ASSERT_EQ(2U, client_hints_settings.size());
845
846 // Navigating to without_accept_ch_without_lifetime_img_localhost() should
847 // attach client hints to the image subresouce contained in that page since
848 // the image is located on the same server as the document origin.
Tarun Bansal229647bd002018-02-27 17:33:36849 SetClientHintExpectationsOnMainFrame(true);
850 SetClientHintExpectationsOnSubresources(true);
Tarun Bansaladd5e1812018-02-09 19:07:58851 ui_test_utils::NavigateToURL(
852 browser(), without_accept_ch_without_lifetime_img_localhost());
853 base::RunLoop().RunUntilIdle();
854 content::FetchHistogramsFromChildProcesses();
855 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
856
Maks Orlovich5dcc99c2020-02-13 19:07:46857 // The user agent hint is attached to all three requests, as is UA-mobile:
Mike West2fddeeb72019-02-15 11:29:48858 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:46859 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:48860
Maks Orlovich5dcc99c2020-02-13 19:07:46861 // Ten other client hints are attached to the image request, and ten to the
Mike West2fddeeb72019-02-15 11:29:48862 // main frame request.
Maks Orlovich5dcc99c2020-02-13 19:07:46863 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58864
865 // Navigating to without_accept_ch_without_lifetime_img_foo_com() should not
866 // attach client hints to the image subresouce contained in that page since
867 // the image is located on a different server as the document origin.
Tarun Bansaladd5e1812018-02-09 19:07:58868 ui_test_utils::NavigateToURL(
869 browser(), without_accept_ch_without_lifetime_img_foo_com());
870 base::RunLoop().RunUntilIdle();
871 content::FetchHistogramsFromChildProcesses();
872 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
873
Tarun Bansalb30b7532018-03-14 21:50:38874 // The device-memory and dprheader is attached to the main frame request.
Tarun Bansal5c28afb2018-03-17 02:55:20875#if defined(OS_ANDROID)
Maks Orlovich5dcc99c2020-02-13 19:07:46876 EXPECT_EQ(10u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20877#else
Maks Orlovich5dcc99c2020-02-13 19:07:46878 EXPECT_EQ(30u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20879#endif
Mike West2fddeeb72019-02-15 11:29:48880
881 // Requests to third party servers should have only one client hint attached
882 // (`Sec-CH-UA`).
Tarun Bansal229647bd002018-02-27 17:33:36883 EXPECT_EQ(1u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:46884 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58885}
886
Maks Orlovich7227ce0d2020-02-28 17:13:16887// Test that client hints are attached to subresources checks the right setting
888// for OTR profile.
889IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
890 ClientHintsHttpsSubresourceOffTheRecord) {
891 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
892 : accept_ch_with_lifetime_url();
893
894 base::HistogramTester histogram_tester;
895
896 // Add client hints for the embedded test server.
897 ui_test_utils::NavigateToURL(browser(), gurl);
898 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
899
900 // Main profile should get hints for both page and subresources.
901 SetClientHintExpectationsOnMainFrame(true);
902 SetClientHintExpectationsOnSubresources(true);
903 ui_test_utils::NavigateToURL(
904 browser(), without_accept_ch_without_lifetime_img_localhost());
905 base::RunLoop().RunUntilIdle();
906 content::FetchHistogramsFromChildProcesses();
907 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
908
909 // The user agent hint is attached to all three requests:
910 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
911 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
912
913 // Ten other client hints are attached to the image request, and ten to the
914 // main frame request.
915 EXPECT_EQ(20u, count_client_hints_headers_seen());
916
917 // OTR profile should get neither.
918 Browser* otr_browser = CreateIncognitoBrowser(browser()->profile());
919 SetClientHintExpectationsOnMainFrame(false);
920 SetClientHintExpectationsOnSubresources(false);
921 ui_test_utils::NavigateToURL(
922 otr_browser, without_accept_ch_without_lifetime_img_localhost());
923}
924
Mike Weste555be862019-02-20 16:17:30925// Verify that we send only major version information in the `Sec-CH-UA` header
926// by default, and full version information after an opt-in.
927IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, UserAgentVersion) {
928 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
929 : accept_ch_with_lifetime_url();
930
931 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
932
933 // Navigate to a page that opts-into the header: the value should end with
934 // the major version, and not contain the full version.
935 SetClientHintExpectationsOnMainFrame(false);
936 ui_test_utils::NavigateToURL(browser(), gurl);
937 EXPECT_TRUE(base::EndsWith(main_frame_ua_observed(), ua.major_version,
938 base::CompareCase::SENSITIVE));
939 EXPECT_EQ(std::string::npos, main_frame_ua_observed().find(ua.full_version));
940
941 // Navigate again, after the opt-in: the value should end with the full
942 // version.
943 SetClientHintExpectationsOnMainFrame(true);
944 ui_test_utils::NavigateToURL(browser(), gurl);
945 EXPECT_TRUE(base::EndsWith(main_frame_ua_observed(), ua.full_version,
946 base::CompareCase::SENSITIVE));
947}
948
Maks Orlovich7227ce0d2020-02-28 17:13:16949void ClientHintsBrowserTest::TestProfilesIndependent(Browser* browser_a,
950 Browser* browser_b) {
951 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
952 : accept_ch_with_lifetime_url();
953
954 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
955
956 // Navigate |browser_a| to a page that opts-into the header: the value should
957 // end with the major version, and not contain the full version.
958 SetClientHintExpectationsOnMainFrame(false);
959 ui_test_utils::NavigateToURL(browser_a, gurl);
960 EXPECT_TRUE(base::EndsWith(main_frame_ua_observed(), ua.major_version,
961 base::CompareCase::SENSITIVE));
962 EXPECT_EQ(std::string::npos, main_frame_ua_observed().find(ua.full_version));
963
964 // Try again on |browser_a|, the header should have an effect there.
965 SetClientHintExpectationsOnMainFrame(true);
966 ui_test_utils::NavigateToURL(browser_a, gurl);
967 EXPECT_TRUE(base::EndsWith(main_frame_ua_observed(), ua.full_version,
968 base::CompareCase::SENSITIVE));
969
970 // Navigate on |browser_b|. That should still only have the major
971 // version.
972 SetClientHintExpectationsOnMainFrame(false);
973 ui_test_utils::NavigateToURL(browser_b, gurl);
974 EXPECT_TRUE(base::EndsWith(main_frame_ua_observed(), ua.major_version,
975 base::CompareCase::SENSITIVE));
976 EXPECT_EQ(std::string::npos, main_frame_ua_observed().find(ua.full_version));
977}
978
979// Check that client hints attached to navigation inside OTR profiles
980// use the right settings, regular -> OTR direction.
981IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, OffTheRecordIndependent) {
982 TestProfilesIndependent(browser(),
983 CreateIncognitoBrowser(browser()->profile()));
984}
985
986// Check that client hints attached to navigation inside OTR profiles
987// use the right settings, OTR -> regular direction.
988IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, OffTheRecordIndependent2) {
989 TestProfilesIndependent(CreateIncognitoBrowser(browser()->profile()),
990 browser());
991}
992
Tarun Bansalea0d8262018-05-21 16:11:50993// Test that client hints are attached to third party subresources if
994// AllowClientHintsToThirdParty feature is enabled.
Tarun Bansal9a7051f2018-07-10 18:30:05995IN_PROC_BROWSER_TEST_P(ClientHintsAllowThirdPartyBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:50996 ClientHintsThirdPartyAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:05997 const GURL gurl = GetParam()
998 ? http_equiv_accept_ch_without_lifetime_img_localhost()
999 : accept_ch_without_lifetime_img_localhost();
1000
Tarun Bansalea0d8262018-05-21 16:11:501001 base::HistogramTester histogram_tester;
1002
1003 SetClientHintExpectationsOnMainFrame(false);
1004 SetClientHintExpectationsOnSubresources(true);
1005
1006 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:051007 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansalea0d8262018-05-21 16:11:501008 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1009
Maks Orlovich5dcc99c2020-02-13 19:07:461010 EXPECT_EQ(10u, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:501011
1012 // Requests to third party servers should not have client hints attached.
1013 EXPECT_EQ(1u, third_party_request_count_seen());
1014
Aaron Tagliaboschia09ec442019-09-18 15:29:031015 // Device memory, viewport width, DRP, and UA client hints should be sent to
1016 // the third-party when feature "AllowClientHintsToThirdParty" is enabled.
Maks Orlovich5dcc99c2020-02-13 19:07:461017 EXPECT_EQ(5u, third_party_client_hints_count_seen());
Tarun Bansalea0d8262018-05-21 16:11:501018}
1019
1020// Test that client hints are not attached to third party subresources if
1021// AllowClientHintsToThirdParty feature is not enabled.
Tarun Bansal9a7051f2018-07-10 18:30:051022IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:501023 ClientHintsThirdPartyNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051024 const GURL gurl = GetParam()
1025 ? http_equiv_accept_ch_without_lifetime_img_localhost()
1026 : accept_ch_without_lifetime_img_localhost();
1027
Tarun Bansalea0d8262018-05-21 16:11:501028 base::HistogramTester histogram_tester;
1029
1030 SetClientHintExpectationsOnMainFrame(false);
1031 SetClientHintExpectationsOnSubresources(true);
1032
1033 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:051034 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansalea0d8262018-05-21 16:11:501035 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1036
Mike West2fddeeb72019-02-15 11:29:481037 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461038 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
1039 EXPECT_EQ(10u, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:501040
1041 // Requests to third party servers should not have client hints attached.
1042 EXPECT_EQ(1u, third_party_request_count_seen());
1043
1044 // Client hints should not be sent to the third-party when feature
Mike West2fddeeb72019-02-15 11:29:481045 // "AllowClientHintsToThirdParty" is not enabled, with the exception of the
1046 // `Sec-CH-UA` hint, which is sent with every request.
Maks Orlovich5dcc99c2020-02-13 19:07:461047 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansalea0d8262018-05-21 16:11:501048}
1049
Tarun Bansaladd5e1812018-02-09 19:07:581050// Loads a HTTPS webpage that does not request persisting of client hints.
Tarun Bansal345418632018-06-29 11:07:041051// A same-origin iframe loaded by the webpage requests persistence of client
1052// hints. Verify that the request from the iframe is honored, and client hints
1053// preference is persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051054IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:041055 PersistenceRequestIframe_SameOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:051056 const GURL gurl =
1057 GetParam() ? accept_ch_without_lifetime_with_iframe_url()
1058 : http_equiv_accept_ch_without_lifetime_with_iframe_url();
Tarun Bansal345418632018-06-29 11:07:041059 base::HistogramTester histogram_tester;
1060 ContentSettingsForOneType host_settings;
1061
1062 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451063 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal345418632018-06-29 11:07:041064 &host_settings);
1065 EXPECT_EQ(0u, host_settings.size());
1066
Tarun Bansal9a7051f2018-07-10 18:30:051067 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal345418632018-06-29 11:07:041068
1069 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
1070
1071 content::FetchHistogramsFromChildProcesses();
1072 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1073
1074 // accept_ch_without_lifetime_with_iframe_url() loads
1075 // accept_ch_with_lifetime() in an iframe. The request to persist client
1076 // hints from accept_ch_with_lifetime() should be persisted.
1077 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 1);
1078 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1079 3600 * 1000, 1);
1080}
1081
1082// Loads a HTTPS webpage that does not request persisting of client hints.
1083// An iframe loaded by the webpage from an cross origin server requests
1084// persistence of client hints.
1085// Verify that the request from the cross origin iframe is not honored, and
1086// client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051087IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:041088 DisregardPersistenceRequestIframe_CrossOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:051089 const GURL gurl =
1090 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
1091 : accept_ch_without_lifetime_with_iframe_url();
1092
1093 intercept_iframe_resource_ = gurl.path();
1094 intercept_to_http_equiv_iframe_ = GetParam();
1095
Tarun Bansaladd5e1812018-02-09 19:07:581096 base::HistogramTester histogram_tester;
1097 ContentSettingsForOneType host_settings;
1098
1099 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451100 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansaladd5e1812018-02-09 19:07:581101 &host_settings);
1102 EXPECT_EQ(0u, host_settings.size());
1103
Tarun Bansal9a7051f2018-07-10 18:30:051104 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:581105
1106 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1107
1108 content::FetchHistogramsFromChildProcesses();
1109 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1110
1111 // accept_ch_without_lifetime_with_iframe_url() loads
Tarun Bansal345418632018-06-29 11:07:041112 // accept_ch_with_lifetime() in a cross origin iframe. The request to persist
1113 // client hints from accept_ch_with_lifetime() should be disregarded.
Tarun Bansaladd5e1812018-02-09 19:07:581114 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1115 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1116}
1117
Tarun Bansal62cc3542018-06-27 23:53:301118// Loads a HTTPS webpage that does not request persisting of client hints.
1119// A subresource loaded by the webpage requests persistence of client hints.
1120// Verify that the request from the subresource is not honored, and client hints
1121// preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051122IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:301123 DisregardPersistenceRequestSubresource) {
Tarun Bansal9a7051f2018-07-10 18:30:051124 const GURL gurl =
1125 GetParam() ? http_equiv_accept_ch_without_lifetime_with_subresource_url()
1126 : accept_ch_without_lifetime_with_subresource_url();
1127
Tarun Bansal62cc3542018-06-27 23:53:301128 base::HistogramTester histogram_tester;
1129 ContentSettingsForOneType host_settings;
1130
1131 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451132 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal62cc3542018-06-27 23:53:301133 &host_settings);
1134 EXPECT_EQ(0u, host_settings.size());
1135
Tarun Bansal9a7051f2018-07-10 18:30:051136 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:301137
1138 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1139
1140 content::FetchHistogramsFromChildProcesses();
1141 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1142
1143 // accept_ch_without_lifetime_with_subresource_url() loads
1144 // accept_ch_with_lifetime() as a subresource. The request to persist client
1145 // hints from accept_ch_with_lifetime() should be disregarded.
1146 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1147 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1148}
1149
1150// Loads a HTTPS webpage that does not request persisting of client hints.
1151// A subresource loaded by the webpage in an iframe requests persistence of
1152// client hints. Verify that the request from the subresource in the iframe
1153// is not honored, and client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051154IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:301155 DisregardPersistenceRequestSubresourceIframe) {
Tarun Bansal9a7051f2018-07-10 18:30:051156 const GURL gurl =
1157 GetParam()
1158 ? http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url()
1159 : accept_ch_without_lifetime_with_subresource_iframe_url();
1160
Tarun Bansal62cc3542018-06-27 23:53:301161 base::HistogramTester histogram_tester;
1162 ContentSettingsForOneType host_settings;
1163
1164 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451165 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal62cc3542018-06-27 23:53:301166 &host_settings);
1167 EXPECT_EQ(0u, host_settings.size());
1168
Tarun Bansal9a7051f2018-07-10 18:30:051169 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:301170
1171 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1172
1173 content::FetchHistogramsFromChildProcesses();
1174 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1175
Tarun Bansal9a7051f2018-07-10 18:30:051176 // |gurl| loads accept_ch_with_lifetime() or
1177 // http_equiv_accept_ch_with_lifetime() as a subresource in an iframe. The
1178 // request to persist client hints from accept_ch_with_lifetime() or
1179 // http_equiv_accept_ch_with_lifetime() should be disregarded.
Tarun Bansal62cc3542018-06-27 23:53:301180 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1181 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1182}
1183
Tarun Bansal3b330b02017-11-09 19:03:141184// Loads a HTTP local webpage (which qualifies as a secure context) that
1185// requests persisting of client hints. Verifies that the browser receives the
1186// mojo notification from the renderer and persists the client hints to the
1187// disk.
Tarun Bansal9a7051f2018-07-10 18:30:051188IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal3b330b02017-11-09 19:03:141189 ClientHintsLifetimeFollowedByNoClientHintHttpLocal) {
Tarun Bansal9a7051f2018-07-10 18:30:051190 const GURL gurl = GetParam()
1191 ? http_equiv_accept_ch_with_lifetime_http_local_url()
1192 : accept_ch_with_lifetime_http_local_url();
1193
Tarun Bansal3b330b02017-11-09 19:03:141194 base::HistogramTester histogram_tester;
1195 ContentSettingsForOneType host_settings;
1196
1197 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451198 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3b330b02017-11-09 19:03:141199 &host_settings);
1200 EXPECT_EQ(0u, host_settings.size());
1201
Tarun Bansal9a7051f2018-07-10 18:30:051202 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal3b330b02017-11-09 19:03:141203
1204 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1205
1206 content::FetchHistogramsFromChildProcesses();
1207 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1208
Aaron Tagliaboschibe775e12019-12-09 19:33:041209 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12u, 1);
Tarun Bansal9a7051f2018-07-10 18:30:051210 // |gurl| sets client hints persist duration to 3600 seconds.
Tarun Bansal3b330b02017-11-09 19:03:141211 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1212 3600 * 1000, 1);
1213
1214 base::RunLoop().RunUntilIdle();
1215
1216 // Clients hints preferences for one origin should be persisted.
1217 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451218 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3b330b02017-11-09 19:03:141219 &host_settings);
1220 EXPECT_EQ(1u, host_settings.size());
1221
Tarun Bansal229647bd002018-02-27 17:33:361222 SetClientHintExpectationsOnMainFrame(true);
1223 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal3b330b02017-11-09 19:03:141224 ui_test_utils::NavigateToURL(browser(),
1225 without_accept_ch_without_lifetime_local_url());
1226
Mike West2fddeeb72019-02-15 11:29:481227 // The user agent hint is attached to all three requests:
1228 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461229 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481230
Maks Orlovich5dcc99c2020-02-13 19:07:461231 // Ten other client hints are attached to the image request, and ten to the
Mike West2fddeeb72019-02-15 11:29:481232 // main frame request.
Maks Orlovich5dcc99c2020-02-13 19:07:461233 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansal3b330b02017-11-09 19:03:141234}
1235
Tarun Bansal0b8b7afd2017-08-25 03:52:161236// Loads a webpage that does not request persisting of client hints.
1237IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {
1238 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:191239 ui_test_utils::NavigateToURL(browser(),
1240 without_accept_ch_without_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:161241
1242 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1243
1244 content::FetchHistogramsFromChildProcesses();
1245 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1246
1247 // no_client_hints_url() does not sets the client hints.
1248 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1249 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1250}
1251
Tarun Bansal9a7051f2018-07-10 18:30:051252IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal1965b042017-09-07 04:59:191253 ClientHintsLifetimeFollowedByNoClientHint) {
Tarun Bansal9a7051f2018-07-10 18:30:051254 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1255 : accept_ch_with_lifetime_url();
1256
Tarun Bansal1965b042017-09-07 04:59:191257 base::HistogramTester histogram_tester;
1258 ContentSettingsForOneType host_settings;
1259
1260 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451261 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191262 &host_settings);
1263 EXPECT_EQ(0u, host_settings.size());
1264
Tarun Bansal9a7051f2018-07-10 18:30:051265 // Fetching |gurl| should persist the request for client hints.
1266 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal1965b042017-09-07 04:59:191267
1268 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1269
1270 content::FetchHistogramsFromChildProcesses();
1271 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1272
Aaron Tagliaboschibe775e12019-12-09 19:33:041273 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12u, 1);
Tarun Bansal1965b042017-09-07 04:59:191274 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1275 // seconds.
1276 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1277 3600 * 1000, 1);
1278 base::RunLoop().RunUntilIdle();
1279
1280 // Clients hints preferences for one origin should be persisted.
1281 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451282 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191283 &host_settings);
1284 EXPECT_EQ(1u, host_settings.size());
1285
Tarun Bansal229647bd002018-02-27 17:33:361286 SetClientHintExpectationsOnMainFrame(true);
1287 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal1965b042017-09-07 04:59:191288 ui_test_utils::NavigateToURL(browser(),
1289 without_accept_ch_without_lifetime_url());
Tarun Bansal6bf54302017-10-02 07:39:141290
Mike West2fddeeb72019-02-15 11:29:481291 // The user agent hint is attached to all three requests:
1292 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461293 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481294
Maks Orlovich5dcc99c2020-02-13 19:07:461295 // Ten other client hints are attached to the image request, and ten to the
Mike West2fddeeb72019-02-15 11:29:481296 // main frame request.
Maks Orlovich5dcc99c2020-02-13 19:07:461297 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansal1965b042017-09-07 04:59:191298}
1299
Tarun Bansal73502f92019-04-16 21:21:191300// Verify that expired persistent client hint preferences are not used.
1301// Verifies this by setting Accept-CH-Lifetime value to 1 second,
1302// and loading a page after 1 second to verify that client hints are not
1303// attached.
1304IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
1305 ShortLifetimeFollowedByNoClientHint) {
1306 const GURL gurl = accept_ch_with_short_lifetime();
1307
1308 base::HistogramTester histogram_tester;
1309 ContentSettingsForOneType host_settings;
1310
1311 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451312 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal73502f92019-04-16 21:21:191313 &host_settings);
1314 EXPECT_EQ(0u, host_settings.size());
1315
1316 // Fetching |gurl| should persist the request for client hints.
1317 ui_test_utils::NavigateToURL(browser(), gurl);
1318
1319 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1320
1321 content::FetchHistogramsFromChildProcesses();
1322 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1323
Aaron Tagliaboschibe775e12019-12-09 19:33:041324 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12u, 1);
Tarun Bansal73502f92019-04-16 21:21:191325 // |gurl| sets client hints persist duration to 1 second.
1326 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration", 1 * 1000,
1327 1);
1328 base::RunLoop().RunUntilIdle();
1329
1330 // Clients hints preferences for one origin should be persisted.
1331 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451332 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal73502f92019-04-16 21:21:191333 &host_settings);
1334 EXPECT_EQ(1u, host_settings.size());
1335
1336 // Sleep for a duration longer than 1 second (duration of persisted client
1337 // hints).
1338 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1001));
1339
1340 SetClientHintExpectationsOnMainFrame(false);
1341 SetClientHintExpectationsOnSubresources(false);
1342 ui_test_utils::NavigateToURL(browser(),
1343 without_accept_ch_without_lifetime_url());
1344
1345 // The user agent hint is attached to all three requests:
1346 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461347 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansal73502f92019-04-16 21:21:191348
1349 // No client hints are attached to the requests since the persisted hints must
1350 // be expired.
1351 EXPECT_EQ(0u, count_client_hints_headers_seen());
1352}
1353
Tarun Bansal293a7b6c2018-12-05 17:41:121354// The test first fetches a page that sets Accept-CH-Lifetime. Next, it fetches
1355// a URL from a different origin. However, that URL response redirects to the
1356// same origin from where the first page was fetched. The test verifies that
1357// on receiving redirect to an origin for which the browser has persisted client
1358// hints prefs, the browser attaches the client hints headers when fetching the
1359// redirected URL.
1360IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
1361 ClientHintsLifetimeFollowedByRedirectToNoClientHint) {
1362 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1363 : accept_ch_with_lifetime_url();
1364
1365 base::HistogramTester histogram_tester;
1366 ContentSettingsForOneType host_settings;
1367
1368 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451369 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal293a7b6c2018-12-05 17:41:121370 &host_settings);
1371 EXPECT_EQ(0u, host_settings.size());
1372
1373 // Fetching |gurl| should persist the request for client hints.
1374 ui_test_utils::NavigateToURL(browser(), gurl);
1375
1376 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1377
1378 content::FetchHistogramsFromChildProcesses();
1379 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1380
Aaron Tagliaboschibe775e12019-12-09 19:33:041381 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12u, 1);
Tarun Bansal293a7b6c2018-12-05 17:41:121382 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1383 // seconds.
1384 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1385 3600 * 1000, 1);
1386 base::RunLoop().RunUntilIdle();
1387
1388 // Clients hints preferences for one origin should be persisted.
1389 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451390 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal293a7b6c2018-12-05 17:41:121391 &host_settings);
1392 EXPECT_EQ(1u, host_settings.size());
1393
1394 SetClientHintExpectationsOnMainFrame(true);
1395 SetClientHintExpectationsOnSubresources(true);
1396 ui_test_utils::NavigateToURL(browser(), redirect_url());
1397
Mike West2fddeeb72019-02-15 11:29:481398 // The user agent hint is attached to all three requests:
1399 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461400 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481401
Maks Orlovich5dcc99c2020-02-13 19:07:461402 // Ten other client hints are attached to the image request, and ten to the
Mike West2fddeeb72019-02-15 11:29:481403 // main frame request.
Maks Orlovich5dcc99c2020-02-13 19:07:461404 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansal293a7b6c2018-12-05 17:41:121405}
1406
Tarun Bansala0c1fc32018-10-03 16:14:521407// Ensure that even when cookies are blocked, client hint preferences are
Tarun Bansala61f0f62017-10-24 23:53:051408// persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051409IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521410 ClientHintsLifetimePersistedCookiesBlocked) {
Tarun Bansal9a7051f2018-07-10 18:30:051411 const GURL gurl_with = GetParam() ? http_equiv_accept_ch_with_lifetime()
1412 : accept_ch_with_lifetime_url();
1413
Tarun Bansala61f0f62017-10-24 23:53:051414 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1415 CookieSettingsFactory::GetForProfile(browser()->profile());
1416 base::HistogramTester histogram_tester;
1417 ContentSettingsForOneType host_settings;
1418
1419 // Block cookies.
1420 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansala0c1fc32018-10-03 16:14:521421 ->SetContentSettingDefaultScope(gurl_with, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451422 ContentSettingsType::COOKIES,
Tarun Bansala61f0f62017-10-24 23:53:051423 std::string(), CONTENT_SETTING_BLOCK);
1424
Tarun Bansala0c1fc32018-10-03 16:14:521425 // Fetching |gurl_with| should persist the request for client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051426 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala0c1fc32018-10-03 16:14:521427 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
Tarun Bansala61f0f62017-10-24 23:53:051428 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451429 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051430 &host_settings);
1431 EXPECT_EQ(1u, host_settings.size());
Tarun Bansala0c1fc32018-10-03 16:14:521432 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051433}
1434
Tarun Bansal9a7051f2018-07-10 18:30:051435IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521436 ClientHintsLifetimeAttachedCookiesBlocked) {
Tarun Bansal9a7051f2018-07-10 18:30:051437 const GURL gurl_with = GetParam() ? http_equiv_accept_ch_with_lifetime()
1438 : accept_ch_with_lifetime_url();
1439 const GURL gurl_without = GetParam()
1440 ? http_equiv_accept_ch_without_lifetime_url()
1441 : accept_ch_without_lifetime_url();
Tarun Bansala61f0f62017-10-24 23:53:051442 base::HistogramTester histogram_tester;
1443 ContentSettingsForOneType host_settings;
1444
1445 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451446 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051447 &host_settings);
1448 EXPECT_EQ(0u, host_settings.size());
1449
Tarun Bansal9a7051f2018-07-10 18:30:051450 // Fetching |gurl_with| should persist the request for client hints.
1451 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala61f0f62017-10-24 23:53:051452 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1453 content::FetchHistogramsFromChildProcesses();
1454 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1455
Aaron Tagliaboschibe775e12019-12-09 19:33:041456 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12u, 1);
Tarun Bansal9a7051f2018-07-10 18:30:051457 // |gurl_with| tries to set client hints persist duration to 3600 seconds.
Tarun Bansala61f0f62017-10-24 23:53:051458 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1459 3600 * 1000, 1);
1460 base::RunLoop().RunUntilIdle();
1461
1462 // Clients hints preferences for one origin should be persisted.
1463 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451464 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051465 &host_settings);
1466 EXPECT_EQ(1u, host_settings.size());
1467
Tarun Bansala0c1fc32018-10-03 16:14:521468 // Block the cookies: Client hints should be attached.
Tarun Bansala61f0f62017-10-24 23:53:051469 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051470 ->SetContentSettingDefaultScope(gurl_without, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451471 ContentSettingsType::COOKIES,
Tarun Bansala61f0f62017-10-24 23:53:051472 std::string(), CONTENT_SETTING_BLOCK);
1473
Tarun Bansal229647bd002018-02-27 17:33:361474 SetClientHintExpectationsOnMainFrame(true);
1475 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051476 ui_test_utils::NavigateToURL(browser(),
1477 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361478
Mike West2fddeeb72019-02-15 11:29:481479 // The user agent hint is attached to all three requests:
1480 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461481 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481482
Maks Orlovich5dcc99c2020-02-13 19:07:461483 // Ten other client hints are attached to the image request, and ten to the
Mike West2fddeeb72019-02-15 11:29:481484 // main frame request.
Maks Orlovich5dcc99c2020-02-13 19:07:461485 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051486
1487 // Clear settings.
1488 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451489 ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
Tarun Bansala61f0f62017-10-24 23:53:051490}
1491
1492// Ensure that when the JavaScript is blocked, client hint preferences are not
1493// persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051494IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051495 ClientHintsLifetimeNotPersistedJavaScriptBlocked) {
1496 ContentSettingsForOneType host_settings;
1497
1498 // Start a navigation. This navigation makes it possible to block JavaScript
1499 // later.
1500 ui_test_utils::NavigateToURL(browser(),
1501 without_accept_ch_without_lifetime_url());
1502
Tarun Bansal9a7051f2018-07-10 18:30:051503 const GURL gurl =
1504 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
1505 : accept_ch_with_lifetime_url();
1506
Tarun Bansala61f0f62017-10-24 23:53:051507 // Block the JavaScript: Client hint preferences should not be persisted.
1508 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051509 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451510 ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051511 std::string(), CONTENT_SETTING_BLOCK);
1512 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1513 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451514 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051515 &host_settings);
1516 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:581517 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051518
1519 // Allow the JavaScript: Client hint preferences should be persisted.
1520 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051521 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451522 ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051523 std::string(), CONTENT_SETTING_ALLOW);
1524 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1525 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451526 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051527 &host_settings);
1528 EXPECT_EQ(1u, host_settings.size());
Tarun Bansal593790112018-03-20 04:53:341529
1530 // Clear settings.
1531 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451532 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:051533}
1534
1535// Ensure that when the JavaScript is blocked, persisted client hints are not
1536// attached to the request headers.
Tarun Bansal9a7051f2018-07-10 18:30:051537IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051538 ClientHintsLifetimeNotAttachedJavaScriptBlocked) {
Tarun Bansal9a7051f2018-07-10 18:30:051539 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1540 : accept_ch_with_lifetime_url();
1541
Tarun Bansala61f0f62017-10-24 23:53:051542 base::HistogramTester histogram_tester;
1543 ContentSettingsForOneType host_settings;
1544
1545 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451546 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051547 &host_settings);
1548 EXPECT_EQ(0u, host_settings.size());
1549
1550 // Fetching accept_ch_with_lifetime_url() should persist the request for
1551 // client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051552 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansala61f0f62017-10-24 23:53:051553 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1554 content::FetchHistogramsFromChildProcesses();
1555 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Mike West2fddeeb72019-02-15 11:29:481556 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461557 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051558
Aaron Tagliaboschibe775e12019-12-09 19:33:041559 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12u, 1);
Tarun Bansala61f0f62017-10-24 23:53:051560 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
1561 // 3600 seconds.
1562 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1563 3600 * 1000, 1);
1564 base::RunLoop().RunUntilIdle();
1565
1566 // Clients hints preferences for one origin should be persisted.
1567 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451568 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051569 &host_settings);
1570 EXPECT_EQ(1u, host_settings.size());
1571
Changwan Ryu434c3a32019-07-30 23:42:581572 // Block JavaScript via WebPreferences: Client hints should not be attached.
1573 SetJsEnabledForActiveView(false);
1574
1575 SetClientHintExpectationsOnMainFrame(false);
1576 SetClientHintExpectationsOnSubresources(false);
1577 ui_test_utils::NavigateToURL(browser(),
1578 without_accept_ch_without_lifetime_url());
1579
1580 EXPECT_EQ(0u, count_client_hints_headers_seen());
1581 VerifyContentSettingsNotNotified();
1582 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461583 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Changwan Ryu434c3a32019-07-30 23:42:581584
1585 SetJsEnabledForActiveView(true);
1586
1587 // Block JavaScript via ContentSetting: Client hints should not be attached.
Tarun Bansala61f0f62017-10-24 23:53:051588 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1589 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
Darin Fisher42f5e7d2019-10-30 07:15:451590 GURL(), ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051591 std::string(), CONTENT_SETTING_BLOCK);
1592 ui_test_utils::NavigateToURL(browser(),
1593 without_accept_ch_without_lifetime_url());
1594 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581595 VerifyContentSettingsNotNotified();
Mike West2fddeeb72019-02-15 11:29:481596 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461597 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051598
Changwan Ryu434c3a32019-07-30 23:42:581599 // Allow JavaScript: Client hints should now be attached.
Tarun Bansala61f0f62017-10-24 23:53:051600 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1601 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
Darin Fisher42f5e7d2019-10-30 07:15:451602 GURL(), ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051603 std::string(), CONTENT_SETTING_ALLOW);
1604
Tarun Bansal229647bd002018-02-27 17:33:361605 SetClientHintExpectationsOnMainFrame(true);
1606 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051607 ui_test_utils::NavigateToURL(browser(),
1608 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361609
Mike West2fddeeb72019-02-15 11:29:481610 // The user agent hint is attached to all three requests:
1611 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461612 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481613
Maks Orlovich5dcc99c2020-02-13 19:07:461614 // Ten other client hints are attached to the image request, and ten to the
Mike West2fddeeb72019-02-15 11:29:481615 // main frame request.
Maks Orlovich5dcc99c2020-02-13 19:07:461616 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051617
1618 // Clear settings.
1619 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451620 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:051621}
1622
Tarun Bansal73502f92019-04-16 21:21:191623// Test that if the content settings are malformed, then the browser does not
1624// crash.
1625IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
1626 ClientHintsMalformedContentSettings) {
1627 ContentSettingsForOneType client_hints_settings;
1628 HostContentSettingsMap* host_content_settings_map =
1629 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
1630
1631 // Add setting for the host.
1632 std::unique_ptr<base::ListValue> expiration_times_list =
1633 std::make_unique<base::ListValue>();
1634 expiration_times_list->AppendInteger(42 /* client hint value */);
1635 auto expiration_times_dictionary = std::make_unique<base::DictionaryValue>();
1636 expiration_times_dictionary->SetList("client_hints",
1637 std::move(expiration_times_list));
Aaron Tagliaboschi3c96a682019-10-29 18:10:281638 expiration_times_dictionary->SetDouble(
1639 "expiration_time",
1640 (base::Time::Now() + base::TimeDelta::FromDays(1)).ToDoubleT());
Tarun Bansal73502f92019-04-16 21:21:191641 host_content_settings_map->SetWebsiteSettingDefaultScope(
1642 without_accept_ch_without_lifetime_url(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451643 ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal73502f92019-04-16 21:21:191644 std::make_unique<base::Value>(expiration_times_dictionary->Clone()));
1645
1646 // Reading the settings should now return one setting.
1647 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:451648 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansal73502f92019-04-16 21:21:191649 EXPECT_EQ(1U, client_hints_settings.size());
1650
1651 SetClientHintExpectationsOnMainFrame(false);
1652 SetClientHintExpectationsOnSubresources(false);
1653 ui_test_utils::NavigateToURL(browser(),
1654 without_accept_ch_without_lifetime_url());
1655}
1656
Tarun Bansal229647bd002018-02-27 17:33:361657// Ensure that when the JavaScript is blocked, client hints requested using
Tarun Bansal3f343d7c2018-03-02 18:48:001658// Accept-CH are not attached to the request headers for subresources.
Tarun Bansal9a7051f2018-07-10 18:30:051659IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal229647bd002018-02-27 17:33:361660 ClientHintsNoLifetimeScriptNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051661 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1662 : accept_ch_with_lifetime_url();
1663
Tarun Bansal1965b042017-09-07 04:59:191664 base::HistogramTester histogram_tester;
1665 ContentSettingsForOneType host_settings;
1666
1667 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451668 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191669 &host_settings);
1670 EXPECT_EQ(0u, host_settings.size());
1671
Tarun Bansal3f343d7c2018-03-02 18:48:001672 // Block the Javascript: Client hints should not be attached.
1673 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361674 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1675 ->SetContentSettingDefaultScope(
1676 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451677 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361678 CONTENT_SETTING_BLOCK);
1679 ui_test_utils::NavigateToURL(browser(),
1680 accept_ch_without_lifetime_img_localhost());
Mike West2fddeeb72019-02-15 11:29:481681 EXPECT_EQ(0u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461682 EXPECT_EQ(0u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001683 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361684 EXPECT_EQ(1u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001685 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal1965b042017-09-07 04:59:191686
Tarun Bansal3f343d7c2018-03-02 18:48:001687 // Allow the Javascript: Client hints should now be attached.
Tarun Bansal229647bd002018-02-27 17:33:361688 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1689 ->SetContentSettingDefaultScope(
1690 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451691 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361692 CONTENT_SETTING_ALLOW);
Tarun Bansal1965b042017-09-07 04:59:191693
Tarun Bansal229647bd002018-02-27 17:33:361694 SetClientHintExpectationsOnSubresources(true);
1695 ui_test_utils::NavigateToURL(browser(),
1696 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:001697
Mike West2fddeeb72019-02-15 11:29:481698 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461699 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
1700 EXPECT_EQ(10u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361701 EXPECT_EQ(2u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461702 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581703 VerifyContentSettingsNotNotified();
Tarun Bansal1965b042017-09-07 04:59:191704
Tarun Bansal229647bd002018-02-27 17:33:361705 // Clear settings.
1706 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451707 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansal1965b042017-09-07 04:59:191708
Tarun Bansal229647bd002018-02-27 17:33:361709 // Block the Javascript again: Client hints should not be attached.
Tarun Bansal3f343d7c2018-03-02 18:48:001710 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361711 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1712 ->SetContentSettingDefaultScope(
1713 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451714 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361715 CONTENT_SETTING_BLOCK);
1716 ui_test_utils::NavigateToURL(browser(),
1717 accept_ch_without_lifetime_img_localhost());
Mike West2fddeeb72019-02-15 11:29:481718 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461719 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
1720 EXPECT_EQ(10u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361721 EXPECT_EQ(3u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461722 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341723
1724 // Clear settings.
1725 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451726 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansal229647bd002018-02-27 17:33:361727}
1728
Tarun Bansala0c1fc32018-10-03 16:14:521729// Ensure that when the cookies is blocked, client hints are attached to the
Tarun Bansal3f343d7c2018-03-02 18:48:001730// request headers.
Tarun Bansal9a7051f2018-07-10 18:30:051731IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521732 ClientHintsLifetimeCookiesNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051733 const GURL gurl = GetParam()
1734 ? http_equiv_accept_ch_without_lifetime_img_localhost()
1735 : accept_ch_without_lifetime_img_localhost();
1736
Tarun Bansal229647bd002018-02-27 17:33:361737 base::HistogramTester histogram_tester;
1738 ContentSettingsForOneType host_settings;
1739 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1740 CookieSettingsFactory::GetForProfile(browser()->profile());
1741
Tarun Bansal1965b042017-09-07 04:59:191742 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451743 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191744 &host_settings);
1745 EXPECT_EQ(0u, host_settings.size());
1746
Tarun Bansal229647bd002018-02-27 17:33:361747 // Block cookies.
1748 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051749 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451750 ContentSettingsType::COOKIES,
Tarun Bansal9a7051f2018-07-10 18:30:051751 std::string(), CONTENT_SETTING_BLOCK);
Tarun Bansal229647bd002018-02-27 17:33:361752 base::RunLoop().RunUntilIdle();
1753
Tarun Bansal229647bd002018-02-27 17:33:361754 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal9a7051f2018-07-10 18:30:051755 ui_test_utils::NavigateToURL(browser(), gurl);
Mike West2fddeeb72019-02-15 11:29:481756 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461757 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
1758 EXPECT_EQ(10u, count_client_hints_headers_seen());
Tarun Bansala0c1fc32018-10-03 16:14:521759 EXPECT_EQ(1u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461760 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341761
1762 // Clear settings.
1763 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451764 ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
Tarun Bansal1965b042017-09-07 04:59:191765}
1766
Tarun Bansal3ce0ca42018-06-25 22:52:221767// Verify that client hints are sent in the incognito profiles, and server
1768// client hint opt-ins are honored within the incognito profile.
Tarun Bansal9a7051f2018-07-10 18:30:051769IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal3ce0ca42018-06-25 22:52:221770 ClientHintsLifetimeFollowedByNoClientHintIncognito) {
Tarun Bansal9a7051f2018-07-10 18:30:051771 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1772 : accept_ch_with_lifetime_url();
1773
Tarun Bansal3ce0ca42018-06-25 22:52:221774 base::HistogramTester histogram_tester;
1775 Browser* incognito = CreateIncognitoBrowser();
1776 ContentSettingsForOneType host_settings;
1777
1778 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451779 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3ce0ca42018-06-25 22:52:221780 &host_settings);
1781 EXPECT_EQ(0u, host_settings.size());
1782
Tarun Bansal9a7051f2018-07-10 18:30:051783 // Fetching |gurl| should persist the request for client hints.
1784 ui_test_utils::NavigateToURL(incognito, gurl);
Tarun Bansal3ce0ca42018-06-25 22:52:221785
1786 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1787
1788 content::FetchHistogramsFromChildProcesses();
1789 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1790
Aaron Tagliaboschibe775e12019-12-09 19:33:041791 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 12u, 1);
Tarun Bansal3ce0ca42018-06-25 22:52:221792 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1793 // seconds.
1794 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1795 3600 * 1000, 1);
1796 base::RunLoop().RunUntilIdle();
1797
1798 // Clients hints preferences for one origin should be persisted.
1799 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451800 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3ce0ca42018-06-25 22:52:221801 &host_settings);
1802 EXPECT_EQ(1u, host_settings.size());
1803
1804 SetClientHintExpectationsOnMainFrame(true);
1805 SetClientHintExpectationsOnSubresources(true);
1806 ui_test_utils::NavigateToURL(incognito,
1807 without_accept_ch_without_lifetime_url());
1808
Mike West2fddeeb72019-02-15 11:29:481809 // The user agent hint is attached to all three requests:
1810 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461811 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481812
Maks Orlovich5dcc99c2020-02-13 19:07:461813 // Ten other client hints are attached to the image request, and ten to the
Mike West2fddeeb72019-02-15 11:29:481814 // main frame request.
Maks Orlovich5dcc99c2020-02-13 19:07:461815 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:221816
1817 // Navigate using regular profile. Client hints should not be send.
1818 SetClientHintExpectationsOnMainFrame(false);
1819 SetClientHintExpectationsOnSubresources(false);
1820 ui_test_utils::NavigateToURL(browser(),
1821 without_accept_ch_without_lifetime_url());
1822
Mike West2fddeeb72019-02-15 11:29:481823 // The user agent hint is attached to the two new requests.
1824 EXPECT_EQ(5u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461825 EXPECT_EQ(5u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481826
1827 // No additional hints are sent.
Maks Orlovich5dcc99c2020-02-13 19:07:461828 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:221829}
Tarun Bansalbef6d652018-10-02 18:41:011830
1831class ClientHintsWebHoldbackBrowserTest : public ClientHintsBrowserTest {
1832 public:
1833 ClientHintsWebHoldbackBrowserTest() : ClientHintsBrowserTest() {
1834 ConfigureHoldbackExperiment();
1835 }
1836
1837 net::EffectiveConnectionType web_effective_connection_type_override() const {
1838 return web_effective_connection_type_override_;
1839 }
1840
Mike West2fddeeb72019-02-15 11:29:481841 std::unique_ptr<base::FeatureList> EnabledFeatures() override {
Tarun Bansalbef6d652018-10-02 18:41:011842 base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
1843 const std::string kTrialName = "TrialFoo";
1844 const std::string kGroupName = "GroupFoo"; // Value not used
1845
1846 scoped_refptr<base::FieldTrial> trial =
1847 base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
1848
1849 std::map<std::string, std::string> params;
1850
1851 params["web_effective_connection_type_override"] =
1852 net::GetNameForEffectiveConnectionType(
1853 web_effective_connection_type_override_);
Mike West2fddeeb72019-02-15 11:29:481854 EXPECT_TRUE(
Tarun Bansalbef6d652018-10-02 18:41:011855 base::FieldTrialParamAssociator::GetInstance()
1856 ->AssociateFieldTrialParams(kTrialName, kGroupName, params));
1857
1858 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
Mike West2fddeeb72019-02-15 11:29:481859 feature_list->InitializeFromCommandLine("UserAgentClientHint", "");
Tarun Bansalbef6d652018-10-02 18:41:011860 feature_list->RegisterFieldTrialOverride(
1861 features::kNetworkQualityEstimatorWebHoldback.name,
1862 base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
Mike West2fddeeb72019-02-15 11:29:481863 return feature_list;
Tarun Bansalbef6d652018-10-02 18:41:011864 }
1865
Mike West2fddeeb72019-02-15 11:29:481866 private:
1867 void ConfigureHoldbackExperiment() {}
1868
Tarun Bansalbef6d652018-10-02 18:41:011869 const net::EffectiveConnectionType web_effective_connection_type_override_ =
1870 net::EFFECTIVE_CONNECTION_TYPE_3G;
Tarun Bansalbef6d652018-10-02 18:41:011871};
1872
1873// Make sure that when NetInfo holdback experiment is enabled, the NetInfo APIs
1874// and client hints return the overridden values. Verify that the client hints
1875// are overridden on both main frame and subresource requests.
1876IN_PROC_BROWSER_TEST_F(ClientHintsWebHoldbackBrowserTest,
1877 EffectiveConnectionTypeChangeNotified) {
1878 SetExpectedEffectiveConnectionType(web_effective_connection_type_override());
1879
1880 SetClientHintExpectationsOnMainFrame(false);
1881 SetClientHintExpectationsOnSubresources(true);
1882
1883 base::RunLoop().RunUntilIdle();
1884
1885 EXPECT_TRUE(embedded_test_server()->Start());
1886 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1887 EXPECT_EQ(0u, count_client_hints_headers_seen());
1888 EXPECT_EQ(0u, third_party_request_count_seen());
1889 EXPECT_EQ(0u, third_party_client_hints_count_seen());
1890
1891 SetClientHintExpectationsOnMainFrame(true);
1892 SetClientHintExpectationsOnSubresources(true);
1893 ui_test_utils::NavigateToURL(
1894 browser(), accept_ch_without_lifetime_with_subresource_url());
1895 base::RunLoop().RunUntilIdle();
1896 content::FetchHistogramsFromChildProcesses();
1897 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1898
Mike West2fddeeb72019-02-15 11:29:481899 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461900 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
1901 EXPECT_EQ(20u, count_client_hints_headers_seen());
Tarun Bansalbef6d652018-10-02 18:41:011902 EXPECT_EQ(0u, third_party_request_count_seen());
1903 EXPECT_EQ(0u, third_party_client_hints_count_seen());
1904}