blob: 76fc8192cc4b961be2c2102a176a64dcafaae054 [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
Tarun Bansal229647bd002018-02-27 17:33:367#include "base/bind.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:168#include "base/command_line.h"
Tarun Bansalbef6d652018-10-02 18:41:019#include "base/metrics/field_trial_param_associator.h"
Gabriel Charetteb71eec892017-09-14 22:52:5610#include "base/run_loop.h"
Tarun Bansal6bf54302017-10-02 07:39:1411#include "base/stl_util.h"
Devlin Cronin626d80c2018-06-01 01:08:3612#include "base/test/metrics/histogram_tester.h"
Tarun Bansal5c28afb2018-03-17 02:55:2013#include "build/build_config.h"
Tarun Bansala61f0f62017-10-24 23:53:0514#include "chrome/browser/content_settings/cookie_settings_factory.h"
Tarun Bansal1965b042017-09-07 04:59:1915#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
Tarun Bansalc211d8b2018-03-19 19:21:5816#include "chrome/browser/content_settings/tab_specific_content_settings.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1617#include "chrome/browser/metrics/subprocess_metrics_provider.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1618#include "chrome/browser/profiles/profile.h"
Tarun Bansal1965b042017-09-07 04:59:1919#include "chrome/browser/ui/browser.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1620#include "chrome/test/base/in_process_browser_test.h"
21#include "chrome/test/base/ui_test_utils.h"
Tarun Bansala61f0f62017-10-24 23:53:0522#include "components/content_settings/core/browser/cookie_settings.h"
Tarun Bansal1965b042017-09-07 04:59:1923#include "components/content_settings/core/browser/host_content_settings_map.h"
Tarun Bansala61f0f62017-10-24 23:53:0524#include "components/content_settings/core/common/pref_names.h"
25#include "components/prefs/pref_service.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1626#include "content/public/browser/browser_thread.h"
Tarun Bansalbef6d652018-10-02 18:41:0127#include "content/public/common/content_features.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1628#include "content/public/common/content_switches.h"
29#include "content/public/test/browser_test_utils.h"
30#include "content/public/test/test_utils.h"
Tarun Bansal229647bd002018-02-27 17:33:3631#include "content/public/test/url_loader_interceptor.h"
32#include "net/dns/mock_host_resolver.h"
33#include "net/http/http_request_headers.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4734#include "net/nqe/effective_connection_type.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1635#include "net/test/embedded_test_server/embedded_test_server.h"
Tarun Bansal1965b042017-09-07 04:59:1936#include "net/test/embedded_test_server/http_request.h"
Tarun Bansal229647bd002018-02-27 17:33:3637#include "net/test/embedded_test_server/http_response.h"
Tarun Bansal74e189d2018-05-07 19:07:3538#include "services/network/public/cpp/cors/cors.h"
Tarun Bansalceab9592018-05-01 18:57:3539#include "services/network/public/cpp/features.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4740#include "services/network/public/cpp/network_switches.h"
Blink Reformata30d4232018-04-07 15:31:0641#include "third_party/blink/public/common/client_hints/client_hints.h"
Tarun Bansal229647bd002018-02-27 17:33:3642
43namespace {
44
45// An interceptor that records count of fetches and client hint headers for
46// requests to https://foo.com/non-existing-image.jpg.
Jay Civelli1ff872d2018-03-09 21:52:1647class ThirdPartyURLLoaderInterceptor {
Tarun Bansal229647bd002018-02-27 17:33:3648 public:
Jay Civelli1ff872d2018-03-09 21:52:1649 explicit ThirdPartyURLLoaderInterceptor(const GURL intercepted_url)
50 : intercepted_url_(intercepted_url),
51 interceptor_(base::BindRepeating(
52 &ThirdPartyURLLoaderInterceptor::InterceptURLRequest,
53 base::Unretained(this))) {}
Tarun Bansal229647bd002018-02-27 17:33:3654
Jay Civelli1ff872d2018-03-09 21:52:1655 ~ThirdPartyURLLoaderInterceptor() = default;
Tarun Bansal229647bd002018-02-27 17:33:3656
57 size_t request_count_seen() const { return request_count_seen_; }
58
59 size_t client_hints_count_seen() const { return client_hints_count_seen_; }
60
61 private:
Jay Civelli1ff872d2018-03-09 21:52:1662 bool InterceptURLRequest(
63 content::URLLoaderInterceptor::RequestParams* params) {
64 if (params->url_request.url != intercepted_url_)
65 return false;
Tarun Bansal229647bd002018-02-27 17:33:3666
Jay Civelli1ff872d2018-03-09 21:52:1667 request_count_seen_++;
Mike West14c11102019-02-04 16:16:4768 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansalf9cf9892018-04-06 04:38:0169 if (params->url_request.headers.HasHeader(
70 blink::kClientHintsHeaderMapping[i])) {
71 client_hints_count_seen_++;
72 }
Tarun Bansal5c28afb2018-03-17 02:55:2073 }
Jay Civelli1ff872d2018-03-09 21:52:1674 return false;
75 }
Tarun Bansal229647bd002018-02-27 17:33:3676
Jay Civelli1ff872d2018-03-09 21:52:1677 GURL intercepted_url_;
78
79 size_t request_count_seen_ = 0u;
80
81 size_t client_hints_count_seen_ = 0u;
82
83 content::URLLoaderInterceptor interceptor_;
84
85 DISALLOW_COPY_AND_ASSIGN(ThirdPartyURLLoaderInterceptor);
Tarun Bansal229647bd002018-02-27 17:33:3686};
87
Tarun Bansal62efba12018-05-04 22:58:3588// Returns true only if |header_value| satisfies ABNF: 1*DIGIT [ "." 1*DIGIT ]
89bool IsSimilarToDoubleABNF(const std::string& header_value) {
90 if (header_value.empty())
91 return false;
92 char first_char = header_value.at(0);
93 if (!isdigit(first_char))
94 return false;
95
96 bool period_found = false;
97 bool digit_found_after_period = false;
98 for (char ch : header_value) {
99 if (isdigit(ch)) {
100 if (period_found) {
101 digit_found_after_period = true;
102 }
103 continue;
104 }
105 if (ch == '.') {
106 if (period_found)
107 return false;
108 period_found = true;
109 continue;
110 }
111 return false;
112 }
113 if (period_found)
114 return digit_found_after_period;
115 return true;
116}
117
118// Returns true only if |header_value| satisfies ABNF: 1*DIGIT
119bool IsSimilarToIntABNF(const std::string& header_value) {
120 if (header_value.empty())
121 return false;
122
123 for (char ch : header_value) {
124 if (!isdigit(ch))
125 return false;
126 }
127 return true;
128}
129
Tarun Bansal229647bd002018-02-27 17:33:36130} // namespace
Tarun Bansal0b8b7afd2017-08-25 03:52:16131
Tarun Bansal9a7051f2018-07-10 18:30:05132class ClientHintsBrowserTest : public InProcessBrowserTest,
133 public testing::WithParamInterface<bool> {
Tarun Bansal0b8b7afd2017-08-25 03:52:16134 public:
135 ClientHintsBrowserTest()
Tarun Bansal3b330b02017-11-09 19:03:14136 : http_server_(net::EmbeddedTestServer::TYPE_HTTP),
137 https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal345418632018-06-29 11:07:04138 https_cross_origin_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal229647bd002018-02-27 17:33:36139 expect_client_hints_on_main_frame_(false),
140 expect_client_hints_on_subresources_(false),
141 count_client_hints_headers_seen_(0),
142 request_interceptor_(nullptr) {
Tarun Bansal3b330b02017-11-09 19:03:14143 http_server_.ServeFilesFromSourceDirectory("chrome/test/data/client_hints");
Tarun Bansal0b8b7afd2017-08-25 03:52:16144 https_server_.ServeFilesFromSourceDirectory(
145 "chrome/test/data/client_hints");
Tarun Bansal345418632018-06-29 11:07:04146 https_cross_origin_server_.ServeFilesFromSourceDirectory(
147 "chrome/test/data/client_hints");
Tarun Bansal1965b042017-09-07 04:59:19148
Tarun Bansal3b330b02017-11-09 19:03:14149 http_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04150 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
151 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19152 https_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04153 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
154 base::Unretained(this)));
155 https_cross_origin_server_.RegisterRequestMonitor(
156 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
157 base::Unretained(this)));
Tarun Bansal293a7b6c2018-12-05 17:41:12158 https_cross_origin_server_.RegisterRequestHandler(
159 base::BindRepeating(&ClientHintsBrowserTest::RequestHandlerToRedirect,
160 base::Unretained(this)));
Tarun Bansal345418632018-06-29 11:07:04161 https_server_.RegisterRequestHandler(base::BindRepeating(
162 &ClientHintsBrowserTest::RequestHandlerToFetchCrossOriginIframe,
163 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19164
Tarun Bansal3b330b02017-11-09 19:03:14165 EXPECT_TRUE(http_server_.Start());
Tarun Bansal0b8b7afd2017-08-25 03:52:16166 EXPECT_TRUE(https_server_.Start());
Tarun Bansal345418632018-06-29 11:07:04167 EXPECT_TRUE(https_cross_origin_server_.Start());
168
169 EXPECT_NE(https_server_.base_url(), https_cross_origin_server_.base_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16170
Tarun Bansal3b330b02017-11-09 19:03:14171 accept_ch_with_lifetime_http_local_url_ =
172 http_server_.GetURL("/accept_ch_with_lifetime.html");
Tarun Bansal9a7051f2018-07-10 18:30:05173 http_equiv_accept_ch_with_lifetime_http_local_url_ =
174 http_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal3b330b02017-11-09 19:03:14175 EXPECT_TRUE(accept_ch_with_lifetime_http_local_url_.SchemeIsHTTPOrHTTPS());
176 EXPECT_FALSE(
177 accept_ch_with_lifetime_http_local_url_.SchemeIsCryptographic());
178
Tarun Bansal1965b042017-09-07 04:59:19179 accept_ch_with_lifetime_url_ =
180 https_server_.GetURL("/accept_ch_with_lifetime.html");
181 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
182 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal0b8b7afd2017-08-25 03:52:16183
Tarun Bansal1965b042017-09-07 04:59:19184 accept_ch_without_lifetime_url_ =
185 https_server_.GetURL("/accept_ch_without_lifetime.html");
186 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
187 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal9a7051f2018-07-10 18:30:05188 http_equiv_accept_ch_without_lifetime_url_ =
189 https_server_.GetURL("/http_equiv_accept_ch_without_lifetime.html");
Tarun Bansal1965b042017-09-07 04:59:19190
191 without_accept_ch_without_lifetime_url_ =
192 https_server_.GetURL("/without_accept_ch_without_lifetime.html");
193 EXPECT_TRUE(without_accept_ch_without_lifetime_url_.SchemeIsHTTPOrHTTPS());
194 EXPECT_TRUE(
195 without_accept_ch_without_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal3b330b02017-11-09 19:03:14196
197 without_accept_ch_without_lifetime_local_url_ =
198 http_server_.GetURL("/without_accept_ch_without_lifetime.html");
199 EXPECT_TRUE(
200 without_accept_ch_without_lifetime_local_url_.SchemeIsHTTPOrHTTPS());
201 EXPECT_FALSE(
202 without_accept_ch_without_lifetime_local_url_.SchemeIsCryptographic());
Tarun Bansaladd5e1812018-02-09 19:07:58203
204 without_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
205 "/without_accept_ch_without_lifetime_img_localhost.html");
206 without_accept_ch_without_lifetime_img_foo_com_ = https_server_.GetURL(
207 "/without_accept_ch_without_lifetime_img_foo_com.html");
208 accept_ch_without_lifetime_with_iframe_url_ =
209 https_server_.GetURL("/accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05210 http_equiv_accept_ch_without_lifetime_with_iframe_url_ =
211 https_server_.GetURL(
212 "/http_equiv_accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal62cc3542018-06-27 23:53:30213 accept_ch_without_lifetime_with_subresource_url_ = https_server_.GetURL(
214 "/accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal9a7051f2018-07-10 18:30:05215 http_equiv_accept_ch_without_lifetime_with_subresource_url_ =
216 https_server_.GetURL(
217 "/http_equiv_accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal62cc3542018-06-27 23:53:30218 accept_ch_without_lifetime_with_subresource_iframe_url_ =
219 https_server_.GetURL(
220 "/accept_ch_without_lifetime_with_subresource_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05221 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_ =
222 https_server_.GetURL(
223 "/http_equiv_accept_ch_without_lifetime_with_subresource_iframe."
224 "html");
Tarun Bansal229647bd002018-02-27 17:33:36225 accept_ch_without_lifetime_img_localhost_ =
226 https_server_.GetURL("/accept_ch_without_lifetime_img_localhost.html");
Tarun Bansal9a7051f2018-07-10 18:30:05227 http_equiv_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
228 "/http_equiv_accept_ch_without_lifetime_img_localhost.html");
229 http_equiv_accept_ch_with_lifetime_ =
230 https_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal293a7b6c2018-12-05 17:41:12231
232 redirect_url_ = https_cross_origin_server_.GetURL("/redirect.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16233 }
234
235 ~ClientHintsBrowserTest() override {}
236
237 void SetUpOnMainThread() override {
Tarun Bansal229647bd002018-02-27 17:33:36238 host_resolver()->AddRule("*", "127.0.0.1");
Tarun Bansal229647bd002018-02-27 17:33:36239
Jay Civelli1ff872d2018-03-09 21:52:16240 request_interceptor_ = std::make_unique<ThirdPartyURLLoaderInterceptor>(
241 GURL("https://foo.com/non-existing-image.jpg"));
Tarun Bansal229647bd002018-02-27 17:33:36242 base::RunLoop().RunUntilIdle();
Tarun Bansal0b8b7afd2017-08-25 03:52:16243 }
244
Jay Civelli1ff872d2018-03-09 21:52:16245 void TearDownOnMainThread() override { request_interceptor_.reset(); }
246
Tarun Bansal0b8b7afd2017-08-25 03:52:16247 void SetUpCommandLine(base::CommandLine* cmd) override {
Tarun Bansal7f3fe8c2018-04-06 22:37:47248 cmd->AppendSwitchASCII(network::switches::kForceEffectiveConnectionType,
249 net::kEffectiveConnectionType2G);
Mike West14c11102019-02-04 16:16:47250 cmd->AppendSwitchASCII(switches::kEnableBlinkFeatures,
251 "LangClientHintHeader");
Tarun Bansal0b8b7afd2017-08-25 03:52:16252 }
253
Tarun Bansal229647bd002018-02-27 17:33:36254 void SetClientHintExpectationsOnMainFrame(bool expect_client_hints) {
255 expect_client_hints_on_main_frame_ = expect_client_hints;
Tarun Bansal1965b042017-09-07 04:59:19256 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16257
Tarun Bansal229647bd002018-02-27 17:33:36258 void SetClientHintExpectationsOnSubresources(bool expect_client_hints) {
259 expect_client_hints_on_subresources_ = expect_client_hints;
Tarun Bansala61f0f62017-10-24 23:53:05260 }
261
Tarun Bansalc211d8b2018-03-19 19:21:58262 // Verify that the user is not notified that cookies or JavaScript were
263 // blocked on the webpage due to the checks done by client hints.
264 void VerifyContentSettingsNotNotified() const {
265 content::WebContents* web_contents =
266 browser()->tab_strip_model()->GetActiveWebContents();
267 EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents)
268 ->IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
269
270 EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents)
271 ->IsContentBlocked(CONTENT_SETTINGS_TYPE_JAVASCRIPT));
272 }
273
Tarun Bansalbef6d652018-10-02 18:41:01274 void SetExpectedEffectiveConnectionType(
275 net::EffectiveConnectionType effective_connection_type) {
276 expected_ect = effective_connection_type;
277 }
278
Tarun Bansal3b330b02017-11-09 19:03:14279 const GURL& accept_ch_with_lifetime_http_local_url() const {
280 return accept_ch_with_lifetime_http_local_url_;
281 }
Tarun Bansal9a7051f2018-07-10 18:30:05282 const GURL& http_equiv_accept_ch_with_lifetime_http_local_url() const {
283 return http_equiv_accept_ch_with_lifetime_http_local_url_;
284 }
Tarun Bansal3b330b02017-11-09 19:03:14285
Tarun Bansal1965b042017-09-07 04:59:19286 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
287 // headers.
288 const GURL& accept_ch_with_lifetime_url() const {
289 return accept_ch_with_lifetime_url_;
290 }
Tarun Bansal9a7051f2018-07-10 18:30:05291 const GURL& http_equiv_accept_ch_with_lifetime() {
292 return http_equiv_accept_ch_with_lifetime_;
293 }
Tarun Bansal1965b042017-09-07 04:59:19294
295 // A URL whose response headers include only Accept-CH header.
296 const GURL& accept_ch_without_lifetime_url() const {
297 return accept_ch_without_lifetime_url_;
298 }
Tarun Bansal9a7051f2018-07-10 18:30:05299 const GURL& http_equiv_accept_ch_without_lifetime_url() const {
300 return http_equiv_accept_ch_without_lifetime_url_;
301 }
Tarun Bansal1965b042017-09-07 04:59:19302
303 // A URL whose response headers do not include either Accept-CH or
304 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
305 const GURL& without_accept_ch_without_lifetime_url() const {
306 return without_accept_ch_without_lifetime_url_;
307 }
308
Tarun Bansal3b330b02017-11-09 19:03:14309 // A URL whose response headers do not include either Accept-CH or
310 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
311 const GURL& without_accept_ch_without_lifetime_local_url() const {
312 return without_accept_ch_without_lifetime_local_url_;
313 }
314
Tarun Bansaladd5e1812018-02-09 19:07:58315 // A URL whose response headers do not include either Accept-CH or
316 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
317 // from localhost.
318 const GURL& without_accept_ch_without_lifetime_img_localhost() const {
319 return without_accept_ch_without_lifetime_img_localhost_;
320 }
321
322 // A URL whose response headers do not include either Accept-CH or
323 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
324 // from foo.com.
325 const GURL& without_accept_ch_without_lifetime_img_foo_com() const {
326 return without_accept_ch_without_lifetime_img_foo_com_;
327 }
328
329 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
330 // headers. The response loads accept_ch_with_lifetime_url() in an iframe.
331 const GURL& accept_ch_without_lifetime_with_iframe_url() const {
332 return accept_ch_without_lifetime_with_iframe_url_;
333 }
Tarun Bansal9a7051f2018-07-10 18:30:05334 const GURL& http_equiv_accept_ch_without_lifetime_with_iframe_url() const {
335 return http_equiv_accept_ch_without_lifetime_with_iframe_url_;
336 }
Tarun Bansaladd5e1812018-02-09 19:07:58337
Tarun Bansal62cc3542018-06-27 23:53:30338 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
339 // headers. The response loads accept_ch_with_lifetime_url() as a subresource
340 // in the main frame.
341 const GURL& accept_ch_without_lifetime_with_subresource_url() const {
342 return accept_ch_without_lifetime_with_subresource_url_;
343 }
Tarun Bansal9a7051f2018-07-10 18:30:05344 const GURL& http_equiv_accept_ch_without_lifetime_with_subresource_url()
345 const {
346 return http_equiv_accept_ch_without_lifetime_with_subresource_url_;
347 }
Tarun Bansal62cc3542018-06-27 23:53:30348
349 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
Tarun Bansal9a7051f2018-07-10 18:30:05350 // headers. The response loads accept_ch_with_lifetime_url() or
351 // http_equiv_accept_ch_with_lifetime_url() as a subresource in the iframe.
Tarun Bansal62cc3542018-06-27 23:53:30352 const GURL& accept_ch_without_lifetime_with_subresource_iframe_url() const {
353 return accept_ch_without_lifetime_with_subresource_iframe_url_;
354 }
Tarun Bansal9a7051f2018-07-10 18:30:05355 const GURL&
356 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url() const {
357 return http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
358 }
Tarun Bansal62cc3542018-06-27 23:53:30359
Tarun Bansal9a7051f2018-07-10 18:30:05360 // A URL whose response includes only Accept-CH header. Navigating to
Tarun Bansal229647bd002018-02-27 17:33:36361 // this URL also fetches two images: One from the localhost, and one from
362 // foo.com.
363 const GURL& accept_ch_without_lifetime_img_localhost() const {
364 return accept_ch_without_lifetime_img_localhost_;
365 }
Tarun Bansal9a7051f2018-07-10 18:30:05366 const GURL& http_equiv_accept_ch_without_lifetime_img_localhost() const {
367 return http_equiv_accept_ch_without_lifetime_img_localhost_;
368 }
Tarun Bansal229647bd002018-02-27 17:33:36369
Tarun Bansal293a7b6c2018-12-05 17:41:12370 const GURL& redirect_url() const { return redirect_url_; }
371
Tarun Bansal1965b042017-09-07 04:59:19372 size_t count_client_hints_headers_seen() const {
373 return count_client_hints_headers_seen_;
374 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16375
Tarun Bansal229647bd002018-02-27 17:33:36376 size_t third_party_request_count_seen() const {
377 return request_interceptor_->request_count_seen();
378 }
379
380 size_t third_party_client_hints_count_seen() const {
381 return request_interceptor_->client_hints_count_seen();
382 }
383
Tarun Bansalea0d8262018-05-21 16:11:50384 base::test::ScopedFeatureList scoped_feature_list_;
385
Tarun Bansal345418632018-06-29 11:07:04386 std::string intercept_iframe_resource_;
Tarun Bansal9a7051f2018-07-10 18:30:05387 bool intercept_to_http_equiv_iframe_ = false;
Tarun Bansal345418632018-06-29 11:07:04388
Tarun Bansal0b8b7afd2017-08-25 03:52:16389 private:
Tarun Bansal345418632018-06-29 11:07:04390 // Intercepts only the main frame requests that contain
Tarun Bansal293a7b6c2018-12-05 17:41:12391 // "redirect" in the resource path. The intercepted requests
392 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
393 // server.
394 std::unique_ptr<net::test_server::HttpResponse> RequestHandlerToRedirect(
395 const net::test_server::HttpRequest& request) {
396 // Check if it's a main frame request.
397 if (request.relative_url.find(".html") == std::string::npos)
398 return nullptr;
399
400 if (request.GetURL().spec().find("redirect") == std::string::npos)
401 return nullptr;
402
403 std::unique_ptr<net::test_server::BasicHttpResponse> response;
404 response.reset(new net::test_server::BasicHttpResponse);
405 response->set_code(net::HTTP_FOUND);
406 response->AddCustomHeader("Location",
407 without_accept_ch_without_lifetime_url().spec());
408 return std::move(response);
409 }
410
411 // Intercepts only the main frame requests that contain
Tarun Bansal345418632018-06-29 11:07:04412 // |intercept_iframe_resource_| in the resource path. The intercepted requests
413 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
414 // server.
415 std::unique_ptr<net::test_server::HttpResponse>
416 RequestHandlerToFetchCrossOriginIframe(
417 const net::test_server::HttpRequest& request) {
418 if (intercept_iframe_resource_.empty())
419 return nullptr;
420
421 // Check if it's a main frame request.
422 if (request.relative_url.find(".html") == std::string::npos)
423 return nullptr;
424
425 if (request.relative_url.find(intercept_iframe_resource_) ==
426 std::string::npos) {
427 return nullptr;
428 }
429
430 const std::string iframe_url =
Tarun Bansal9a7051f2018-07-10 18:30:05431 intercept_to_http_equiv_iframe_
432 ? https_cross_origin_server_
433 .GetURL("/http_equiv_accept_ch_with_lifetime.html")
434 .spec()
435 : https_cross_origin_server_.GetURL("/accept_ch_with_lifetime.html")
436 .spec();
Tarun Bansal345418632018-06-29 11:07:04437
438 std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
439 new net::test_server::BasicHttpResponse());
440 http_response->set_code(net::HTTP_OK);
441 http_response->set_content_type("text/html");
442 http_response->set_content(
443 "<html>"
444 "<link rel='icon' href='data:;base64,='><head></head>"
445 "Empty file which uses link-rel to disable favicon fetches. "
446 "<iframe src='" +
447 iframe_url + "'></iframe></html>");
448
449 return std::move(http_response);
450 }
451
Tarun Bansal1965b042017-09-07 04:59:19452 // Called by |https_server_|.
453 void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
Tarun Bansal6bf54302017-10-02 07:39:14454 bool is_main_frame_navigation =
455 request.GetURL().spec().find(".html") != std::string::npos;
456
Tarun Bansal293a7b6c2018-12-05 17:41:12457 if (is_main_frame_navigation &&
458 request.GetURL().spec().find("redirect") != std::string::npos) {
459 return;
460 }
461
Tarun Bansal229647bd002018-02-27 17:33:36462 if (is_main_frame_navigation) {
Tarun Bansalf9cf9892018-04-06 04:38:01463 VerifyClientHintsReceived(expect_client_hints_on_main_frame_, request);
Tarun Bansal5c28afb2018-03-17 02:55:20464 if (expect_client_hints_on_main_frame_) {
465 double value = 0.0;
466 EXPECT_TRUE(base::StringToDouble(
467 request.headers.find("device-memory")->second, &value));
468 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35469 EXPECT_TRUE(IsSimilarToDoubleABNF(
470 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42471 main_frame_device_memory_observed_ = value;
Tarun Bansal5c28afb2018-03-17 02:55:20472
473 EXPECT_TRUE(
474 base::StringToDouble(request.headers.find("dpr")->second, &value));
475 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35476 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42477 main_frame_dpr_observed_ = value;
478
Tarun Bansal5c28afb2018-03-17 02:55:20479 EXPECT_TRUE(base::StringToDouble(
480 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35481 EXPECT_TRUE(
482 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36483#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20484 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36485#else
486 EXPECT_EQ(980, value);
Tarun Bansal5c28afb2018-03-17 02:55:20487#endif
Tarun Bansal44ad96882018-03-28 17:47:42488 main_frame_viewport_width_observed_ = value;
Tarun Bansal7f3fe8c2018-04-06 22:37:47489 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20490 }
Tarun Bansala61f0f62017-10-24 23:53:05491 }
Tarun Bansal6bf54302017-10-02 07:39:14492
Tarun Bansal229647bd002018-02-27 17:33:36493 if (!is_main_frame_navigation) {
Tarun Bansalf9cf9892018-04-06 04:38:01494 VerifyClientHintsReceived(expect_client_hints_on_subresources_, request);
Tarun Bansal5c28afb2018-03-17 02:55:20495
496 if (expect_client_hints_on_subresources_) {
497 double value = 0.0;
498 EXPECT_TRUE(base::StringToDouble(
499 request.headers.find("device-memory")->second, &value));
500 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35501 EXPECT_TRUE(IsSimilarToDoubleABNF(
502 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42503 if (main_frame_device_memory_observed_ > 0) {
504 EXPECT_EQ(main_frame_device_memory_observed_, value);
505 }
Tarun Bansal5c28afb2018-03-17 02:55:20506
507 EXPECT_TRUE(
508 base::StringToDouble(request.headers.find("dpr")->second, &value));
509 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35510 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42511 if (main_frame_dpr_observed_ > 0) {
512 EXPECT_EQ(main_frame_dpr_observed_, value);
513 }
Tarun Bansal5c28afb2018-03-17 02:55:20514
515 EXPECT_TRUE(base::StringToDouble(
516 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35517 EXPECT_TRUE(
518 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36519#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20520 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36521#else
522 EXPECT_EQ(980, value);
523#endif
Tarun Bansal44ad96882018-03-28 17:47:42524#if defined(OS_ANDROID)
525 // TODO(tbansal): https://crbug.com/825892: Viewport width on main
526 // frame requests may be incorrect when the Chrome window is not
527 // maximized.
528 if (main_frame_viewport_width_observed_ > 0) {
529 EXPECT_EQ(main_frame_viewport_width_observed_, value);
530 }
531#endif
Tarun Bansal7f3fe8c2018-04-06 22:37:47532 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20533 }
Tarun Bansala61f0f62017-10-24 23:53:05534 }
Tarun Bansal6bf54302017-10-02 07:39:14535
Mike West14c11102019-02-04 16:16:47536 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansalf9cf9892018-04-06 04:38:01537 if (base::ContainsKey(request.headers,
538 blink::kClientHintsHeaderMapping[i])) {
539 count_client_hints_headers_seen_++;
540 }
541 }
542 }
Tarun Bansal1965b042017-09-07 04:59:19543
Tarun Bansalf9cf9892018-04-06 04:38:01544 void VerifyClientHintsReceived(bool expect_client_hints,
545 const net::test_server::HttpRequest& request) {
Mike West14c11102019-02-04 16:16:47546 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
547 SCOPED_TRACE(testing::Message()
548 << std::string(blink::kClientHintsHeaderMapping[i]));
Tarun Bansalf9cf9892018-04-06 04:38:01549 // Resource width client hint is only attached on image subresources.
550 if (std::string(blink::kClientHintsHeaderMapping[i]) == "width") {
551 continue;
552 }
553 EXPECT_EQ(expect_client_hints,
554 base::ContainsKey(request.headers,
555 blink::kClientHintsHeaderMapping[i]));
556 }
Tarun Bansal1965b042017-09-07 04:59:19557 }
558
Tarun Bansal7f3fe8c2018-04-06 22:37:47559 void VerifyNetworkQualityClientHints(
560 const net::test_server::HttpRequest& request) const {
561 // Effective connection type is forced to 2G using command line in these
562 // tests.
Tarun Bansal509a8dd2018-04-10 17:19:16563 int rtt_value = 0.0;
Tarun Bansal7f3fe8c2018-04-06 22:37:47564 EXPECT_TRUE(
Tarun Bansal509a8dd2018-04-10 17:19:16565 base::StringToInt(request.headers.find("rtt")->second, &rtt_value));
566 EXPECT_LE(0, rtt_value);
Tarun Bansal62efba12018-05-04 22:58:35567 EXPECT_TRUE(IsSimilarToIntABNF(request.headers.find("rtt")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16568 // Verify that RTT value is a multiple of 50 milliseconds.
569 EXPECT_EQ(0, rtt_value % 50);
Tarun Bansalbef6d652018-10-02 18:41:01570 EXPECT_GE(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? 3000 : 500,
571 rtt_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47572
Tarun Bansal509a8dd2018-04-10 17:19:16573 double mbps_value = 0.0;
574 EXPECT_TRUE(base::StringToDouble(request.headers.find("downlink")->second,
575 &mbps_value));
576 EXPECT_LE(0, mbps_value);
Tarun Bansal62efba12018-05-04 22:58:35577 EXPECT_TRUE(
578 IsSimilarToDoubleABNF(request.headers.find("downlink")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16579 // Verify that the mbps value is a multiple of 0.050 mbps.
580 // Allow for small amount of noise due to double to integer conversions.
581 EXPECT_NEAR(0, (static_cast<int>(mbps_value * 1000)) % 50, 1);
582 EXPECT_GE(10.0, mbps_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47583
584 EXPECT_FALSE(request.headers.find("ect")->second.empty());
Tarun Bansalceab9592018-05-01 18:57:35585
586 // TODO(tbansal): https://crbug.com/819244: When network servicification is
Tarun Bansal5ac533542018-08-10 19:45:52587 // enabled, the renderer processes do not receive notifications on
588 // change in the network quality. Hence, the network quality client hints
589 // are not set to the correct value on subresources.
590 bool is_main_frame_navigation =
591 request.GetURL().spec().find(".html") != std::string::npos;
592 if (!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
593 is_main_frame_navigation) {
Tarun Bansalceab9592018-05-01 18:57:35594 // Effective connection type is forced to 2G using command line in these
595 // tests. RTT is expected to be 1800 msec but leave some gap to account
596 // for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01597 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
598 EXPECT_NEAR(1800, rtt_value, 360);
599 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
600 EXPECT_NEAR(450, rtt_value, 90);
601 } else {
602 NOTREACHED();
603 }
Tarun Bansalceab9592018-05-01 18:57:35604
605 // Effective connection type is forced to 2G using command line in these
606 // tests. downlink is expected to be 0.075 Mbps but leave some gap to
607 // account for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01608 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
609 EXPECT_NEAR(0.075, mbps_value, 0.05);
610 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
611 EXPECT_NEAR(0.4, mbps_value, 0.1);
612 } else {
613 NOTREACHED();
614 }
Tarun Bansalceab9592018-05-01 18:57:35615
Tarun Bansalbef6d652018-10-02 18:41:01616 EXPECT_EQ(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? "2g" : "3g",
617 request.headers.find("ect")->second);
Tarun Bansalceab9592018-05-01 18:57:35618 }
Tarun Bansal7f3fe8c2018-04-06 22:37:47619 }
620
Tarun Bansal3b330b02017-11-09 19:03:14621 net::EmbeddedTestServer http_server_;
Tarun Bansal0b8b7afd2017-08-25 03:52:16622 net::EmbeddedTestServer https_server_;
Tarun Bansal345418632018-06-29 11:07:04623 net::EmbeddedTestServer https_cross_origin_server_;
Tarun Bansal3b330b02017-11-09 19:03:14624 GURL accept_ch_with_lifetime_http_local_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05625 GURL http_equiv_accept_ch_with_lifetime_http_local_url_;
Tarun Bansal1965b042017-09-07 04:59:19626 GURL accept_ch_with_lifetime_url_;
627 GURL accept_ch_without_lifetime_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05628 GURL http_equiv_accept_ch_without_lifetime_url_;
Tarun Bansal1965b042017-09-07 04:59:19629 GURL without_accept_ch_without_lifetime_url_;
Tarun Bansal3b330b02017-11-09 19:03:14630 GURL without_accept_ch_without_lifetime_local_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58631 GURL accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05632 GURL http_equiv_accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal62cc3542018-06-27 23:53:30633 GURL accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05634 GURL http_equiv_accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal62cc3542018-06-27 23:53:30635 GURL accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05636 GURL http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58637 GURL without_accept_ch_without_lifetime_img_foo_com_;
638 GURL without_accept_ch_without_lifetime_img_localhost_;
Tarun Bansal229647bd002018-02-27 17:33:36639 GURL accept_ch_without_lifetime_img_localhost_;
Tarun Bansal9a7051f2018-07-10 18:30:05640 GURL http_equiv_accept_ch_without_lifetime_img_localhost_;
641 GURL http_equiv_accept_ch_with_lifetime_;
Tarun Bansal293a7b6c2018-12-05 17:41:12642 GURL redirect_url_;
Tarun Bansal1965b042017-09-07 04:59:19643
Tarun Bansal44ad96882018-03-28 17:47:42644 double main_frame_dpr_observed_ = -1;
645 double main_frame_viewport_width_observed_ = -1;
646 double main_frame_device_memory_observed_ = -1;
647
Tarun Bansal229647bd002018-02-27 17:33:36648 // Expect client hints on all the main frame request.
649 bool expect_client_hints_on_main_frame_;
650 // Expect client hints on all the subresource requests.
651 bool expect_client_hints_on_subresources_;
652
Tarun Bansal1965b042017-09-07 04:59:19653 size_t count_client_hints_headers_seen_;
Tarun Bansala61f0f62017-10-24 23:53:05654
Jay Civelli1ff872d2018-03-09 21:52:16655 std::unique_ptr<ThirdPartyURLLoaderInterceptor> request_interceptor_;
Tarun Bansal229647bd002018-02-27 17:33:36656
Tarun Bansalbef6d652018-10-02 18:41:01657 // Set to 2G in SetUpCommandLine().
658 net::EffectiveConnectionType expected_ect = net::EFFECTIVE_CONNECTION_TYPE_2G;
659
Tarun Bansala61f0f62017-10-24 23:53:05660 DISALLOW_COPY_AND_ASSIGN(ClientHintsBrowserTest);
Tarun Bansal0b8b7afd2017-08-25 03:52:16661};
662
Tarun Bansal9a7051f2018-07-10 18:30:05663// True if testing for http-equiv correctness. When set to true, the tests
664// use webpages that may contain http-equiv Accept-CH and Accept-CH-Lifetime
665// headers. When set to false, the tests use webpages that set the headers in
666// the HTTP response headers.
667INSTANTIATE_TEST_CASE_P(/* no prefix */,
668 ClientHintsBrowserTest,
669 testing::Bool());
670
Tarun Bansalea0d8262018-05-21 16:11:50671class ClientHintsAllowThirdPartyBrowserTest : public ClientHintsBrowserTest {
672 void SetUpCommandLine(base::CommandLine* cmd) override {
673 scoped_feature_list_.InitFromCommandLine("AllowClientHintsToThirdParty",
674 "");
675 ClientHintsBrowserTest::SetUpCommandLine(cmd);
676 }
677};
678
Tarun Bansal74e189d2018-05-07 19:07:35679IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, CorsChecks) {
Mike West14c11102019-02-04 16:16:47680 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansal74e189d2018-05-07 19:07:35681 // Do not test for headers that have not been enabled on the blink "stable"
682 // yet.
683 if (std::string(blink::kClientHintsHeaderMapping[i]) == "rtt" ||
684 std::string(blink::kClientHintsHeaderMapping[i]) == "downlink" ||
685 std::string(blink::kClientHintsHeaderMapping[i]) == "ect") {
686 continue;
687 }
Takashi Toyoshima2e01e692018-11-16 03:23:27688 EXPECT_TRUE(network::cors::IsCorsSafelistedHeader(
Tarun Bansal74e189d2018-05-07 19:07:35689 blink::kClientHintsHeaderMapping[i], "42" /* value */));
690 }
Takashi Toyoshima2e01e692018-11-16 03:23:27691 EXPECT_FALSE(network::cors::IsCorsSafelistedHeader("not-a-client-hint-header",
Tarun Bansal74e189d2018-05-07 19:07:35692 "" /* value */));
693 EXPECT_TRUE(
Takashi Toyoshima2e01e692018-11-16 03:23:27694 network::cors::IsCorsSafelistedHeader("save-data", "on" /* value */));
Tarun Bansal74e189d2018-05-07 19:07:35695}
696
Tarun Bansal0b8b7afd2017-08-25 03:52:16697// Loads a webpage that requests persisting of client hints. Verifies that
698// the browser receives the mojo notification from the renderer and persists the
699// client hints to the disk.
Tarun Bansal9a7051f2018-07-10 18:30:05700IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, ClientHintsHttps) {
Tarun Bansal0b8b7afd2017-08-25 03:52:16701 base::HistogramTester histogram_tester;
Tarun Bansal9a7051f2018-07-10 18:30:05702 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
703 : accept_ch_with_lifetime_url();
704 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal0b8b7afd2017-08-25 03:52:16705
706 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
707
708 content::FetchHistogramsFromChildProcesses();
709 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
710
Mike West14c11102019-02-04 16:16:47711 // client_hints_url() sets seven client hints.
712 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 7, 1);
Tarun Bansal1965b042017-09-07 04:59:19713 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
714 // seconds.
Tarun Bansal0b8b7afd2017-08-25 03:52:16715 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
716 3600 * 1000, 1);
717}
718
Tarun Bansaladd5e1812018-02-09 19:07:58719// Test that client hints are attached to subresources only if they belong
720// to the same host as document host.
Tarun Bansal9a7051f2018-07-10 18:30:05721IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansaladd5e1812018-02-09 19:07:58722 ClientHintsHttpsSubresourceDifferentOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:05723 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
724 : accept_ch_with_lifetime_url();
725
Tarun Bansaladd5e1812018-02-09 19:07:58726 base::HistogramTester histogram_tester;
727
728 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:05729 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:58730 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
731
732 // Verify that the client hints settings for localhost have been saved.
733 ContentSettingsForOneType client_hints_settings;
734 HostContentSettingsMap* host_content_settings_map =
735 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
736 host_content_settings_map->GetSettingsForOneType(
737 CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
738 &client_hints_settings);
739 ASSERT_EQ(1U, client_hints_settings.size());
740
741 // Copy the client hints setting for localhost to foo.com.
742 host_content_settings_map->SetWebsiteSettingDefaultScope(
743 GURL("https://foo.com/"), GURL(), CONTENT_SETTINGS_TYPE_CLIENT_HINTS,
744 std::string(),
Jeremy Romanec48d7a2018-03-01 17:35:09745 std::make_unique<base::Value>(
Oksana Zhuravlovab14dc882018-04-12 17:34:57746 client_hints_settings.at(0).setting_value.Clone()));
Tarun Bansaladd5e1812018-02-09 19:07:58747
748 // Verify that client hints for the two hosts has been saved.
749 host_content_settings_map =
750 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
751 host_content_settings_map->GetSettingsForOneType(
752 CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
753 &client_hints_settings);
754 ASSERT_EQ(2U, client_hints_settings.size());
755
756 // Navigating to without_accept_ch_without_lifetime_img_localhost() should
757 // attach client hints to the image subresouce contained in that page since
758 // the image is located on the same server as the document origin.
Tarun Bansal229647bd002018-02-27 17:33:36759 SetClientHintExpectationsOnMainFrame(true);
760 SetClientHintExpectationsOnSubresources(true);
Tarun Bansaladd5e1812018-02-09 19:07:58761 ui_test_utils::NavigateToURL(
762 browser(), without_accept_ch_without_lifetime_img_localhost());
763 base::RunLoop().RunUntilIdle();
764 content::FetchHistogramsFromChildProcesses();
765 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
766
Mike West14c11102019-02-04 16:16:47767 // seven client hints are attached to the image request, and seven to the main
Tarun Bansal79df868e2018-03-20 23:01:36768 // frame request.
Mike West14c11102019-02-04 16:16:47769 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58770
771 // Navigating to without_accept_ch_without_lifetime_img_foo_com() should not
772 // attach client hints to the image subresouce contained in that page since
773 // the image is located on a different server as the document origin.
Tarun Bansaladd5e1812018-02-09 19:07:58774 ui_test_utils::NavigateToURL(
775 browser(), without_accept_ch_without_lifetime_img_foo_com());
776 base::RunLoop().RunUntilIdle();
777 content::FetchHistogramsFromChildProcesses();
778 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
779
Tarun Bansalb30b7532018-03-14 21:50:38780 // The device-memory and dprheader is attached to the main frame request.
Tarun Bansal5c28afb2018-03-17 02:55:20781#if defined(OS_ANDROID)
Mike West14c11102019-02-04 16:16:47782 EXPECT_EQ(7u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20783#else
Mike West14c11102019-02-04 16:16:47784 EXPECT_EQ(21u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20785#endif
Tarun Bansal229647bd002018-02-27 17:33:36786 // Requests to third party servers should not have client hints attached.
787 EXPECT_EQ(1u, third_party_request_count_seen());
788 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58789}
790
Tarun Bansalea0d8262018-05-21 16:11:50791// Test that client hints are attached to third party subresources if
792// AllowClientHintsToThirdParty feature is enabled.
Tarun Bansal9a7051f2018-07-10 18:30:05793IN_PROC_BROWSER_TEST_P(ClientHintsAllowThirdPartyBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:50794 ClientHintsThirdPartyAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:05795 const GURL gurl = GetParam()
796 ? http_equiv_accept_ch_without_lifetime_img_localhost()
797 : accept_ch_without_lifetime_img_localhost();
798
Tarun Bansalea0d8262018-05-21 16:11:50799 base::HistogramTester histogram_tester;
800
801 SetClientHintExpectationsOnMainFrame(false);
802 SetClientHintExpectationsOnSubresources(true);
803
804 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:05805 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansalea0d8262018-05-21 16:11:50806 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
807
Mike West14c11102019-02-04 16:16:47808 EXPECT_EQ(7u, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:50809
810 // Requests to third party servers should not have client hints attached.
811 EXPECT_EQ(1u, third_party_request_count_seen());
812
813 // Device memory, viewport width and DRP client hints should be sent to the
814 // third-party when feature "AllowClientHintsToThirdParty" is enabled.
815 EXPECT_EQ(3u, third_party_client_hints_count_seen());
816}
817
818// Test that client hints are not attached to third party subresources if
819// AllowClientHintsToThirdParty feature is not enabled.
Tarun Bansal9a7051f2018-07-10 18:30:05820IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:50821 ClientHintsThirdPartyNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:05822 const GURL gurl = GetParam()
823 ? http_equiv_accept_ch_without_lifetime_img_localhost()
824 : accept_ch_without_lifetime_img_localhost();
825
Tarun Bansalea0d8262018-05-21 16:11:50826 base::HistogramTester histogram_tester;
827
828 SetClientHintExpectationsOnMainFrame(false);
829 SetClientHintExpectationsOnSubresources(true);
830
831 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:05832 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansalea0d8262018-05-21 16:11:50833 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
834
Mike West14c11102019-02-04 16:16:47835 EXPECT_EQ(7u, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:50836
837 // Requests to third party servers should not have client hints attached.
838 EXPECT_EQ(1u, third_party_request_count_seen());
839
840 // Client hints should not be sent to the third-party when feature
841 // "AllowClientHintsToThirdParty" is not enabled.
842 EXPECT_EQ(0u, third_party_client_hints_count_seen());
843}
844
Tarun Bansaladd5e1812018-02-09 19:07:58845// Loads a HTTPS webpage that does not request persisting of client hints.
Tarun Bansal345418632018-06-29 11:07:04846// A same-origin iframe loaded by the webpage requests persistence of client
847// hints. Verify that the request from the iframe is honored, and client hints
848// preference is persisted.
Tarun Bansal9a7051f2018-07-10 18:30:05849IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:04850 PersistenceRequestIframe_SameOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:05851 const GURL gurl =
852 GetParam() ? accept_ch_without_lifetime_with_iframe_url()
853 : http_equiv_accept_ch_without_lifetime_with_iframe_url();
Tarun Bansal345418632018-06-29 11:07:04854 base::HistogramTester histogram_tester;
855 ContentSettingsForOneType host_settings;
856
857 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
858 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
859 &host_settings);
860 EXPECT_EQ(0u, host_settings.size());
861
Tarun Bansal9a7051f2018-07-10 18:30:05862 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal345418632018-06-29 11:07:04863
864 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
865
866 content::FetchHistogramsFromChildProcesses();
867 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
868
869 // accept_ch_without_lifetime_with_iframe_url() loads
870 // accept_ch_with_lifetime() in an iframe. The request to persist client
871 // hints from accept_ch_with_lifetime() should be persisted.
872 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 1);
873 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
874 3600 * 1000, 1);
875}
876
877// Loads a HTTPS webpage that does not request persisting of client hints.
878// An iframe loaded by the webpage from an cross origin server requests
879// persistence of client hints.
880// Verify that the request from the cross origin iframe is not honored, and
881// client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:05882IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:04883 DisregardPersistenceRequestIframe_CrossOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:05884 const GURL gurl =
885 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
886 : accept_ch_without_lifetime_with_iframe_url();
887
888 intercept_iframe_resource_ = gurl.path();
889 intercept_to_http_equiv_iframe_ = GetParam();
890
Tarun Bansaladd5e1812018-02-09 19:07:58891 base::HistogramTester histogram_tester;
892 ContentSettingsForOneType host_settings;
893
894 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
895 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
896 &host_settings);
897 EXPECT_EQ(0u, host_settings.size());
898
Tarun Bansal9a7051f2018-07-10 18:30:05899 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:58900
901 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
902
903 content::FetchHistogramsFromChildProcesses();
904 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
905
906 // accept_ch_without_lifetime_with_iframe_url() loads
Tarun Bansal345418632018-06-29 11:07:04907 // accept_ch_with_lifetime() in a cross origin iframe. The request to persist
908 // client hints from accept_ch_with_lifetime() should be disregarded.
Tarun Bansaladd5e1812018-02-09 19:07:58909 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
910 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
911}
912
Tarun Bansal62cc3542018-06-27 23:53:30913// Loads a HTTPS webpage that does not request persisting of client hints.
914// A subresource loaded by the webpage requests persistence of client hints.
915// Verify that the request from the subresource is not honored, and client hints
916// preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:05917IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:30918 DisregardPersistenceRequestSubresource) {
Tarun Bansal9a7051f2018-07-10 18:30:05919 const GURL gurl =
920 GetParam() ? http_equiv_accept_ch_without_lifetime_with_subresource_url()
921 : accept_ch_without_lifetime_with_subresource_url();
922
Tarun Bansal62cc3542018-06-27 23:53:30923 base::HistogramTester histogram_tester;
924 ContentSettingsForOneType host_settings;
925
926 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
927 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
928 &host_settings);
929 EXPECT_EQ(0u, host_settings.size());
930
Tarun Bansal9a7051f2018-07-10 18:30:05931 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:30932
933 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
934
935 content::FetchHistogramsFromChildProcesses();
936 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
937
938 // accept_ch_without_lifetime_with_subresource_url() loads
939 // accept_ch_with_lifetime() as a subresource. The request to persist client
940 // hints from accept_ch_with_lifetime() should be disregarded.
941 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
942 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
943}
944
945// Loads a HTTPS webpage that does not request persisting of client hints.
946// A subresource loaded by the webpage in an iframe requests persistence of
947// client hints. Verify that the request from the subresource in the iframe
948// is not honored, and client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:05949IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:30950 DisregardPersistenceRequestSubresourceIframe) {
Tarun Bansal9a7051f2018-07-10 18:30:05951 const GURL gurl =
952 GetParam()
953 ? http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url()
954 : accept_ch_without_lifetime_with_subresource_iframe_url();
955
Tarun Bansal62cc3542018-06-27 23:53:30956 base::HistogramTester histogram_tester;
957 ContentSettingsForOneType host_settings;
958
959 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
960 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
961 &host_settings);
962 EXPECT_EQ(0u, host_settings.size());
963
Tarun Bansal9a7051f2018-07-10 18:30:05964 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:30965
966 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
967
968 content::FetchHistogramsFromChildProcesses();
969 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
970
Tarun Bansal9a7051f2018-07-10 18:30:05971 // |gurl| loads accept_ch_with_lifetime() or
972 // http_equiv_accept_ch_with_lifetime() as a subresource in an iframe. The
973 // request to persist client hints from accept_ch_with_lifetime() or
974 // http_equiv_accept_ch_with_lifetime() should be disregarded.
Tarun Bansal62cc3542018-06-27 23:53:30975 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
976 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
977}
978
Tarun Bansal3b330b02017-11-09 19:03:14979// Loads a HTTP local webpage (which qualifies as a secure context) that
980// requests persisting of client hints. Verifies that the browser receives the
981// mojo notification from the renderer and persists the client hints to the
982// disk.
Tarun Bansal9a7051f2018-07-10 18:30:05983IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal3b330b02017-11-09 19:03:14984 ClientHintsLifetimeFollowedByNoClientHintHttpLocal) {
Tarun Bansal9a7051f2018-07-10 18:30:05985 const GURL gurl = GetParam()
986 ? http_equiv_accept_ch_with_lifetime_http_local_url()
987 : accept_ch_with_lifetime_http_local_url();
988
Tarun Bansal3b330b02017-11-09 19:03:14989 base::HistogramTester histogram_tester;
990 ContentSettingsForOneType host_settings;
991
992 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
993 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
994 &host_settings);
995 EXPECT_EQ(0u, host_settings.size());
996
Tarun Bansal9a7051f2018-07-10 18:30:05997 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal3b330b02017-11-09 19:03:14998
999 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1000
1001 content::FetchHistogramsFromChildProcesses();
1002 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1003
Mike West14c11102019-02-04 16:16:471004 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 7, 1);
Tarun Bansal9a7051f2018-07-10 18:30:051005 // |gurl| sets client hints persist duration to 3600 seconds.
Tarun Bansal3b330b02017-11-09 19:03:141006 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1007 3600 * 1000, 1);
1008
1009 base::RunLoop().RunUntilIdle();
1010
1011 // Clients hints preferences for one origin should be persisted.
1012 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1013 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1014 &host_settings);
1015 EXPECT_EQ(1u, host_settings.size());
1016
Tarun Bansal229647bd002018-02-27 17:33:361017 SetClientHintExpectationsOnMainFrame(true);
1018 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal3b330b02017-11-09 19:03:141019 ui_test_utils::NavigateToURL(browser(),
1020 without_accept_ch_without_lifetime_local_url());
1021
Mike West14c11102019-02-04 16:16:471022 // seven client hints are attached to the image request, and seven to the main
Tarun Bansal79df868e2018-03-20 23:01:361023 // frame request.
Mike West14c11102019-02-04 16:16:471024 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansal3b330b02017-11-09 19:03:141025}
1026
Tarun Bansal0b8b7afd2017-08-25 03:52:161027// Loads a webpage that does not request persisting of client hints.
1028IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {
1029 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:191030 ui_test_utils::NavigateToURL(browser(),
1031 without_accept_ch_without_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:161032
1033 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1034
1035 content::FetchHistogramsFromChildProcesses();
1036 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1037
1038 // no_client_hints_url() does not sets the client hints.
1039 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1040 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1041}
1042
Tarun Bansal9a7051f2018-07-10 18:30:051043IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal1965b042017-09-07 04:59:191044 ClientHintsLifetimeFollowedByNoClientHint) {
Tarun Bansal9a7051f2018-07-10 18:30:051045 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1046 : accept_ch_with_lifetime_url();
1047
Tarun Bansal1965b042017-09-07 04:59:191048 base::HistogramTester histogram_tester;
1049 ContentSettingsForOneType host_settings;
1050
1051 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1052 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1053 &host_settings);
1054 EXPECT_EQ(0u, host_settings.size());
1055
Tarun Bansal9a7051f2018-07-10 18:30:051056 // Fetching |gurl| should persist the request for client hints.
1057 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal1965b042017-09-07 04:59:191058
1059 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1060
1061 content::FetchHistogramsFromChildProcesses();
1062 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1063
Mike West14c11102019-02-04 16:16:471064 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 7, 1);
Tarun Bansal1965b042017-09-07 04:59:191065 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1066 // seconds.
1067 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1068 3600 * 1000, 1);
1069 base::RunLoop().RunUntilIdle();
1070
1071 // Clients hints preferences for one origin should be persisted.
1072 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1073 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1074 &host_settings);
1075 EXPECT_EQ(1u, host_settings.size());
1076
Tarun Bansal229647bd002018-02-27 17:33:361077 SetClientHintExpectationsOnMainFrame(true);
1078 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal1965b042017-09-07 04:59:191079 ui_test_utils::NavigateToURL(browser(),
1080 without_accept_ch_without_lifetime_url());
Tarun Bansal6bf54302017-10-02 07:39:141081
Mike West14c11102019-02-04 16:16:471082 // seven client hints are attached to the image request, and seven to the main
Tarun Bansal79df868e2018-03-20 23:01:361083 // frame request.
Mike West14c11102019-02-04 16:16:471084 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansal1965b042017-09-07 04:59:191085}
1086
Tarun Bansal293a7b6c2018-12-05 17:41:121087// The test first fetches a page that sets Accept-CH-Lifetime. Next, it fetches
1088// a URL from a different origin. However, that URL response redirects to the
1089// same origin from where the first page was fetched. The test verifies that
1090// on receiving redirect to an origin for which the browser has persisted client
1091// hints prefs, the browser attaches the client hints headers when fetching the
1092// redirected URL.
1093IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
1094 ClientHintsLifetimeFollowedByRedirectToNoClientHint) {
1095 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1096 : accept_ch_with_lifetime_url();
1097
1098 base::HistogramTester histogram_tester;
1099 ContentSettingsForOneType host_settings;
1100
1101 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1102 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1103 &host_settings);
1104 EXPECT_EQ(0u, host_settings.size());
1105
1106 // Fetching |gurl| should persist the request for client hints.
1107 ui_test_utils::NavigateToURL(browser(), gurl);
1108
1109 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1110
1111 content::FetchHistogramsFromChildProcesses();
1112 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1113
Mike West14c11102019-02-04 16:16:471114 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 7, 1);
Tarun Bansal293a7b6c2018-12-05 17:41:121115 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1116 // seconds.
1117 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1118 3600 * 1000, 1);
1119 base::RunLoop().RunUntilIdle();
1120
1121 // Clients hints preferences for one origin should be persisted.
1122 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1123 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1124 &host_settings);
1125 EXPECT_EQ(1u, host_settings.size());
1126
1127 SetClientHintExpectationsOnMainFrame(true);
1128 SetClientHintExpectationsOnSubresources(true);
1129 ui_test_utils::NavigateToURL(browser(), redirect_url());
1130
Mike West14c11102019-02-04 16:16:471131 // seven client hints are attached to the image request, and seven to the main
Tarun Bansal293a7b6c2018-12-05 17:41:121132 // frame request.
Mike West14c11102019-02-04 16:16:471133 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansal293a7b6c2018-12-05 17:41:121134}
1135
Tarun Bansala0c1fc32018-10-03 16:14:521136// Ensure that even when cookies are blocked, client hint preferences are
Tarun Bansala61f0f62017-10-24 23:53:051137// persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051138IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521139 ClientHintsLifetimePersistedCookiesBlocked) {
Tarun Bansal9a7051f2018-07-10 18:30:051140 const GURL gurl_with = GetParam() ? http_equiv_accept_ch_with_lifetime()
1141 : accept_ch_with_lifetime_url();
1142
Tarun Bansala61f0f62017-10-24 23:53:051143 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1144 CookieSettingsFactory::GetForProfile(browser()->profile());
1145 base::HistogramTester histogram_tester;
1146 ContentSettingsForOneType host_settings;
1147
1148 // Block cookies.
1149 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansala0c1fc32018-10-03 16:14:521150 ->SetContentSettingDefaultScope(gurl_with, GURL(),
Tarun Bansala61f0f62017-10-24 23:53:051151 CONTENT_SETTINGS_TYPE_COOKIES,
1152 std::string(), CONTENT_SETTING_BLOCK);
1153
Tarun Bansala0c1fc32018-10-03 16:14:521154 // Fetching |gurl_with| should persist the request for client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051155 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala0c1fc32018-10-03 16:14:521156 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
Tarun Bansala61f0f62017-10-24 23:53:051157 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1158 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1159 &host_settings);
1160 EXPECT_EQ(1u, host_settings.size());
Tarun Bansala0c1fc32018-10-03 16:14:521161 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051162}
1163
Tarun Bansal9a7051f2018-07-10 18:30:051164IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521165 ClientHintsLifetimeAttachedCookiesBlocked) {
Tarun Bansal9a7051f2018-07-10 18:30:051166 const GURL gurl_with = GetParam() ? http_equiv_accept_ch_with_lifetime()
1167 : accept_ch_with_lifetime_url();
1168 const GURL gurl_without = GetParam()
1169 ? http_equiv_accept_ch_without_lifetime_url()
1170 : accept_ch_without_lifetime_url();
Tarun Bansala61f0f62017-10-24 23:53:051171 base::HistogramTester histogram_tester;
1172 ContentSettingsForOneType host_settings;
1173
1174 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1175 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1176 &host_settings);
1177 EXPECT_EQ(0u, host_settings.size());
1178
Tarun Bansal9a7051f2018-07-10 18:30:051179 // Fetching |gurl_with| should persist the request for client hints.
1180 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala61f0f62017-10-24 23:53:051181 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1182 content::FetchHistogramsFromChildProcesses();
1183 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1184
Mike West14c11102019-02-04 16:16:471185 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 7, 1);
Tarun Bansal9a7051f2018-07-10 18:30:051186 // |gurl_with| tries to set client hints persist duration to 3600 seconds.
Tarun Bansala61f0f62017-10-24 23:53:051187 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1188 3600 * 1000, 1);
1189 base::RunLoop().RunUntilIdle();
1190
1191 // Clients hints preferences for one origin should be persisted.
1192 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1193 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1194 &host_settings);
1195 EXPECT_EQ(1u, host_settings.size());
1196
Tarun Bansala0c1fc32018-10-03 16:14:521197 // Block the cookies: Client hints should be attached.
Tarun Bansala61f0f62017-10-24 23:53:051198 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051199 ->SetContentSettingDefaultScope(gurl_without, GURL(),
Tarun Bansala61f0f62017-10-24 23:53:051200 CONTENT_SETTINGS_TYPE_COOKIES,
1201 std::string(), CONTENT_SETTING_BLOCK);
1202
Tarun Bansal229647bd002018-02-27 17:33:361203 SetClientHintExpectationsOnMainFrame(true);
1204 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051205 ui_test_utils::NavigateToURL(browser(),
1206 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361207
Mike West14c11102019-02-04 16:16:471208 // seven client hints are attached to the image request, and seven to the main
Tarun Bansal79df868e2018-03-20 23:01:361209 // frame request.
Mike West14c11102019-02-04 16:16:471210 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051211
1212 // Clear settings.
1213 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1214 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
1215}
1216
1217// Ensure that when the JavaScript is blocked, client hint preferences are not
1218// persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051219IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051220 ClientHintsLifetimeNotPersistedJavaScriptBlocked) {
1221 ContentSettingsForOneType host_settings;
1222
1223 // Start a navigation. This navigation makes it possible to block JavaScript
1224 // later.
1225 ui_test_utils::NavigateToURL(browser(),
1226 without_accept_ch_without_lifetime_url());
1227
Tarun Bansal9a7051f2018-07-10 18:30:051228 const GURL gurl =
1229 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
1230 : accept_ch_with_lifetime_url();
1231
Tarun Bansala61f0f62017-10-24 23:53:051232 // Block the JavaScript: Client hint preferences should not be persisted.
1233 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051234 ->SetContentSettingDefaultScope(gurl, GURL(),
Tarun Bansala61f0f62017-10-24 23:53:051235 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
1236 std::string(), CONTENT_SETTING_BLOCK);
1237 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1238 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1239 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1240 &host_settings);
1241 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:581242 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051243
1244 // Allow the JavaScript: Client hint preferences should be persisted.
1245 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051246 ->SetContentSettingDefaultScope(gurl, GURL(),
Tarun Bansala61f0f62017-10-24 23:53:051247 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
1248 std::string(), CONTENT_SETTING_ALLOW);
1249 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1250 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1251 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1252 &host_settings);
1253 EXPECT_EQ(1u, host_settings.size());
Tarun Bansal593790112018-03-20 04:53:341254
1255 // Clear settings.
1256 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1257 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:051258}
1259
1260// Ensure that when the JavaScript is blocked, persisted client hints are not
1261// attached to the request headers.
Tarun Bansal9a7051f2018-07-10 18:30:051262IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051263 ClientHintsLifetimeNotAttachedJavaScriptBlocked) {
Tarun Bansal9a7051f2018-07-10 18:30:051264 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1265 : accept_ch_with_lifetime_url();
1266
Tarun Bansala61f0f62017-10-24 23:53:051267 base::HistogramTester histogram_tester;
1268 ContentSettingsForOneType host_settings;
1269
1270 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1271 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1272 &host_settings);
1273 EXPECT_EQ(0u, host_settings.size());
1274
1275 // Fetching accept_ch_with_lifetime_url() should persist the request for
1276 // client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051277 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansala61f0f62017-10-24 23:53:051278 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1279 content::FetchHistogramsFromChildProcesses();
1280 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1281
Mike West14c11102019-02-04 16:16:471282 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 7, 1);
Tarun Bansala61f0f62017-10-24 23:53:051283 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
1284 // 3600 seconds.
1285 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1286 3600 * 1000, 1);
1287 base::RunLoop().RunUntilIdle();
1288
1289 // Clients hints preferences for one origin should be persisted.
1290 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1291 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1292 &host_settings);
1293 EXPECT_EQ(1u, host_settings.size());
1294
1295 // Block the Javascript: Client hints should not be attached.
1296 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1297 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
1298 GURL(), CONTENT_SETTINGS_TYPE_JAVASCRIPT,
1299 std::string(), CONTENT_SETTING_BLOCK);
1300 ui_test_utils::NavigateToURL(browser(),
1301 without_accept_ch_without_lifetime_url());
1302 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581303 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051304
1305 // Allow the Javascript: Client hints should now be attached.
1306 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1307 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
1308 GURL(), CONTENT_SETTINGS_TYPE_JAVASCRIPT,
1309 std::string(), CONTENT_SETTING_ALLOW);
1310
Tarun Bansal229647bd002018-02-27 17:33:361311 SetClientHintExpectationsOnMainFrame(true);
1312 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051313 ui_test_utils::NavigateToURL(browser(),
1314 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361315
Mike West14c11102019-02-04 16:16:471316 // seven client hints are attached to the image request, and seven to the main
Tarun Bansal79df868e2018-03-20 23:01:361317 // frame request.
Mike West14c11102019-02-04 16:16:471318 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051319
1320 // Clear settings.
1321 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1322 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
1323}
1324
Tarun Bansal229647bd002018-02-27 17:33:361325// Ensure that when the JavaScript is blocked, client hints requested using
Tarun Bansal3f343d7c2018-03-02 18:48:001326// Accept-CH are not attached to the request headers for subresources.
Tarun Bansal9a7051f2018-07-10 18:30:051327IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal229647bd002018-02-27 17:33:361328 ClientHintsNoLifetimeScriptNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051329 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1330 : accept_ch_with_lifetime_url();
1331
Tarun Bansal1965b042017-09-07 04:59:191332 base::HistogramTester histogram_tester;
1333 ContentSettingsForOneType host_settings;
1334
1335 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1336 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1337 &host_settings);
1338 EXPECT_EQ(0u, host_settings.size());
1339
Tarun Bansal3f343d7c2018-03-02 18:48:001340 // Block the Javascript: Client hints should not be attached.
1341 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361342 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1343 ->SetContentSettingDefaultScope(
1344 accept_ch_without_lifetime_img_localhost(), GURL(),
1345 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
1346 CONTENT_SETTING_BLOCK);
1347 ui_test_utils::NavigateToURL(browser(),
1348 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:001349 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361350 EXPECT_EQ(1u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001351 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal1965b042017-09-07 04:59:191352
Tarun Bansal3f343d7c2018-03-02 18:48:001353 // Allow the Javascript: Client hints should now be attached.
Tarun Bansal229647bd002018-02-27 17:33:361354 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1355 ->SetContentSettingDefaultScope(
1356 accept_ch_without_lifetime_img_localhost(), GURL(),
1357 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
1358 CONTENT_SETTING_ALLOW);
Tarun Bansal1965b042017-09-07 04:59:191359
Tarun Bansal229647bd002018-02-27 17:33:361360 SetClientHintExpectationsOnSubresources(true);
1361 ui_test_utils::NavigateToURL(browser(),
1362 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:001363
Mike West14c11102019-02-04 16:16:471364 EXPECT_EQ(7u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361365 EXPECT_EQ(2u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001366 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581367 VerifyContentSettingsNotNotified();
Tarun Bansal1965b042017-09-07 04:59:191368
Tarun Bansal229647bd002018-02-27 17:33:361369 // Clear settings.
1370 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1371 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansal1965b042017-09-07 04:59:191372
Tarun Bansal229647bd002018-02-27 17:33:361373 // Block the Javascript again: Client hints should not be attached.
Tarun Bansal3f343d7c2018-03-02 18:48:001374 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361375 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1376 ->SetContentSettingDefaultScope(
1377 accept_ch_without_lifetime_img_localhost(), GURL(),
1378 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
1379 CONTENT_SETTING_BLOCK);
1380 ui_test_utils::NavigateToURL(browser(),
1381 accept_ch_without_lifetime_img_localhost());
Mike West14c11102019-02-04 16:16:471382 EXPECT_EQ(7u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361383 EXPECT_EQ(3u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001384 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341385
1386 // Clear settings.
1387 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1388 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansal229647bd002018-02-27 17:33:361389}
1390
Tarun Bansala0c1fc32018-10-03 16:14:521391// Ensure that when the cookies is blocked, client hints are attached to the
Tarun Bansal3f343d7c2018-03-02 18:48:001392// request headers.
Tarun Bansal9a7051f2018-07-10 18:30:051393IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521394 ClientHintsLifetimeCookiesNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051395 const GURL gurl = GetParam()
1396 ? http_equiv_accept_ch_without_lifetime_img_localhost()
1397 : accept_ch_without_lifetime_img_localhost();
1398
Tarun Bansal229647bd002018-02-27 17:33:361399 base::HistogramTester histogram_tester;
1400 ContentSettingsForOneType host_settings;
1401 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1402 CookieSettingsFactory::GetForProfile(browser()->profile());
1403
Tarun Bansal1965b042017-09-07 04:59:191404 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1405 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1406 &host_settings);
1407 EXPECT_EQ(0u, host_settings.size());
1408
Tarun Bansal229647bd002018-02-27 17:33:361409 // Block cookies.
1410 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051411 ->SetContentSettingDefaultScope(gurl, GURL(),
1412 CONTENT_SETTINGS_TYPE_COOKIES,
1413 std::string(), CONTENT_SETTING_BLOCK);
Tarun Bansal229647bd002018-02-27 17:33:361414 base::RunLoop().RunUntilIdle();
1415
Tarun Bansal229647bd002018-02-27 17:33:361416 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal9a7051f2018-07-10 18:30:051417 ui_test_utils::NavigateToURL(browser(), gurl);
Mike West14c11102019-02-04 16:16:471418 EXPECT_EQ(7u, count_client_hints_headers_seen());
Tarun Bansala0c1fc32018-10-03 16:14:521419 EXPECT_EQ(1u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001420 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341421
1422 // Clear settings.
1423 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1424 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
Tarun Bansal1965b042017-09-07 04:59:191425}
1426
Tarun Bansal3ce0ca42018-06-25 22:52:221427// Verify that client hints are sent in the incognito profiles, and server
1428// client hint opt-ins are honored within the incognito profile.
Tarun Bansal9a7051f2018-07-10 18:30:051429IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal3ce0ca42018-06-25 22:52:221430 ClientHintsLifetimeFollowedByNoClientHintIncognito) {
Tarun Bansal9a7051f2018-07-10 18:30:051431 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1432 : accept_ch_with_lifetime_url();
1433
Tarun Bansal3ce0ca42018-06-25 22:52:221434 base::HistogramTester histogram_tester;
1435 Browser* incognito = CreateIncognitoBrowser();
1436 ContentSettingsForOneType host_settings;
1437
1438 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
1439 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1440 &host_settings);
1441 EXPECT_EQ(0u, host_settings.size());
1442
Tarun Bansal9a7051f2018-07-10 18:30:051443 // Fetching |gurl| should persist the request for client hints.
1444 ui_test_utils::NavigateToURL(incognito, gurl);
Tarun Bansal3ce0ca42018-06-25 22:52:221445
1446 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1447
1448 content::FetchHistogramsFromChildProcesses();
1449 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1450
Mike West14c11102019-02-04 16:16:471451 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 7, 1);
Tarun Bansal3ce0ca42018-06-25 22:52:221452 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1453 // seconds.
1454 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1455 3600 * 1000, 1);
1456 base::RunLoop().RunUntilIdle();
1457
1458 // Clients hints preferences for one origin should be persisted.
1459 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
1460 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
1461 &host_settings);
1462 EXPECT_EQ(1u, host_settings.size());
1463
1464 SetClientHintExpectationsOnMainFrame(true);
1465 SetClientHintExpectationsOnSubresources(true);
1466 ui_test_utils::NavigateToURL(incognito,
1467 without_accept_ch_without_lifetime_url());
1468
Mike West14c11102019-02-04 16:16:471469 // Seven client hints are attached to the image request, and seven to the main
Tarun Bansal3ce0ca42018-06-25 22:52:221470 // frame request.
Mike West14c11102019-02-04 16:16:471471 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:221472
1473 // Navigate using regular profile. Client hints should not be send.
1474 SetClientHintExpectationsOnMainFrame(false);
1475 SetClientHintExpectationsOnSubresources(false);
1476 ui_test_utils::NavigateToURL(browser(),
1477 without_accept_ch_without_lifetime_url());
1478
Mike West14c11102019-02-04 16:16:471479 // Seven client hints are attached to the image request, and seven to the main
Tarun Bansal3ce0ca42018-06-25 22:52:221480 // frame request.
Mike West14c11102019-02-04 16:16:471481 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:221482}
Tarun Bansalbef6d652018-10-02 18:41:011483
1484class ClientHintsWebHoldbackBrowserTest : public ClientHintsBrowserTest {
1485 public:
1486 ClientHintsWebHoldbackBrowserTest() : ClientHintsBrowserTest() {
1487 ConfigureHoldbackExperiment();
1488 }
1489
1490 net::EffectiveConnectionType web_effective_connection_type_override() const {
1491 return web_effective_connection_type_override_;
1492 }
1493
1494 private:
1495 void ConfigureHoldbackExperiment() {
1496 base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
1497 const std::string kTrialName = "TrialFoo";
1498 const std::string kGroupName = "GroupFoo"; // Value not used
1499
1500 scoped_refptr<base::FieldTrial> trial =
1501 base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
1502
1503 std::map<std::string, std::string> params;
1504
1505 params["web_effective_connection_type_override"] =
1506 net::GetNameForEffectiveConnectionType(
1507 web_effective_connection_type_override_);
1508 ASSERT_TRUE(
1509 base::FieldTrialParamAssociator::GetInstance()
1510 ->AssociateFieldTrialParams(kTrialName, kGroupName, params));
1511
1512 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
1513 feature_list->RegisterFieldTrialOverride(
1514 features::kNetworkQualityEstimatorWebHoldback.name,
1515 base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
1516 scoped_feature_list_override_.InitWithFeatureList(std::move(feature_list));
1517 }
1518
1519 const net::EffectiveConnectionType web_effective_connection_type_override_ =
1520 net::EFFECTIVE_CONNECTION_TYPE_3G;
1521
1522 base::test::ScopedFeatureList scoped_feature_list_override_;
1523};
1524
1525// Make sure that when NetInfo holdback experiment is enabled, the NetInfo APIs
1526// and client hints return the overridden values. Verify that the client hints
1527// are overridden on both main frame and subresource requests.
1528IN_PROC_BROWSER_TEST_F(ClientHintsWebHoldbackBrowserTest,
1529 EffectiveConnectionTypeChangeNotified) {
1530 SetExpectedEffectiveConnectionType(web_effective_connection_type_override());
1531
1532 SetClientHintExpectationsOnMainFrame(false);
1533 SetClientHintExpectationsOnSubresources(true);
1534
1535 base::RunLoop().RunUntilIdle();
1536
1537 EXPECT_TRUE(embedded_test_server()->Start());
1538 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1539 EXPECT_EQ(0u, count_client_hints_headers_seen());
1540 EXPECT_EQ(0u, third_party_request_count_seen());
1541 EXPECT_EQ(0u, third_party_client_hints_count_seen());
1542
1543 SetClientHintExpectationsOnMainFrame(true);
1544 SetClientHintExpectationsOnSubresources(true);
1545 ui_test_utils::NavigateToURL(
1546 browser(), accept_ch_without_lifetime_with_subresource_url());
1547 base::RunLoop().RunUntilIdle();
1548 content::FetchHistogramsFromChildProcesses();
1549 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1550
Mike West14c11102019-02-04 16:16:471551 EXPECT_EQ(14u, count_client_hints_headers_seen());
Tarun Bansalbef6d652018-10-02 18:41:011552 EXPECT_EQ(0u, third_party_request_count_seen());
1553 EXPECT_EQ(0u, third_party_client_hints_count_seen());
1554}