blob: bda60b5ed4dae471307fd573de70afc7cd7ca18e [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"
Blink Reformata30d4232018-04-07 15:31:0636#include "third_party/blink/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.
Tarun Bansal509a8dd2018-04-10 17:19:16349 int rtt_value = 0.0;
Tarun Bansal7f3fe8c2018-04-06 22:37:47350 EXPECT_TRUE(
Tarun Bansal509a8dd2018-04-10 17:19:16351 base::StringToInt(request.headers.find("rtt")->second, &rtt_value));
352 EXPECT_LE(0, rtt_value);
353 // Verify that RTT value is a multiple of 50 milliseconds.
354 EXPECT_EQ(0, rtt_value % 50);
355 EXPECT_GE(3000, rtt_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47356
Tarun Bansal509a8dd2018-04-10 17:19:16357 double mbps_value = 0.0;
358 EXPECT_TRUE(base::StringToDouble(request.headers.find("downlink")->second,
359 &mbps_value));
360 EXPECT_LE(0, mbps_value);
361 // Verify that the mbps value is a multiple of 0.050 mbps.
362 // Allow for small amount of noise due to double to integer conversions.
363 EXPECT_NEAR(0, (static_cast<int>(mbps_value * 1000)) % 50, 1);
364 EXPECT_GE(10.0, mbps_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47365
366 EXPECT_FALSE(request.headers.find("ect")->second.empty());
367 }
368
Tarun Bansal3b330b02017-11-09 19:03:14369 net::EmbeddedTestServer http_server_;
Tarun Bansal0b8b7afd2017-08-25 03:52:16370 net::EmbeddedTestServer https_server_;
Tarun Bansal3b330b02017-11-09 19:03:14371 GURL accept_ch_with_lifetime_http_local_url_;
Tarun Bansal1965b042017-09-07 04:59:19372 GURL accept_ch_with_lifetime_url_;
373 GURL accept_ch_without_lifetime_url_;
374 GURL without_accept_ch_without_lifetime_url_;
Tarun Bansal3b330b02017-11-09 19:03:14375 GURL without_accept_ch_without_lifetime_local_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58376 GURL accept_ch_without_lifetime_with_iframe_url_;
377 GURL without_accept_ch_without_lifetime_img_foo_com_;
378 GURL without_accept_ch_without_lifetime_img_localhost_;
Tarun Bansal229647bd002018-02-27 17:33:36379 GURL accept_ch_without_lifetime_img_localhost_;
Tarun Bansal1965b042017-09-07 04:59:19380
Tarun Bansal44ad96882018-03-28 17:47:42381 double main_frame_dpr_observed_ = -1;
382 double main_frame_viewport_width_observed_ = -1;
383 double main_frame_device_memory_observed_ = -1;
384
Tarun Bansal229647bd002018-02-27 17:33:36385 // Expect client hints on all the main frame request.
386 bool expect_client_hints_on_main_frame_;
387 // Expect client hints on all the subresource requests.
388 bool expect_client_hints_on_subresources_;
389
Tarun Bansal1965b042017-09-07 04:59:19390 size_t count_client_hints_headers_seen_;
Tarun Bansala61f0f62017-10-24 23:53:05391
Jay Civelli1ff872d2018-03-09 21:52:16392 std::unique_ptr<ThirdPartyURLLoaderInterceptor> request_interceptor_;
Tarun Bansal229647bd002018-02-27 17:33:36393
Tarun Bansala61f0f62017-10-24 23:53:05394 DISALLOW_COPY_AND_ASSIGN(ClientHintsBrowserTest);
Tarun Bansal0b8b7afd2017-08-25 03:52:16395};
396
397// Loads a webpage that requests persisting of client hints. Verifies that
398// the browser receives the mojo notification from the renderer and persists the
399// client hints to the disk.
400IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttps) {
401 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:19402 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16403
404 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
405
406 content::FetchHistogramsFromChildProcesses();
407 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
408
Tarun Bansal7f3fe8c2018-04-06 22:37:47409 // client_hints_url() sets six client hints.
410 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal1965b042017-09-07 04:59:19411 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
412 // seconds.
Tarun Bansal0b8b7afd2017-08-25 03:52:16413 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
414 3600 * 1000, 1);
415}
416
Tarun Bansaladd5e1812018-02-09 19:07:58417// Test that client hints are attached to subresources only if they belong
418// to the same host as document host.
419IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
420 ClientHintsHttpsSubresourceDifferentOrigin) {
421 base::HistogramTester histogram_tester;
422
423 // Add client hints for the embedded test server.
424 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
425 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
426
427 // Verify that the client hints settings for localhost have been saved.
428 ContentSettingsForOneType client_hints_settings;
429 HostContentSettingsMap* host_content_settings_map =
430 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
431 host_content_settings_map->GetSettingsForOneType(
432 CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
433 &client_hints_settings);
434 ASSERT_EQ(1U, client_hints_settings.size());
435
436 // Copy the client hints setting for localhost to foo.com.
437 host_content_settings_map->SetWebsiteSettingDefaultScope(
438 GURL("https://foo.com/"), GURL(), CONTENT_SETTINGS_TYPE_CLIENT_HINTS,
439 std::string(),
Jeremy Romanec48d7a2018-03-01 17:35:09440 std::make_unique<base::Value>(
Oksana Zhuravlovab14dc882018-04-12 17:34:57441 client_hints_settings.at(0).setting_value.Clone()));
Tarun Bansaladd5e1812018-02-09 19:07:58442
443 // Verify that client hints for the two hosts has been saved.
444 host_content_settings_map =
445 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
446 host_content_settings_map->GetSettingsForOneType(
447 CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
448 &client_hints_settings);
449 ASSERT_EQ(2U, client_hints_settings.size());
450
451 // Navigating to without_accept_ch_without_lifetime_img_localhost() should
452 // attach client hints to the image subresouce contained in that page since
453 // the image is located on the same server as the document origin.
Tarun Bansal229647bd002018-02-27 17:33:36454 SetClientHintExpectationsOnMainFrame(true);
455 SetClientHintExpectationsOnSubresources(true);
Tarun Bansaladd5e1812018-02-09 19:07:58456 ui_test_utils::NavigateToURL(
457 browser(), without_accept_ch_without_lifetime_img_localhost());
458 base::RunLoop().RunUntilIdle();
459 content::FetchHistogramsFromChildProcesses();
460 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
461
Tarun Bansal7f3fe8c2018-04-06 22:37:47462 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36463 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47464 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58465
466 // Navigating to without_accept_ch_without_lifetime_img_foo_com() should not
467 // attach client hints to the image subresouce contained in that page since
468 // the image is located on a different server as the document origin.
Tarun Bansaladd5e1812018-02-09 19:07:58469 ui_test_utils::NavigateToURL(
470 browser(), without_accept_ch_without_lifetime_img_foo_com());
471 base::RunLoop().RunUntilIdle();
472 content::FetchHistogramsFromChildProcesses();
473 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
474
Tarun Bansalb30b7532018-03-14 21:50:38475 // The device-memory and dprheader is attached to the main frame request.
Tarun Bansal5c28afb2018-03-17 02:55:20476#if defined(OS_ANDROID)
Tarun Bansalb30b7532018-03-14 21:50:38477 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20478#else
Tarun Bansal7f3fe8c2018-04-06 22:37:47479 EXPECT_EQ(18u, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20480#endif
Tarun Bansal229647bd002018-02-27 17:33:36481 // Requests to third party servers should not have client hints attached.
482 EXPECT_EQ(1u, third_party_request_count_seen());
483 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58484}
485
486// Loads a HTTPS webpage that does not request persisting of client hints.
487// An iframe loaded by the webpage requests persistence of client hints.
488// Verify that the request from the iframe is not honored, and client hints
489// preference is not persisted.
490IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
491 DisregardPersistenceRequestIframe) {
492 base::HistogramTester histogram_tester;
493 ContentSettingsForOneType host_settings;
494
495 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
496 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
497 &host_settings);
498 EXPECT_EQ(0u, host_settings.size());
499
500 ui_test_utils::NavigateToURL(browser(),
501 accept_ch_without_lifetime_with_iframe_url());
502
503 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
504
505 content::FetchHistogramsFromChildProcesses();
506 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
507
508 // accept_ch_without_lifetime_with_iframe_url() loads
509 // accept_ch_with_lifetime() in an iframe. The request to persist client
510 // hints from accept_ch_with_lifetime() should be disregarded.
511 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
512 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
513}
514
Tarun Bansal3b330b02017-11-09 19:03:14515// Loads a HTTP local webpage (which qualifies as a secure context) that
516// requests persisting of client hints. Verifies that the browser receives the
517// mojo notification from the renderer and persists the client hints to the
518// disk.
519IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
520 ClientHintsLifetimeFollowedByNoClientHintHttpLocal) {
521 base::HistogramTester histogram_tester;
522 ContentSettingsForOneType host_settings;
523
524 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
525 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
526 &host_settings);
527 EXPECT_EQ(0u, host_settings.size());
528
529 ui_test_utils::NavigateToURL(browser(),
530 accept_ch_with_lifetime_http_local_url());
531
532 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
533
534 content::FetchHistogramsFromChildProcesses();
535 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
536
Tarun Bansal7f3fe8c2018-04-06 22:37:47537 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal3b330b02017-11-09 19:03:14538 // accept_ch_with_lifetime_http_local_url() sets client hints persist duration
539 // to 3600 seconds.
540 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
541 3600 * 1000, 1);
542
543 base::RunLoop().RunUntilIdle();
544
545 // Clients hints preferences for one origin should be persisted.
546 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
547 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
548 &host_settings);
549 EXPECT_EQ(1u, host_settings.size());
550
Tarun Bansal229647bd002018-02-27 17:33:36551 SetClientHintExpectationsOnMainFrame(true);
552 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal3b330b02017-11-09 19:03:14553 ui_test_utils::NavigateToURL(browser(),
554 without_accept_ch_without_lifetime_local_url());
555
Tarun Bansal7f3fe8c2018-04-06 22:37:47556 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36557 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47558 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansal3b330b02017-11-09 19:03:14559}
560
Tarun Bansal0b8b7afd2017-08-25 03:52:16561// Loads a webpage that does not request persisting of client hints.
562IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {
563 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:19564 ui_test_utils::NavigateToURL(browser(),
565 without_accept_ch_without_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16566
567 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
568
569 content::FetchHistogramsFromChildProcesses();
570 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
571
572 // no_client_hints_url() does not sets the client hints.
573 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
574 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
575}
576
Tarun Bansal1965b042017-09-07 04:59:19577IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
578 ClientHintsLifetimeFollowedByNoClientHint) {
579 base::HistogramTester histogram_tester;
580 ContentSettingsForOneType host_settings;
581
582 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
583 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
584 &host_settings);
585 EXPECT_EQ(0u, host_settings.size());
586
587 // Fetching accept_ch_with_lifetime_url() should persist the request for
588 // client hints.
589 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
590
591 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
592
593 content::FetchHistogramsFromChildProcesses();
594 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
595
Tarun Bansal7f3fe8c2018-04-06 22:37:47596 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal1965b042017-09-07 04:59:19597 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
598 // seconds.
599 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
600 3600 * 1000, 1);
601 base::RunLoop().RunUntilIdle();
602
603 // Clients hints preferences for one origin should be persisted.
604 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
605 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
606 &host_settings);
607 EXPECT_EQ(1u, host_settings.size());
608
Tarun Bansal229647bd002018-02-27 17:33:36609 SetClientHintExpectationsOnMainFrame(true);
610 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal1965b042017-09-07 04:59:19611 ui_test_utils::NavigateToURL(browser(),
612 without_accept_ch_without_lifetime_url());
Tarun Bansal6bf54302017-10-02 07:39:14613
Tarun Bansal7f3fe8c2018-04-06 22:37:47614 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36615 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47616 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansal1965b042017-09-07 04:59:19617}
618
Tarun Bansala61f0f62017-10-24 23:53:05619// Ensure that when cookies are blocked, client hint preferences are not
620// persisted.
621IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
622 ClientHintsLifetimeNotPersistedCookiesBlocked) {
623 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
624 CookieSettingsFactory::GetForProfile(browser()->profile());
625 base::HistogramTester histogram_tester;
626 ContentSettingsForOneType host_settings;
627
628 // Block cookies.
629 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
630 ->SetContentSettingDefaultScope(accept_ch_without_lifetime_url(), GURL(),
631 CONTENT_SETTINGS_TYPE_COOKIES,
632 std::string(), CONTENT_SETTING_BLOCK);
633
634 // Fetching accept_ch_with_lifetime_url() should not persist the request for
635 // client hints since cookies are blocked.
636 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
637 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
638 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
639 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
640 &host_settings);
641 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:58642 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05643
644 // Allow cookies.
645 cookie_settings_->SetCookieSetting(accept_ch_without_lifetime_url(),
646 CONTENT_SETTING_ALLOW);
647 // Fetching accept_ch_with_lifetime_url() should persist the request for
648 // client hints since cookies are allowed.
649 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
650 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
651 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
652 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
653 &host_settings);
654 EXPECT_EQ(1u, host_settings.size());
655}
656
657IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
658 ClientHintsLifetimeNotAttachedCookiesBlocked) {
659 base::HistogramTester histogram_tester;
660 ContentSettingsForOneType host_settings;
661
662 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
663 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
664 &host_settings);
665 EXPECT_EQ(0u, host_settings.size());
666
667 // Fetching accept_ch_with_lifetime_url() should persist the request for
668 // client hints.
669 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
670 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
671 content::FetchHistogramsFromChildProcesses();
672 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
673
Tarun Bansal7f3fe8c2018-04-06 22:37:47674 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansala61f0f62017-10-24 23:53:05675 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
676 // 3600 seconds.
677 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
678 3600 * 1000, 1);
679 base::RunLoop().RunUntilIdle();
680
681 // Clients hints preferences for one origin should be persisted.
682 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
683 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
684 &host_settings);
685 EXPECT_EQ(1u, host_settings.size());
686
687 // Block the cookies: Client hints should not be attached.
688 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
689 ->SetContentSettingDefaultScope(accept_ch_without_lifetime_url(), GURL(),
690 CONTENT_SETTINGS_TYPE_COOKIES,
691 std::string(), CONTENT_SETTING_BLOCK);
692
693 ui_test_utils::NavigateToURL(browser(),
694 without_accept_ch_without_lifetime_url());
695 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58696 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05697
698 // Allow the cookies: Client hints should now be attached.
699 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
700 ->SetContentSettingDefaultScope(accept_ch_without_lifetime_url(), GURL(),
701 CONTENT_SETTINGS_TYPE_COOKIES,
702 std::string(), CONTENT_SETTING_ALLOW);
703
Tarun Bansal229647bd002018-02-27 17:33:36704 SetClientHintExpectationsOnMainFrame(true);
705 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:05706 ui_test_utils::NavigateToURL(browser(),
707 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:36708
Tarun Bansal7f3fe8c2018-04-06 22:37:47709 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36710 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47711 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:05712
713 // Clear settings.
714 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
715 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
716}
717
718// Ensure that when the JavaScript is blocked, client hint preferences are not
719// persisted.
720IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
721 ClientHintsLifetimeNotPersistedJavaScriptBlocked) {
722 ContentSettingsForOneType host_settings;
723
724 // Start a navigation. This navigation makes it possible to block JavaScript
725 // later.
726 ui_test_utils::NavigateToURL(browser(),
727 without_accept_ch_without_lifetime_url());
728
729 // Block the JavaScript: Client hint preferences should not be persisted.
730 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
731 ->SetContentSettingDefaultScope(accept_ch_with_lifetime_url(), GURL(),
732 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
733 std::string(), CONTENT_SETTING_BLOCK);
734 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
735 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
736 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
737 &host_settings);
738 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:58739 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05740
741 // Allow the JavaScript: Client hint preferences should be persisted.
742 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
743 ->SetContentSettingDefaultScope(accept_ch_with_lifetime_url(), GURL(),
744 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
745 std::string(), CONTENT_SETTING_ALLOW);
746 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
747 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
748 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
749 &host_settings);
750 EXPECT_EQ(1u, host_settings.size());
Tarun Bansal593790112018-03-20 04:53:34751
752 // Clear settings.
753 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
754 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:05755}
756
757// Ensure that when the JavaScript is blocked, persisted client hints are not
758// attached to the request headers.
759IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
760 ClientHintsLifetimeNotAttachedJavaScriptBlocked) {
761 base::HistogramTester histogram_tester;
762 ContentSettingsForOneType host_settings;
763
764 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
765 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
766 &host_settings);
767 EXPECT_EQ(0u, host_settings.size());
768
769 // Fetching accept_ch_with_lifetime_url() should persist the request for
770 // client hints.
771 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
772 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
773 content::FetchHistogramsFromChildProcesses();
774 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
775
Tarun Bansal7f3fe8c2018-04-06 22:37:47776 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansala61f0f62017-10-24 23:53:05777 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
778 // 3600 seconds.
779 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
780 3600 * 1000, 1);
781 base::RunLoop().RunUntilIdle();
782
783 // Clients hints preferences for one origin should be persisted.
784 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
785 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
786 &host_settings);
787 EXPECT_EQ(1u, host_settings.size());
788
789 // Block the Javascript: Client hints should not be attached.
790 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
791 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
792 GURL(), CONTENT_SETTINGS_TYPE_JAVASCRIPT,
793 std::string(), CONTENT_SETTING_BLOCK);
794 ui_test_utils::NavigateToURL(browser(),
795 without_accept_ch_without_lifetime_url());
796 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58797 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:05798
799 // Allow the Javascript: Client hints should now be attached.
800 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
801 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
802 GURL(), CONTENT_SETTINGS_TYPE_JAVASCRIPT,
803 std::string(), CONTENT_SETTING_ALLOW);
804
Tarun Bansal229647bd002018-02-27 17:33:36805 SetClientHintExpectationsOnMainFrame(true);
806 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:05807 ui_test_utils::NavigateToURL(browser(),
808 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:36809
Tarun Bansal7f3fe8c2018-04-06 22:37:47810 // Six client hints are attached to the image request, and six to the main
Tarun Bansal79df868e2018-03-20 23:01:36811 // frame request.
Tarun Bansal7f3fe8c2018-04-06 22:37:47812 EXPECT_EQ(12u, count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:05813
814 // Clear settings.
815 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
816 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
817}
818
Tarun Bansal229647bd002018-02-27 17:33:36819// Ensure that when the JavaScript is blocked, client hints requested using
Tarun Bansal3f343d7c2018-03-02 18:48:00820// Accept-CH are not attached to the request headers for subresources.
Tarun Bansal1965b042017-09-07 04:59:19821IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal229647bd002018-02-27 17:33:36822 ClientHintsNoLifetimeScriptNotAllowed) {
Tarun Bansal1965b042017-09-07 04:59:19823 base::HistogramTester histogram_tester;
824 ContentSettingsForOneType host_settings;
825
826 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
827 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
828 &host_settings);
829 EXPECT_EQ(0u, host_settings.size());
830
Tarun Bansal3f343d7c2018-03-02 18:48:00831 // Block the Javascript: Client hints should not be attached.
832 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:36833 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
834 ->SetContentSettingDefaultScope(
835 accept_ch_without_lifetime_img_localhost(), GURL(),
836 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
837 CONTENT_SETTING_BLOCK);
838 ui_test_utils::NavigateToURL(browser(),
839 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:00840 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36841 EXPECT_EQ(1u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00842 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal1965b042017-09-07 04:59:19843
Tarun Bansal3f343d7c2018-03-02 18:48:00844 // Allow the Javascript: Client hints should now be attached.
Tarun Bansal229647bd002018-02-27 17:33:36845 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
846 ->SetContentSettingDefaultScope(
847 accept_ch_without_lifetime_img_localhost(), GURL(),
848 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
849 CONTENT_SETTING_ALLOW);
Tarun Bansal1965b042017-09-07 04:59:19850
Tarun Bansal229647bd002018-02-27 17:33:36851 SetClientHintExpectationsOnSubresources(true);
852 ui_test_utils::NavigateToURL(browser(),
853 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:00854
Tarun Bansal7f3fe8c2018-04-06 22:37:47855 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36856 EXPECT_EQ(2u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00857 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58858 VerifyContentSettingsNotNotified();
Tarun Bansal1965b042017-09-07 04:59:19859
Tarun Bansal229647bd002018-02-27 17:33:36860 // Clear settings.
861 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
862 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansal1965b042017-09-07 04:59:19863
Tarun Bansal229647bd002018-02-27 17:33:36864 // Block the Javascript again: Client hints should not be attached.
Tarun Bansal3f343d7c2018-03-02 18:48:00865 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:36866 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
867 ->SetContentSettingDefaultScope(
868 accept_ch_without_lifetime_img_localhost(), GURL(),
869 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(),
870 CONTENT_SETTING_BLOCK);
871 ui_test_utils::NavigateToURL(browser(),
872 accept_ch_without_lifetime_img_localhost());
Tarun Bansal7f3fe8c2018-04-06 22:37:47873 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36874 EXPECT_EQ(3u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00875 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:34876
877 // Clear settings.
878 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
879 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
Tarun Bansal229647bd002018-02-27 17:33:36880}
881
Tarun Bansal3f343d7c2018-03-02 18:48:00882// Ensure that when the cookies is blocked, client hints are not attached to the
883// request headers.
Tarun Bansal229647bd002018-02-27 17:33:36884IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
885 ClientHintsNoLifetimeCookiesNotAllowed) {
886 base::HistogramTester histogram_tester;
887 ContentSettingsForOneType host_settings;
888 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
889 CookieSettingsFactory::GetForProfile(browser()->profile());
890
Tarun Bansal1965b042017-09-07 04:59:19891 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
892 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
893 &host_settings);
894 EXPECT_EQ(0u, host_settings.size());
895
Tarun Bansal229647bd002018-02-27 17:33:36896 // Block cookies.
897 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
898 ->SetContentSettingDefaultScope(
899 accept_ch_without_lifetime_img_localhost(), GURL(),
900 CONTENT_SETTINGS_TYPE_COOKIES, std::string(), CONTENT_SETTING_BLOCK);
901 base::RunLoop().RunUntilIdle();
902
Tarun Bansal1965b042017-09-07 04:59:19903 ui_test_utils::NavigateToURL(browser(),
Tarun Bansal229647bd002018-02-27 17:33:36904 accept_ch_without_lifetime_img_localhost());
905 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00906 // Client hints are not attached to third party subresources even though
907 // cookies are allowed only for the first party origin.
908 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:58909 VerifyContentSettingsNotNotified();
Tarun Bansal229647bd002018-02-27 17:33:36910
911 // Allow cookies.
912 cookie_settings_->SetCookieSetting(accept_ch_without_lifetime_img_localhost(),
913 CONTENT_SETTING_ALLOW);
914 base::RunLoop().RunUntilIdle();
915
916 SetClientHintExpectationsOnSubresources(true);
917 ui_test_utils::NavigateToURL(browser(),
918 accept_ch_without_lifetime_img_localhost());
Tarun Bansal7f3fe8c2018-04-06 22:37:47919 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36920 EXPECT_EQ(2u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00921 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal229647bd002018-02-27 17:33:36922
923 // Block cookies again.
924 SetClientHintExpectationsOnSubresources(false);
925 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
926 ->SetContentSettingDefaultScope(
927 accept_ch_without_lifetime_img_localhost(), GURL(),
928 CONTENT_SETTINGS_TYPE_COOKIES, std::string(), CONTENT_SETTING_BLOCK);
929 base::RunLoop().RunUntilIdle();
930
931 ui_test_utils::NavigateToURL(browser(),
932 accept_ch_without_lifetime_img_localhost());
Tarun Bansal7f3fe8c2018-04-06 22:37:47933 EXPECT_EQ(6u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:36934 EXPECT_EQ(3u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:00935 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:34936
937 // Clear settings.
938 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
939 ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
Tarun Bansal1965b042017-09-07 04:59:19940}
941
Tarun Bansal0b8b7afd2017-08-25 03:52:16942// Check the client hints for the given URL in an incognito window.
943// Start incognito browser twice to ensure that client hints prefs are
944// not carried over.
945IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttpsIncognito) {
946 for (size_t i = 0; i < 2; ++i) {
947 base::HistogramTester histogram_tester;
948
949 Browser* incognito = CreateIncognitoBrowser();
Tarun Bansal1965b042017-09-07 04:59:19950 ui_test_utils::NavigateToURL(incognito, accept_ch_with_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16951
952 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
953
954 content::FetchHistogramsFromChildProcesses();
955 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
956
Tarun Bansal7f3fe8c2018-04-06 22:37:47957 // accept_ch_with_lifetime_url() sets six client hints.
958 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 6, 1);
Tarun Bansal0b8b7afd2017-08-25 03:52:16959
960 // At least one renderer must have been created. All the renderers created
961 // must have read 0 client hints.
962 EXPECT_LE(1u,
963 histogram_tester.GetAllSamples("ClientHints.CountRulesReceived")
964 .size());
965 for (const auto& bucket :
966 histogram_tester.GetAllSamples("ClientHints.CountRulesReceived")) {
967 EXPECT_EQ(0, bucket.min);
968 }
969 // |url| sets client hints persist duration to 3600 seconds.
970 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
971 3600 * 1000, 1);
972
973 CloseBrowserSynchronously(incognito);
974 }
975}