blob: 99a881e69d0de26ed606124f841a0d3e886f2c83 [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 Bansal229647bd002018-02-27 17:33:365#include "base/bind.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:166#include "base/command_line.h"
Gabriel Charetteb71eec892017-09-14 22:52:567#include "base/run_loop.h"
Tarun Bansal6bf54302017-10-02 07:39:148#include "base/stl_util.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:169#include "base/test/histogram_tester.h"
Tarun Bansal5c28afb2018-03-17 02:55:2010#include "build/build_config.h"
Tarun Bansala61f0f62017-10-24 23:53:0511#include "chrome/browser/content_settings/cookie_settings_factory.h"
Tarun Bansal1965b042017-09-07 04:59:1912#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
Tarun Bansalc211d8b2018-03-19 19:21:5813#include "chrome/browser/content_settings/tab_specific_content_settings.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1614#include "chrome/browser/metrics/subprocess_metrics_provider.h"
15#include "chrome/browser/net/url_request_mock_util.h"
16#include "chrome/browser/profiles/profile.h"
Tarun Bansal1965b042017-09-07 04:59:1917#include "chrome/browser/ui/browser.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1618#include "chrome/test/base/in_process_browser_test.h"
19#include "chrome/test/base/ui_test_utils.h"
Tarun Bansala61f0f62017-10-24 23:53:0520#include "components/content_settings/core/browser/cookie_settings.h"
Tarun Bansal1965b042017-09-07 04:59:1921#include "components/content_settings/core/browser/host_content_settings_map.h"
Tarun Bansala61f0f62017-10-24 23:53:0522#include "components/content_settings/core/common/pref_names.h"
23#include "components/prefs/pref_service.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1624#include "content/public/browser/browser_thread.h"
25#include "content/public/common/content_switches.h"
26#include "content/public/test/browser_test_utils.h"
27#include "content/public/test/test_utils.h"
Tarun Bansal229647bd002018-02-27 17:33:3628#include "content/public/test/url_loader_interceptor.h"
29#include "net/dns/mock_host_resolver.h"
30#include "net/http/http_request_headers.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4731#include "net/nqe/effective_connection_type.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1632#include "net/test/embedded_test_server/embedded_test_server.h"
Tarun Bansal1965b042017-09-07 04:59:1933#include "net/test/embedded_test_server/http_request.h"
Tarun Bansal229647bd002018-02-27 17:33:3634#include "net/test/embedded_test_server/http_response.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4735#include "services/network/public/cpp/network_switches.h"
Tarun Bansalf9cf9892018-04-06 04:38:0136#include "third_party/WebKit/public/common/client_hints/client_hints.h"
Tarun Bansal229647bd002018-02-27 17:33:3637
38namespace {
39
40// An interceptor that records count of fetches and client hint headers for
41// requests to https://foo.com/non-existing-image.jpg.
Jay Civelli1ff872d2018-03-09 21:52:1642class ThirdPartyURLLoaderInterceptor {
Tarun Bansal229647bd002018-02-27 17:33:3643 public:
Jay Civelli1ff872d2018-03-09 21:52:1644 explicit ThirdPartyURLLoaderInterceptor(const GURL intercepted_url)
45 : intercepted_url_(intercepted_url),
46 interceptor_(base::BindRepeating(
47 &ThirdPartyURLLoaderInterceptor::InterceptURLRequest,
48 base::Unretained(this))) {}
Tarun Bansal229647bd002018-02-27 17:33:3649
Jay Civelli1ff872d2018-03-09 21:52:1650 ~ThirdPartyURLLoaderInterceptor() = default;
Tarun Bansal229647bd002018-02-27 17:33:3651
52 size_t request_count_seen() const { return request_count_seen_; }
53
54 size_t client_hints_count_seen() const { return client_hints_count_seen_; }
55
56 private:
Jay Civelli1ff872d2018-03-09 21:52:1657 bool InterceptURLRequest(
58 content::URLLoaderInterceptor::RequestParams* params) {
59 if (params->url_request.url != intercepted_url_)
60 return false;
Tarun Bansal229647bd002018-02-27 17:33:3661
Jay Civelli1ff872d2018-03-09 21:52:1662 request_count_seen_++;
Tarun Bansalf9cf9892018-04-06 04:38:0163 for (size_t i = 0; i < blink::kClientHintsHeaderMappingCount; ++i) {
64 if (params->url_request.headers.HasHeader(
65 blink::kClientHintsHeaderMapping[i])) {
66 client_hints_count_seen_++;
67 }
Tarun Bansal5c28afb2018-03-17 02:55:2068 }
Jay Civelli1ff872d2018-03-09 21:52:1669 return false;
70 }
Tarun Bansal229647bd002018-02-27 17:33:3671
Jay Civelli1ff872d2018-03-09 21:52:1672 GURL intercepted_url_;
73
74 size_t request_count_seen_ = 0u;
75
76 size_t client_hints_count_seen_ = 0u;
77
78 content::URLLoaderInterceptor interceptor_;
79
80 DISALLOW_COPY_AND_ASSIGN(ThirdPartyURLLoaderInterceptor);
Tarun Bansal229647bd002018-02-27 17:33:3681};
82
83} // namespace
Tarun Bansal0b8b7afd2017-08-25 03:52:1684
85class ClientHintsBrowserTest : public InProcessBrowserTest {
86 public:
87 ClientHintsBrowserTest()
Tarun Bansal3b330b02017-11-09 19:03:1488 : http_server_(net::EmbeddedTestServer::TYPE_HTTP),
89 https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal229647bd002018-02-27 17:33:3690 expect_client_hints_on_main_frame_(false),
91 expect_client_hints_on_subresources_(false),
92 count_client_hints_headers_seen_(0),
93 request_interceptor_(nullptr) {
Tarun Bansal3b330b02017-11-09 19:03:1494 http_server_.ServeFilesFromSourceDirectory("chrome/test/data/client_hints");
Tarun Bansal0b8b7afd2017-08-25 03:52:1695 https_server_.ServeFilesFromSourceDirectory(
96 "chrome/test/data/client_hints");
Tarun Bansal1965b042017-09-07 04:59:1997
Tarun Bansal3b330b02017-11-09 19:03:1498 http_server_.RegisterRequestMonitor(
99 base::Bind(&ClientHintsBrowserTest::MonitorResourceRequest,
100 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19101 https_server_.RegisterRequestMonitor(
102 base::Bind(&ClientHintsBrowserTest::MonitorResourceRequest,
103 base::Unretained(this)));
104
Tarun Bansal3b330b02017-11-09 19:03:14105 EXPECT_TRUE(http_server_.Start());
Tarun Bansal0b8b7afd2017-08-25 03:52:16106 EXPECT_TRUE(https_server_.Start());
107
Tarun Bansal3b330b02017-11-09 19:03:14108 accept_ch_with_lifetime_http_local_url_ =
109 http_server_.GetURL("/accept_ch_with_lifetime.html");
110 EXPECT_TRUE(accept_ch_with_lifetime_http_local_url_.SchemeIsHTTPOrHTTPS());
111 EXPECT_FALSE(
112 accept_ch_with_lifetime_http_local_url_.SchemeIsCryptographic());
113
Tarun Bansal1965b042017-09-07 04:59:19114 accept_ch_with_lifetime_url_ =
115 https_server_.GetURL("/accept_ch_with_lifetime.html");
116 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
117 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal0b8b7afd2017-08-25 03:52:16118
Tarun Bansal1965b042017-09-07 04:59:19119 accept_ch_without_lifetime_url_ =
120 https_server_.GetURL("/accept_ch_without_lifetime.html");
121 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
122 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
123
124 without_accept_ch_without_lifetime_url_ =
125 https_server_.GetURL("/without_accept_ch_without_lifetime.html");
126 EXPECT_TRUE(without_accept_ch_without_lifetime_url_.SchemeIsHTTPOrHTTPS());
127 EXPECT_TRUE(
128 without_accept_ch_without_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal3b330b02017-11-09 19:03:14129
130 without_accept_ch_without_lifetime_local_url_ =
131 http_server_.GetURL("/without_accept_ch_without_lifetime.html");
132 EXPECT_TRUE(
133 without_accept_ch_without_lifetime_local_url_.SchemeIsHTTPOrHTTPS());
134 EXPECT_FALSE(
135 without_accept_ch_without_lifetime_local_url_.SchemeIsCryptographic());
Tarun Bansaladd5e1812018-02-09 19:07:58136
137 without_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
138 "/without_accept_ch_without_lifetime_img_localhost.html");
139 without_accept_ch_without_lifetime_img_foo_com_ = https_server_.GetURL(
140 "/without_accept_ch_without_lifetime_img_foo_com.html");
141 accept_ch_without_lifetime_with_iframe_url_ =
142 https_server_.GetURL("/accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal229647bd002018-02-27 17:33:36143 accept_ch_without_lifetime_img_localhost_ =
144 https_server_.GetURL("/accept_ch_without_lifetime_img_localhost.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16145 }
146
147 ~ClientHintsBrowserTest() override {}
148
149 void SetUpOnMainThread() override {
Tarun Bansal229647bd002018-02-27 17:33:36150 host_resolver()->AddRule("*", "127.0.0.1");
Tarun Bansal0b8b7afd2017-08-25 03:52:16151 content::BrowserThread::PostTask(
152 content::BrowserThread::IO, FROM_HERE,
153 base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
Tarun Bansal229647bd002018-02-27 17:33:36154
Jay Civelli1ff872d2018-03-09 21:52:16155 request_interceptor_ = std::make_unique<ThirdPartyURLLoaderInterceptor>(
156 GURL("https://foo.com/non-existing-image.jpg"));
Tarun Bansal229647bd002018-02-27 17:33:36157 base::RunLoop().RunUntilIdle();
Tarun Bansal0b8b7afd2017-08-25 03:52:16158 }
159
Jay Civelli1ff872d2018-03-09 21:52:16160 void TearDownOnMainThread() override { request_interceptor_.reset(); }
161
Tarun Bansal0b8b7afd2017-08-25 03:52:16162 void SetUpCommandLine(base::CommandLine* cmd) override {
163 cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
Tarun Bansal7f3fe8c2018-04-06 22:37:47164 cmd->AppendSwitchASCII(network::switches::kForceEffectiveConnectionType,
165 net::kEffectiveConnectionType2G);
Tarun Bansal0b8b7afd2017-08-25 03:52:16166 }
167
Tarun Bansal229647bd002018-02-27 17:33:36168 void SetClientHintExpectationsOnMainFrame(bool expect_client_hints) {
169 expect_client_hints_on_main_frame_ = expect_client_hints;
Tarun Bansal1965b042017-09-07 04:59:19170 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16171
Tarun Bansal229647bd002018-02-27 17:33:36172 void SetClientHintExpectationsOnSubresources(bool expect_client_hints) {
173 expect_client_hints_on_subresources_ = expect_client_hints;
Tarun Bansala61f0f62017-10-24 23:53:05174 }
175
Tarun Bansalc211d8b2018-03-19 19:21:58176 // Verify that the user is not notified that cookies or JavaScript were
177 // blocked on the webpage due to the checks done by client hints.
178 void VerifyContentSettingsNotNotified() const {
179 content::WebContents* web_contents =
180 browser()->tab_strip_model()->GetActiveWebContents();
181 EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents)
182 ->IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
183
184 EXPECT_FALSE(TabSpecificContentSettings::FromWebContents(web_contents)
185 ->IsContentBlocked(CONTENT_SETTINGS_TYPE_JAVASCRIPT));
186 }
187
Tarun Bansal3b330b02017-11-09 19:03:14188 const GURL& accept_ch_with_lifetime_http_local_url() const {
189 return accept_ch_with_lifetime_http_local_url_;
190 }
191
Tarun Bansal1965b042017-09-07 04:59:19192 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
193 // headers.
194 const GURL& accept_ch_with_lifetime_url() const {
195 return accept_ch_with_lifetime_url_;
196 }
197
198 // A URL whose response headers include only Accept-CH header.
199 const GURL& accept_ch_without_lifetime_url() const {
200 return accept_ch_without_lifetime_url_;
201 }
202
203 // A URL whose response headers do not include either Accept-CH or
204 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
205 const GURL& without_accept_ch_without_lifetime_url() const {
206 return without_accept_ch_without_lifetime_url_;
207 }
208
Tarun Bansal3b330b02017-11-09 19:03:14209 // A URL whose response headers do not include either Accept-CH or
210 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
211 const GURL& without_accept_ch_without_lifetime_local_url() const {
212 return without_accept_ch_without_lifetime_local_url_;
213 }
214
Tarun Bansaladd5e1812018-02-09 19:07:58215 // A URL whose response headers do not include either Accept-CH or
216 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
217 // from localhost.
218 const GURL& without_accept_ch_without_lifetime_img_localhost() const {
219 return without_accept_ch_without_lifetime_img_localhost_;
220 }
221
222 // A URL whose response headers do not include either Accept-CH or
223 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
224 // from foo.com.
225 const GURL& without_accept_ch_without_lifetime_img_foo_com() const {
226 return without_accept_ch_without_lifetime_img_foo_com_;
227 }
228
229 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
230 // headers. The response loads accept_ch_with_lifetime_url() in an iframe.
231 const GURL& accept_ch_without_lifetime_with_iframe_url() const {
232 return accept_ch_without_lifetime_with_iframe_url_;
233 }
234
Tarun Bansal229647bd002018-02-27 17:33:36235 // A URL whose response headers includes only Accept-CH header. Navigating to
236 // this URL also fetches two images: One from the localhost, and one from
237 // foo.com.
238 const GURL& accept_ch_without_lifetime_img_localhost() const {
239 return accept_ch_without_lifetime_img_localhost_;
240 }
241
Tarun Bansal1965b042017-09-07 04:59:19242 size_t count_client_hints_headers_seen() const {
243 return count_client_hints_headers_seen_;
244 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16245
Tarun Bansal229647bd002018-02-27 17:33:36246 size_t third_party_request_count_seen() const {
247 return request_interceptor_->request_count_seen();
248 }
249
250 size_t third_party_client_hints_count_seen() const {
251 return request_interceptor_->client_hints_count_seen();
252 }
253
Tarun Bansal0b8b7afd2017-08-25 03:52:16254 private:
Tarun Bansal1965b042017-09-07 04:59:19255 // Called by |https_server_|.
256 void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
Tarun Bansal6bf54302017-10-02 07:39:14257 bool is_main_frame_navigation =
258 request.GetURL().spec().find(".html") != std::string::npos;
259
Tarun Bansal229647bd002018-02-27 17:33:36260 if (is_main_frame_navigation) {
Tarun Bansalf9cf9892018-04-06 04:38:01261 VerifyClientHintsReceived(expect_client_hints_on_main_frame_, request);
Tarun Bansal5c28afb2018-03-17 02:55:20262 if (expect_client_hints_on_main_frame_) {
263 double value = 0.0;
264 EXPECT_TRUE(base::StringToDouble(
265 request.headers.find("device-memory")->second, &value));
266 EXPECT_LT(0.0, value);
Tarun Bansal44ad96882018-03-28 17:47:42267 main_frame_device_memory_observed_ = value;
Tarun Bansal5c28afb2018-03-17 02:55:20268
269 EXPECT_TRUE(
270 base::StringToDouble(request.headers.find("dpr")->second, &value));
271 EXPECT_LT(0.0, value);
Tarun Bansal44ad96882018-03-28 17:47:42272 main_frame_dpr_observed_ = value;
273
Tarun Bansal5c28afb2018-03-17 02:55:20274 EXPECT_TRUE(base::StringToDouble(
275 request.headers.find("viewport-width")->second, &value));
Tarun Bansal79df868e2018-03-20 23:01:36276#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20277 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36278#else
279 EXPECT_EQ(980, value);
Tarun Bansal5c28afb2018-03-17 02:55:20280#endif
Tarun Bansal44ad96882018-03-28 17:47:42281 main_frame_viewport_width_observed_ = value;
Tarun Bansal7f3fe8c2018-04-06 22:37:47282 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20283 }
Tarun Bansala61f0f62017-10-24 23:53:05284 }
Tarun Bansal6bf54302017-10-02 07:39:14285
Tarun Bansal229647bd002018-02-27 17:33:36286 if (!is_main_frame_navigation) {
Tarun Bansalf9cf9892018-04-06 04:38:01287 VerifyClientHintsReceived(expect_client_hints_on_subresources_, request);
Tarun Bansal5c28afb2018-03-17 02:55:20288
289 if (expect_client_hints_on_subresources_) {
290 double value = 0.0;
291 EXPECT_TRUE(base::StringToDouble(
292 request.headers.find("device-memory")->second, &value));
293 EXPECT_LT(0.0, value);
Tarun Bansal44ad96882018-03-28 17:47:42294 if (main_frame_device_memory_observed_ > 0) {
295 EXPECT_EQ(main_frame_device_memory_observed_, value);
296 }
Tarun Bansal5c28afb2018-03-17 02:55:20297
298 EXPECT_TRUE(
299 base::StringToDouble(request.headers.find("dpr")->second, &value));
300 EXPECT_LT(0.0, value);
Tarun Bansal44ad96882018-03-28 17:47:42301 if (main_frame_dpr_observed_ > 0) {
302 EXPECT_EQ(main_frame_dpr_observed_, value);
303 }
Tarun Bansal5c28afb2018-03-17 02:55:20304
305 EXPECT_TRUE(base::StringToDouble(
306 request.headers.find("viewport-width")->second, &value));
Tarun Bansal79df868e2018-03-20 23:01:36307#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20308 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36309#else
310 EXPECT_EQ(980, value);
311#endif
Tarun Bansal44ad96882018-03-28 17:47:42312#if defined(OS_ANDROID)
313 // TODO(tbansal): https://crbug.com/825892: Viewport width on main
314 // frame requests may be incorrect when the Chrome window is not
315 // maximized.
316 if (main_frame_viewport_width_observed_ > 0) {
317 EXPECT_EQ(main_frame_viewport_width_observed_, value);
318 }
319#endif
Tarun Bansal7f3fe8c2018-04-06 22:37:47320 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20321 }
Tarun Bansala61f0f62017-10-24 23:53:05322 }
Tarun Bansal6bf54302017-10-02 07:39:14323
Tarun Bansalf9cf9892018-04-06 04:38:01324 for (size_t i = 0; i < blink::kClientHintsHeaderMappingCount; ++i) {
325 if (base::ContainsKey(request.headers,
326 blink::kClientHintsHeaderMapping[i])) {
327 count_client_hints_headers_seen_++;
328 }
329 }
330 }
Tarun Bansal1965b042017-09-07 04:59:19331
Tarun Bansalf9cf9892018-04-06 04:38:01332 void VerifyClientHintsReceived(bool expect_client_hints,
333 const net::test_server::HttpRequest& request) {
334 for (size_t i = 0; i < blink::kClientHintsHeaderMappingCount; ++i) {
335 // Resource width client hint is only attached on image subresources.
336 if (std::string(blink::kClientHintsHeaderMapping[i]) == "width") {
337 continue;
338 }
339 EXPECT_EQ(expect_client_hints,
340 base::ContainsKey(request.headers,
341 blink::kClientHintsHeaderMapping[i]));
342 }
Tarun Bansal1965b042017-09-07 04:59:19343 }
344
Tarun Bansal7f3fe8c2018-04-06 22:37:47345 void VerifyNetworkQualityClientHints(
346 const net::test_server::HttpRequest& request) const {
347 // Effective connection type is forced to 2G using command line in these
348 // tests.
349 double value = 0.0;
350 EXPECT_TRUE(
351 base::StringToDouble(request.headers.find("rtt")->second, &value));
352 EXPECT_LE(0, value);
353
354 EXPECT_TRUE(
355 base::StringToDouble(request.headers.find("downlink")->second, &value));
356 EXPECT_LE(0, value);
357
358 EXPECT_FALSE(request.headers.find("ect")->second.empty());
359 }
360
Tarun Bansal3b330b02017-11-09 19:03:14361 net::EmbeddedTestServer http_server_;
Tarun Bansal0b8b7afd2017-08-25 03:52:16362 net::EmbeddedTestServer https_server_;
Tarun Bansal3b330b02017-11-09 19:03:14363 GURL accept_ch_with_lifetime_http_local_url_;
Tarun Bansal1965b042017-09-07 04:59:19364 GURL accept_ch_with_lifetime_url_;
365 GURL accept_ch_without_lifetime_url_;
366 GURL without_accept_ch_without_lifetime_url_;
Tarun Bansal3b330b02017-11-09 19:03:14367 GURL without_accept_ch_without_lifetime_local_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58368 GURL accept_ch_without_lifetime_with_iframe_url_;
369 GURL without_accept_ch_without_lifetime_img_foo_com_;
370 GURL without_accept_ch_without_lifetime_img_localhost_;
Tarun Bansal229647bd002018-02-27 17:33:36371 GURL accept_ch_without_lifetime_img_localhost_;
Tarun Bansal1965b042017-09-07 04:59:19372
Tarun Bansal44ad96882018-03-28 17:47:42373 double main_frame_dpr_observed_ = -1;
374 double main_frame_viewport_width_observed_ = -1;
375 double main_frame_device_memory_observed_ = -1;
376
Tarun Bansal229647bd002018-02-27 17:33:36377 // Expect client hints on all the main frame request.
378 bool expect_client_hints_on_main_frame_;
379 // Expect client hints on all the subresource requests.
380 bool expect_client_hints_on_subresources_;
381
Tarun Bansal1965b042017-09-07 04:59:19382 size_t count_client_hints_headers_seen_;
Tarun Bansala61f0f62017-10-24 23:53:05383
Jay Civelli1ff872d2018-03-09 21:52:16384 std::unique_ptr<ThirdPartyURLLoaderInterceptor> request_interceptor_;
Tarun Bansal229647bd002018-02-27 17:33:36385
Tarun Bansala61f0f62017-10-24 23:53:05386 DISALLOW_COPY_AND_ASSIGN(ClientHintsBrowserTest);
Tarun Bansal0b8b7afd2017-08-25 03:52:16387};
388
389// Loads a webpage that requests persisting of client hints. Verifies that
390// the browser receives the mojo notification from the renderer and persists the
391// client hints to the disk.
392IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttps) {
393 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:19394 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16395
396 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
397
398 content::FetchHistogramsFromChildProcesses();
399 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
400
Tarun Bansal7f3fe8c2018-04-06 22:37:47401 // client_hints_url() sets six client hints.
402 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal1965b042017-09-07 04:59:19403 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
404 // seconds.
Tarun Bansal0b8b7afd2017-08-25 03:52:16405 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
406 3600 * 1000, 1);
407}
408
Tarun Bansaladd5e1812018-02-09 19:07:58409// Test that client hints are attached to subresources only if they belong
410// to the same host as document host.
411IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
412 ClientHintsHttpsSubresourceDifferentOrigin) {
413 base::HistogramTester histogram_tester;
414
415 // Add client hints for the embedded test server.
416 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
417 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
418
419 // Verify that the client hints settings for localhost have been saved.
420 ContentSettingsForOneType client_hints_settings;
421 HostContentSettingsMap* host_content_settings_map =
422 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
423 host_content_settings_map->GetSettingsForOneType(
424 CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
425 &client_hints_settings);
426 ASSERT_EQ(1U, client_hints_settings.size());
427
428 // Copy the client hints setting for localhost to foo.com.
429 host_content_settings_map->SetWebsiteSettingDefaultScope(
430 GURL("https://foo.com/"), GURL(), CONTENT_SETTINGS_TYPE_CLIENT_HINTS,
431 std::string(),
Jeremy Romanec48d7a2018-03-01 17:35:09432 std::make_unique<base::Value>(
Tarun Bansaladd5e1812018-02-09 19:07:58433 client_hints_settings.at(0).setting_value->Clone()));
434
435 // Verify that client hints for the two hosts has been saved.
436 host_content_settings_map =
437 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
438 host_content_settings_map->GetSettingsForOneType(
439 CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
440 &client_hints_settings);
441 ASSERT_EQ(2U, client_hints_settings.size());
442
443 // Navigating to without_accept_ch_without_lifetime_img_localhost() should
444 // attach client hints to the image subresouce contained in that page since
445 // the image is located on the same server as the document origin.
Tarun Bansal229647bd002018-02-27 17:33:36446 SetClientHintExpectationsOnMainFrame(true);
447 SetClientHintExpectationsOnSubresources(true);
Tarun Bansaladd5e1812018-02-09 19:07:58448 ui_test_utils::NavigateToURL(
449 browser(), without_accept_ch_without_lifetime_img_localhost());
450 base::RunLoop().RunUntilIdle();
451 content::FetchHistogramsFromChildProcesses();
452 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
453
Tarun Bansal7f3fe8c2018-04-06 22:37:47454 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36455 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47456 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58457
458 // Navigating to without_accept_ch_without_lifetime_img_foo_com() should not
459 // attach client hints to the image subresouce contained in that page since
460 // the image is located on a different server as the document origin.
Tarun Bansaladd5e1812018-02-09 19:07:58461 ui_test_utils::NavigateToURL(
462 browser(), without_accept_ch_without_lifetime_img_foo_com());
463 base::RunLoop().RunUntilIdle();
464 content::FetchHistogramsFromChildProcesses();
465 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
466
Tarun Bansalb30b7532018-03-14 21:50:38467 // The device-memory and dprheader is attached to the main frame request.
Tarun Bansal5c28afb2018-03-17 02:55:20468#if defined(OS_ANDROID)
Tarun Bansalb30b7532018-03-14 21:50:38469 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20470#else
Tarun Bansal7f3fe8c2018-04-06 22:37:47471 EXPECT_EQ(18u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20472#endif
Tarun Bansal229647bd002018-02-27 17:33:36473 // Requests to third party servers should not have client hints attached.
474 EXPECT_EQ(1u, third_party_request_count_seen());
475 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58476}
477
478// Loads a HTTPS webpage that does not request persisting of client hints.
479// An iframe loaded by the webpage requests persistence of client hints.
480// Verify that the request from the iframe is not honored, and client hints
481// preference is not persisted.
482IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
483 DisregardPersistenceRequestIframe) {
484 base::HistogramTester histogram_tester;
485 ContentSettingsForOneType host_settings;
486
487 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
488 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
489 &host_settings);
490 EXPECT_EQ(0u, host_settings.size());
491
492 ui_test_utils::NavigateToURL(browser(),
493 accept_ch_without_lifetime_with_iframe_url());
494
495 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
496
497 content::FetchHistogramsFromChildProcesses();
498 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
499
500 // accept_ch_without_lifetime_with_iframe_url() loads
501 // accept_ch_with_lifetime() in an iframe. The request to persist client
502 // hints from accept_ch_with_lifetime() should be disregarded.
503 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
504 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
505}
506
Tarun Bansal3b330b02017-11-09 19:03:14507// Loads a HTTP local webpage (which qualifies as a secure context) that
508// requests persisting of client hints. Verifies that the browser receives the
509// mojo notification from the renderer and persists the client hints to the
510// disk.
511IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
512 ClientHintsLifetimeFollowedByNoClientHintHttpLocal) {
513 base::HistogramTester histogram_tester;
514 ContentSettingsForOneType host_settings;
515
516 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
517 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
518 &host_settings);
519 EXPECT_EQ(0u, host_settings.size());
520
521 ui_test_utils::NavigateToURL(browser(),
522 accept_ch_with_lifetime_http_local_url());
523
524 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
525
526 content::FetchHistogramsFromChildProcesses();
527 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
528
Tarun Bansal7f3fe8c2018-04-06 22:37:47529 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal3b330b02017-11-09 19:03:14530 // accept_ch_with_lifetime_http_local_url() sets client hints persist duration
531 // to 3600 seconds.
532 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
533 3600 * 1000, 1);
534
535 base::RunLoop().RunUntilIdle();
536
537 // Clients hints preferences for one origin should be persisted.
538 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
539 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
540 &host_settings);
541 EXPECT_EQ(1u, host_settings.size());
542
Tarun Bansal229647bd002018-02-27 17:33:36543 SetClientHintExpectationsOnMainFrame(true);
544 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal3b330b02017-11-09 19:03:14545 ui_test_utils::NavigateToURL(browser(),
546 without_accept_ch_without_lifetime_local_url());
547
Tarun Bansal7f3fe8c2018-04-06 22:37:47548 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36549 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47550 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansal3b330b02017-11-09 19:03:14551}
552
Tarun Bansal0b8b7afd2017-08-25 03:52:16553// Loads a webpage that does not request persisting of client hints.
554IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {
555 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:19556 ui_test_utils::NavigateToURL(browser(),
557 without_accept_ch_without_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16558
559 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
560
561 content::FetchHistogramsFromChildProcesses();
562 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
563
564 // no_client_hints_url() does not sets the client hints.
565 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
566 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
567}
568
Tarun Bansal1965b042017-09-07 04:59:19569IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
570 ClientHintsLifetimeFollowedByNoClientHint) {
571 base::HistogramTester histogram_tester;
572 ContentSettingsForOneType host_settings;
573
574 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
575 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
576 &host_settings);
577 EXPECT_EQ(0u, host_settings.size());
578
579 // Fetching accept_ch_with_lifetime_url() should persist the request for
580 // client hints.
581 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
582
583 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
584
585 content::FetchHistogramsFromChildProcesses();
586 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
587
Tarun Bansal7f3fe8c2018-04-06 22:37:47588 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal1965b042017-09-07 04:59:19589 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
590 // seconds.
591 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
592 3600 * 1000, 1);
593 base::RunLoop().RunUntilIdle();
594
595 // Clients hints preferences for one origin should be persisted.
596 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
597 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
598 &host_settings);
599 EXPECT_EQ(1u, host_settings.size());
600
Tarun Bansal229647bd002018-02-27 17:33:36601 SetClientHintExpectationsOnMainFrame(true);
602 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal1965b042017-09-07 04:59:19603 ui_test_utils::NavigateToURL(browser(),
604 without_accept_ch_without_lifetime_url());
Tarun Bansal6bf54302017-10-02 07:39:14605
Tarun Bansal7f3fe8c2018-04-06 22:37:47606 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36607 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47608 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansal1965b042017-09-07 04:59:19609}
610
Tarun Bansala61f0f62017-10-24 23:53:05611// Ensure that when cookies are blocked, client hint preferences are not
612// persisted.
613IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
614 ClientHintsLifetimeNotPersistedCookiesBlocked) {
615 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
616 CookieSettingsFactory::GetForProfile(browser()->profile());
617 base::HistogramTester histogram_tester;
618 ContentSettingsForOneType host_settings;
619
620 // Block cookies.
621 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
622 ->SetContentSettingDefaultScope(accept_ch_without_lifetime_url(), GURL(),
623 CONTENT_SETTINGS_TYPE_COOKIES,
624 std::string(), CONTENT_SETTING_BLOCK);
625
626 // Fetching accept_ch_with_lifetime_url() should not persist the request for
627 // client hints since cookies are blocked.
628 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
629 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
630 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
631 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
632 &host_settings);
633 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:58634 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05635
636 // Allow cookies.
637 cookie_settings_->SetCookieSetting(accept_ch_without_lifetime_url(),
638 CONTENT_SETTING_ALLOW);
639 // Fetching accept_ch_with_lifetime_url() should persist the request for
640 // client hints since cookies are allowed.
641 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
642 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
643 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
644 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
645 &host_settings);
646 EXPECT_EQ(1u, host_settings.size());
647}
648
649IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
650 ClientHintsLifetimeNotAttachedCookiesBlocked) {
651 base::HistogramTester histogram_tester;
652 ContentSettingsForOneType host_settings;
653
654 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
655 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
656 &host_settings);
657 EXPECT_EQ(0u, host_settings.size());
658
659 // Fetching accept_ch_with_lifetime_url() should persist the request for
660 // client hints.
661 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
662 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
663 content::FetchHistogramsFromChildProcesses();
664 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
665
Tarun Bansal7f3fe8c2018-04-06 22:37:47666 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansala61f0f62017-10-24 23:53:05667 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
668 // 3600 seconds.
669 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
670 3600 * 1000, 1);
671 base::RunLoop().RunUntilIdle();
672
673 // Clients hints preferences for one origin should be persisted.
674 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
675 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
676 &host_settings);
677 EXPECT_EQ(1u, host_settings.size());
678
679 // Block the cookies: Client hints should not be attached.
680 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
681 ->SetContentSettingDefaultScope(accept_ch_without_lifetime_url(), GURL(),
682 CONTENT_SETTINGS_TYPE_COOKIES,
683 std::string(), CONTENT_SETTING_BLOCK);
684
685 ui_test_utils::NavigateToURL(browser(),
686 without_accept_ch_without_lifetime_url());
687 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58688 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05689
690 // Allow the cookies: Client hints should now be attached.
691 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
692 ->SetContentSettingDefaultScope(accept_ch_without_lifetime_url(), GURL(),
693 CONTENT_SETTINGS_TYPE_COOKIES,
694 std::string(), CONTENT_SETTING_ALLOW);
695
Tarun Bansal229647bd002018-02-27 17:33:36696 SetClientHintExpectationsOnMainFrame(true);
697 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:05698 ui_test_utils::NavigateToURL(browser(),
699 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:36700
Tarun Bansal7f3fe8c2018-04-06 22:37:47701 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36702 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47703 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:05704
705 // Clear settings.
706 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
707 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
708}
709
710// Ensure that when the JavaScript is blocked, client hint preferences are not
711// persisted.
712IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
713 ClientHintsLifetimeNotPersistedJavaScriptBlocked) {
714 ContentSettingsForOneType host_settings;
715
716 // Start a navigation. This navigation makes it possible to block JavaScript
717 // later.
718 ui_test_utils::NavigateToURL(browser(),
719 without_accept_ch_without_lifetime_url());
720
721 // Block the JavaScript: Client hint preferences should not be persisted.
722 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
723 ->SetContentSettingDefaultScope(accept_ch_with_lifetime_url(), GURL(),
724 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
725 std::string(), CONTENT_SETTING_BLOCK);
726 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
727 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
728 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
729 &host_settings);
730 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:58731 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05732
733 // Allow the JavaScript: Client hint preferences should be persisted.
734 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
735 ->SetContentSettingDefaultScope(accept_ch_with_lifetime_url(), GURL(),
736 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
737 std::string(), CONTENT_SETTING_ALLOW);
738 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
739 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
740 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
741 &host_settings);
742 EXPECT_EQ(1u, host_settings.size());
Tarun Bansal593790112018-03-20 04:53:34743
744 // Clear settings.
745 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
746 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:05747}
748
749// Ensure that when the JavaScript is blocked, persisted client hints are not
750// attached to the request headers.
751IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
752 ClientHintsLifetimeNotAttachedJavaScriptBlocked) {
753 base::HistogramTester histogram_tester;
754 ContentSettingsForOneType host_settings;
755
756 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
757 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
758 &host_settings);
759 EXPECT_EQ(0u, host_settings.size());
760
761 // Fetching accept_ch_with_lifetime_url() should persist the request for
762 // client hints.
763 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
764 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
765 content::FetchHistogramsFromChildProcesses();
766 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
767
Tarun Bansal7f3fe8c2018-04-06 22:37:47768 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansala61f0f62017-10-24 23:53:05769 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
770 // 3600 seconds.
771 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
772 3600 * 1000, 1);
773 base::RunLoop().RunUntilIdle();
774
775 // Clients hints preferences for one origin should be persisted.
776 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
777 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
778 &host_settings);
779 EXPECT_EQ(1u, host_settings.size());
780
781 // Block the Javascript: Client hints should not be attached.
782 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
783 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
784 GURL(), CONTENT_SETTINGS_TYPE_JAVASCRIPT,
785 std::string(), CONTENT_SETTING_BLOCK);
786 ui_test_utils::NavigateToURL(browser(),
787 without_accept_ch_without_lifetime_url());
788 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58789 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05790
791 // Allow the Javascript: Client hints should now be attached.
792 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
793 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
794 GURL(), CONTENT_SETTINGS_TYPE_JAVASCRIPT,
795 std::string(), CONTENT_SETTING_ALLOW);
796
Tarun Bansal229647bd002018-02-27 17:33:36797 SetClientHintExpectationsOnMainFrame(true);
798 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:05799 ui_test_utils::NavigateToURL(browser(),
800 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:36801
Tarun Bansal7f3fe8c2018-04-06 22:37:47802 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36803 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47804 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:05805
806 // Clear settings.
807 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
808 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
809}
810
Tarun Bansal229647bd002018-02-27 17:33:36811// Ensure that when the JavaScript is blocked, client hints requested using
Tarun Bansal3f343d7c2018-03-02 18:48:00812// Accept-CH are not attached to the request headers for subresources.
Tarun Bansal1965b042017-09-07 04:59:19813IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal229647bd002018-02-27 17:33:36814 ClientHintsNoLifetimeScriptNotAllowed) {
Tarun Bansal1965b042017-09-07 04:59:19815 base::HistogramTester histogram_tester;
816 ContentSettingsForOneType host_settings;
817
818 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
819 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
820 &host_settings);
821 EXPECT_EQ(0u, host_settings.size());
822
Tarun Bansal3f343d7c2018-03-02 18:48:00823 // Block the Javascript: Client hints should not be attached.
824 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:36825 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
826 ->SetContentSettingDefaultScope(
827 accept_ch_without_lifetime_img_localhost(), GURL(),
828 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
829 CONTENT_SETTING_BLOCK);
830 ui_test_utils::NavigateToURL(browser(),
831 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:00832 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36833 EXPECT_EQ(1u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00834 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal1965b042017-09-07 04:59:19835
Tarun Bansal3f343d7c2018-03-02 18:48:00836 // Allow the Javascript: Client hints should now be attached.
Tarun Bansal229647bd002018-02-27 17:33:36837 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
838 ->SetContentSettingDefaultScope(
839 accept_ch_without_lifetime_img_localhost(), GURL(),
840 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
841 CONTENT_SETTING_ALLOW);
Tarun Bansal1965b042017-09-07 04:59:19842
Tarun Bansal229647bd002018-02-27 17:33:36843 SetClientHintExpectationsOnSubresources(true);
844 ui_test_utils::NavigateToURL(browser(),
845 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:00846
Tarun Bansal7f3fe8c2018-04-06 22:37:47847 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36848 EXPECT_EQ(2u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00849 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58850 VerifyContentSettingsNotNotified();
Tarun Bansal1965b042017-09-07 04:59:19851
Tarun Bansal229647bd002018-02-27 17:33:36852 // Clear settings.
853 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
854 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansal1965b042017-09-07 04:59:19855
Tarun Bansal229647bd002018-02-27 17:33:36856 // Block the Javascript again: Client hints should not be attached.
Tarun Bansal3f343d7c2018-03-02 18:48:00857 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:36858 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
859 ->SetContentSettingDefaultScope(
860 accept_ch_without_lifetime_img_localhost(), GURL(),
861 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
862 CONTENT_SETTING_BLOCK);
863 ui_test_utils::NavigateToURL(browser(),
864 accept_ch_without_lifetime_img_localhost());
Tarun Bansal7f3fe8c2018-04-06 22:37:47865 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36866 EXPECT_EQ(3u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00867 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:34868
869 // Clear settings.
870 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
871 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansal229647bd002018-02-27 17:33:36872}
873
Tarun Bansal3f343d7c2018-03-02 18:48:00874// Ensure that when the cookies is blocked, client hints are not attached to the
875// request headers.
Tarun Bansal229647bd002018-02-27 17:33:36876IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
877 ClientHintsNoLifetimeCookiesNotAllowed) {
878 base::HistogramTester histogram_tester;
879 ContentSettingsForOneType host_settings;
880 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
881 CookieSettingsFactory::GetForProfile(browser()->profile());
882
Tarun Bansal1965b042017-09-07 04:59:19883 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
884 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
885 &host_settings);
886 EXPECT_EQ(0u, host_settings.size());
887
Tarun Bansal229647bd002018-02-27 17:33:36888 // Block cookies.
889 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
890 ->SetContentSettingDefaultScope(
891 accept_ch_without_lifetime_img_localhost(), GURL(),
892 CONTENT_SETTINGS_TYPE_COOKIES, std::string(), CONTENT_SETTING_BLOCK);
893 base::RunLoop().RunUntilIdle();
894
Tarun Bansal1965b042017-09-07 04:59:19895 ui_test_utils::NavigateToURL(browser(),
Tarun Bansal229647bd002018-02-27 17:33:36896 accept_ch_without_lifetime_img_localhost());
897 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00898 // Client hints are not attached to third party subresources even though
899 // cookies are allowed only for the first party origin.
900 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58901 VerifyContentSettingsNotNotified();
Tarun Bansal229647bd002018-02-27 17:33:36902
903 // Allow cookies.
904 cookie_settings_->SetCookieSetting(accept_ch_without_lifetime_img_localhost(),
905 CONTENT_SETTING_ALLOW);
906 base::RunLoop().RunUntilIdle();
907
908 SetClientHintExpectationsOnSubresources(true);
909 ui_test_utils::NavigateToURL(browser(),
910 accept_ch_without_lifetime_img_localhost());
Tarun Bansal7f3fe8c2018-04-06 22:37:47911 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36912 EXPECT_EQ(2u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00913 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal229647bd002018-02-27 17:33:36914
915 // Block cookies again.
916 SetClientHintExpectationsOnSubresources(false);
917 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
918 ->SetContentSettingDefaultScope(
919 accept_ch_without_lifetime_img_localhost(), GURL(),
920 CONTENT_SETTINGS_TYPE_COOKIES, std::string(), CONTENT_SETTING_BLOCK);
921 base::RunLoop().RunUntilIdle();
922
923 ui_test_utils::NavigateToURL(browser(),
924 accept_ch_without_lifetime_img_localhost());
Tarun Bansal7f3fe8c2018-04-06 22:37:47925 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36926 EXPECT_EQ(3u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00927 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:34928
929 // Clear settings.
930 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
931 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
Tarun Bansal1965b042017-09-07 04:59:19932}
933
Tarun Bansal0b8b7afd2017-08-25 03:52:16934// Check the client hints for the given URL in an incognito window.
935// Start incognito browser twice to ensure that client hints prefs are
936// not carried over.
937IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttpsIncognito) {
938 for (size_t i = 0; i < 2; ++i) {
939 base::HistogramTester histogram_tester;
940
941 Browser* incognito = CreateIncognitoBrowser();
Tarun Bansal1965b042017-09-07 04:59:19942 ui_test_utils::NavigateToURL(incognito, accept_ch_with_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16943
944 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
945
946 content::FetchHistogramsFromChildProcesses();
947 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
948
Tarun Bansal7f3fe8c2018-04-06 22:37:47949 // accept_ch_with_lifetime_url() sets six client hints.
950 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal0b8b7afd2017-08-25 03:52:16951
952 // At least one renderer must have been created. All the renderers created
953 // must have read 0 client hints.
954 EXPECT_LE(1u,
955 histogram_tester.GetAllSamples("ClientHints.CountRulesReceived")
956 .size());
957 for (const auto& bucket :
958 histogram_tester.GetAllSamples("ClientHints.CountRulesReceived")) {
959 EXPECT_EQ(0, bucket.min);
960 }
961 // |url| sets client hints persist duration to 3600 seconds.
962 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
963 3600 * 1000, 1);
964
965 CloseBrowserSynchronously(incognito);
966 }
967}