blob: f63db1a71107d47a674a3be9f81c677e6a828316 [file] [log] [blame]
Tarun Bansal0b8b7afd2017-08-25 03:52:161// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Tarun Bansal62efba12018-05-04 22:58:355#include <cctype>
6
Mike West2fddeeb72019-02-15 11:29:487#include "base/base_switches.h"
Tarun Bansal229647bd002018-02-27 17:33:368#include "base/bind.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:169#include "base/command_line.h"
Tarun Bansalbef6d652018-10-02 18:41:0110#include "base/metrics/field_trial_param_associator.h"
Gabriel Charetteb71eec892017-09-14 22:52:5611#include "base/run_loop.h"
Tarun Bansal6bf54302017-10-02 07:39:1412#include "base/stl_util.h"
Mike Weste555be862019-02-20 16:17:3013#include "base/strings/string_util.h"
Callum May7d88ff3e2019-11-12 18:21:4614#include "base/synchronization/lock.h"
Devlin Cronin626d80c2018-06-01 01:08:3615#include "base/test/metrics/histogram_tester.h"
Tarun Bansal5c28afb2018-03-17 02:55:2016#include "build/build_config.h"
Mike Weste555be862019-02-20 16:17:3017#include "chrome/browser/chrome_content_browser_client.h"
Tarun Bansala61f0f62017-10-24 23:53:0518#include "chrome/browser/content_settings/cookie_settings_factory.h"
Tarun Bansal1965b042017-09-07 04:59:1919#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1620#include "chrome/browser/metrics/subprocess_metrics_provider.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1621#include "chrome/browser/profiles/profile.h"
Tarun Bansal1965b042017-09-07 04:59:1922#include "chrome/browser/ui/browser.h"
Maks Orlovich73f374d2020-04-02 12:46:1323#include "chrome/browser/ui/browser_commands.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1624#include "chrome/test/base/in_process_browser_test.h"
25#include "chrome/test/base/ui_test_utils.h"
Clark DuVall84a33d612020-04-17 16:01:0026#include "components/content_settings/browser/tab_specific_content_settings.h"
Tarun Bansala61f0f62017-10-24 23:53:0527#include "components/content_settings/core/browser/cookie_settings.h"
Tarun Bansal1965b042017-09-07 04:59:1928#include "components/content_settings/core/browser/host_content_settings_map.h"
Tarun Bansala61f0f62017-10-24 23:53:0529#include "components/content_settings/core/common/pref_names.h"
30#include "components/prefs/pref_service.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1631#include "content/public/browser/browser_thread.h"
Maks Orlovich73f374d2020-04-02 12:46:1332#include "content/public/browser/navigation_entry.h"
Changwan Ryu434c3a32019-07-30 23:42:5833#include "content/public/browser/render_view_host.h"
Tarun Bansalbef6d652018-10-02 18:41:0134#include "content/public/common/content_features.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1635#include "content/public/common/content_switches.h"
Changwan Ryu434c3a32019-07-30 23:42:5836#include "content/public/common/web_preferences.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1637#include "content/public/test/browser_test_utils.h"
38#include "content/public/test/test_utils.h"
Tarun Bansal229647bd002018-02-27 17:33:3639#include "content/public/test/url_loader_interceptor.h"
40#include "net/dns/mock_host_resolver.h"
41#include "net/http/http_request_headers.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4742#include "net/nqe/effective_connection_type.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1643#include "net/test/embedded_test_server/embedded_test_server.h"
Tarun Bansal1965b042017-09-07 04:59:1944#include "net/test/embedded_test_server/http_request.h"
Tarun Bansal229647bd002018-02-27 17:33:3645#include "net/test/embedded_test_server/http_response.h"
Tarun Bansal74e189d2018-05-07 19:07:3546#include "services/network/public/cpp/cors/cors.h"
Tarun Bansalceab9592018-05-01 18:57:3547#include "services/network/public/cpp/features.h"
Tarun Bansal7f3fe8c2018-04-06 22:37:4748#include "services/network/public/cpp/network_switches.h"
Blink Reformata30d4232018-04-07 15:31:0649#include "third_party/blink/public/common/client_hints/client_hints.h"
Tarun Bansal229647bd002018-02-27 17:33:3650
51namespace {
52
Yoav Weissfd1d19f2020-05-05 09:23:0353const unsigned expected_client_hints_number = 12u;
Yoav Weissd33bacb2020-03-12 06:42:2154
Tarun Bansal229647bd002018-02-27 17:33:3655// An interceptor that records count of fetches and client hint headers for
56// requests to https://foo.com/non-existing-image.jpg.
Jay Civelli1ff872d2018-03-09 21:52:1657class ThirdPartyURLLoaderInterceptor {
Tarun Bansal229647bd002018-02-27 17:33:3658 public:
Jay Civelli1ff872d2018-03-09 21:52:1659 explicit ThirdPartyURLLoaderInterceptor(const GURL intercepted_url)
60 : intercepted_url_(intercepted_url),
61 interceptor_(base::BindRepeating(
62 &ThirdPartyURLLoaderInterceptor::InterceptURLRequest,
63 base::Unretained(this))) {}
Tarun Bansal229647bd002018-02-27 17:33:3664
Jay Civelli1ff872d2018-03-09 21:52:1665 ~ThirdPartyURLLoaderInterceptor() = default;
Tarun Bansal229647bd002018-02-27 17:33:3666
67 size_t request_count_seen() const { return request_count_seen_; }
68
69 size_t client_hints_count_seen() const { return client_hints_count_seen_; }
70
71 private:
Jay Civelli1ff872d2018-03-09 21:52:1672 bool InterceptURLRequest(
73 content::URLLoaderInterceptor::RequestParams* params) {
74 if (params->url_request.url != intercepted_url_)
75 return false;
Tarun Bansal229647bd002018-02-27 17:33:3676
Jay Civelli1ff872d2018-03-09 21:52:1677 request_count_seen_++;
Mike West14c11102019-02-04 16:16:4778 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansalf9cf9892018-04-06 04:38:0179 if (params->url_request.headers.HasHeader(
80 blink::kClientHintsHeaderMapping[i])) {
81 client_hints_count_seen_++;
82 }
Tarun Bansal5c28afb2018-03-17 02:55:2083 }
Jay Civelli1ff872d2018-03-09 21:52:1684 return false;
85 }
Tarun Bansal229647bd002018-02-27 17:33:3686
Jay Civelli1ff872d2018-03-09 21:52:1687 GURL intercepted_url_;
88
89 size_t request_count_seen_ = 0u;
90
91 size_t client_hints_count_seen_ = 0u;
92
93 content::URLLoaderInterceptor interceptor_;
94
95 DISALLOW_COPY_AND_ASSIGN(ThirdPartyURLLoaderInterceptor);
Tarun Bansal229647bd002018-02-27 17:33:3696};
97
Tarun Bansal62efba12018-05-04 22:58:3598// Returns true only if |header_value| satisfies ABNF: 1*DIGIT [ "." 1*DIGIT ]
99bool IsSimilarToDoubleABNF(const std::string& header_value) {
100 if (header_value.empty())
101 return false;
102 char first_char = header_value.at(0);
103 if (!isdigit(first_char))
104 return false;
105
106 bool period_found = false;
107 bool digit_found_after_period = false;
108 for (char ch : header_value) {
109 if (isdigit(ch)) {
110 if (period_found) {
111 digit_found_after_period = true;
112 }
113 continue;
114 }
115 if (ch == '.') {
116 if (period_found)
117 return false;
118 period_found = true;
119 continue;
120 }
121 return false;
122 }
123 if (period_found)
124 return digit_found_after_period;
125 return true;
126}
127
128// Returns true only if |header_value| satisfies ABNF: 1*DIGIT
129bool IsSimilarToIntABNF(const std::string& header_value) {
130 if (header_value.empty())
131 return false;
132
133 for (char ch : header_value) {
134 if (!isdigit(ch))
135 return false;
136 }
137 return true;
138}
139
Tarun Bansal229647bd002018-02-27 17:33:36140} // namespace
Tarun Bansal0b8b7afd2017-08-25 03:52:16141
Tarun Bansal9a7051f2018-07-10 18:30:05142class ClientHintsBrowserTest : public InProcessBrowserTest,
143 public testing::WithParamInterface<bool> {
Tarun Bansal0b8b7afd2017-08-25 03:52:16144 public:
145 ClientHintsBrowserTest()
Mikel Astiz2de748d2019-11-16 10:39:36146 : http_server_(net::EmbeddedTestServer::TYPE_HTTP),
Tarun Bansal3b330b02017-11-09 19:03:14147 https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal345418632018-06-29 11:07:04148 https_cross_origin_server_(net::EmbeddedTestServer::TYPE_HTTPS),
Tarun Bansal229647bd002018-02-27 17:33:36149 expect_client_hints_on_main_frame_(false),
150 expect_client_hints_on_subresources_(false),
Mike West2fddeeb72019-02-15 11:29:48151 count_user_agent_hint_headers_seen_(0),
Maks Orlovich5dcc99c2020-02-13 19:07:46152 count_ua_mobile_client_hints_headers_seen_(0),
Tarun Bansal229647bd002018-02-27 17:33:36153 count_client_hints_headers_seen_(0),
154 request_interceptor_(nullptr) {
Tarun Bansal3b330b02017-11-09 19:03:14155 http_server_.ServeFilesFromSourceDirectory("chrome/test/data/client_hints");
Tarun Bansal0b8b7afd2017-08-25 03:52:16156 https_server_.ServeFilesFromSourceDirectory(
157 "chrome/test/data/client_hints");
Tarun Bansal345418632018-06-29 11:07:04158 https_cross_origin_server_.ServeFilesFromSourceDirectory(
159 "chrome/test/data/client_hints");
Tarun Bansal1965b042017-09-07 04:59:19160
Tarun Bansal3b330b02017-11-09 19:03:14161 http_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04162 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
163 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19164 https_server_.RegisterRequestMonitor(
Tarun Bansal345418632018-06-29 11:07:04165 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
166 base::Unretained(this)));
167 https_cross_origin_server_.RegisterRequestMonitor(
168 base::BindRepeating(&ClientHintsBrowserTest::MonitorResourceRequest,
169 base::Unretained(this)));
Tarun Bansal293a7b6c2018-12-05 17:41:12170 https_cross_origin_server_.RegisterRequestHandler(
171 base::BindRepeating(&ClientHintsBrowserTest::RequestHandlerToRedirect,
172 base::Unretained(this)));
Tarun Bansal345418632018-06-29 11:07:04173 https_server_.RegisterRequestHandler(base::BindRepeating(
174 &ClientHintsBrowserTest::RequestHandlerToFetchCrossOriginIframe,
175 base::Unretained(this)));
Tarun Bansal1965b042017-09-07 04:59:19176
Tarun Bansal3b330b02017-11-09 19:03:14177 EXPECT_TRUE(http_server_.Start());
Tarun Bansal0b8b7afd2017-08-25 03:52:16178 EXPECT_TRUE(https_server_.Start());
Tarun Bansal345418632018-06-29 11:07:04179 EXPECT_TRUE(https_cross_origin_server_.Start());
180
181 EXPECT_NE(https_server_.base_url(), https_cross_origin_server_.base_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16182
Tarun Bansal3b330b02017-11-09 19:03:14183 accept_ch_with_lifetime_http_local_url_ =
184 http_server_.GetURL("/accept_ch_with_lifetime.html");
Tarun Bansal9a7051f2018-07-10 18:30:05185 http_equiv_accept_ch_with_lifetime_http_local_url_ =
186 http_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal3b330b02017-11-09 19:03:14187 EXPECT_TRUE(accept_ch_with_lifetime_http_local_url_.SchemeIsHTTPOrHTTPS());
188 EXPECT_FALSE(
189 accept_ch_with_lifetime_http_local_url_.SchemeIsCryptographic());
190
Tarun Bansal1965b042017-09-07 04:59:19191 accept_ch_with_lifetime_url_ =
192 https_server_.GetURL("/accept_ch_with_lifetime.html");
Tarun Bansal73502f92019-04-16 21:21:19193 accept_ch_with_short_lifetime_url_ =
194 https_server_.GetURL("/accept_ch_with_short_lifetime.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16195
Tarun Bansal1965b042017-09-07 04:59:19196 accept_ch_without_lifetime_url_ =
197 https_server_.GetURL("/accept_ch_without_lifetime.html");
198 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
199 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal9a7051f2018-07-10 18:30:05200 http_equiv_accept_ch_without_lifetime_url_ =
201 https_server_.GetURL("/http_equiv_accept_ch_without_lifetime.html");
Tarun Bansal1965b042017-09-07 04:59:19202
203 without_accept_ch_without_lifetime_url_ =
204 https_server_.GetURL("/without_accept_ch_without_lifetime.html");
205 EXPECT_TRUE(without_accept_ch_without_lifetime_url_.SchemeIsHTTPOrHTTPS());
206 EXPECT_TRUE(
207 without_accept_ch_without_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal3b330b02017-11-09 19:03:14208
209 without_accept_ch_without_lifetime_local_url_ =
210 http_server_.GetURL("/without_accept_ch_without_lifetime.html");
211 EXPECT_TRUE(
212 without_accept_ch_without_lifetime_local_url_.SchemeIsHTTPOrHTTPS());
213 EXPECT_FALSE(
214 without_accept_ch_without_lifetime_local_url_.SchemeIsCryptographic());
Tarun Bansaladd5e1812018-02-09 19:07:58215
216 without_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
217 "/without_accept_ch_without_lifetime_img_localhost.html");
218 without_accept_ch_without_lifetime_img_foo_com_ = https_server_.GetURL(
219 "/without_accept_ch_without_lifetime_img_foo_com.html");
220 accept_ch_without_lifetime_with_iframe_url_ =
221 https_server_.GetURL("/accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05222 http_equiv_accept_ch_without_lifetime_with_iframe_url_ =
223 https_server_.GetURL(
224 "/http_equiv_accept_ch_without_lifetime_with_iframe.html");
Tarun Bansal62cc3542018-06-27 23:53:30225 accept_ch_without_lifetime_with_subresource_url_ = https_server_.GetURL(
226 "/accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal9a7051f2018-07-10 18:30:05227 http_equiv_accept_ch_without_lifetime_with_subresource_url_ =
228 https_server_.GetURL(
229 "/http_equiv_accept_ch_without_lifetime_with_subresource.html");
Tarun Bansal62cc3542018-06-27 23:53:30230 accept_ch_without_lifetime_with_subresource_iframe_url_ =
231 https_server_.GetURL(
232 "/accept_ch_without_lifetime_with_subresource_iframe.html");
Tarun Bansal9a7051f2018-07-10 18:30:05233 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_ =
234 https_server_.GetURL(
235 "/http_equiv_accept_ch_without_lifetime_with_subresource_iframe."
236 "html");
Tarun Bansal229647bd002018-02-27 17:33:36237 accept_ch_without_lifetime_img_localhost_ =
238 https_server_.GetURL("/accept_ch_without_lifetime_img_localhost.html");
Tarun Bansal9a7051f2018-07-10 18:30:05239 http_equiv_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
240 "/http_equiv_accept_ch_without_lifetime_img_localhost.html");
241 http_equiv_accept_ch_with_lifetime_ =
242 https_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
Tarun Bansal293a7b6c2018-12-05 17:41:12243
244 redirect_url_ = https_cross_origin_server_.GetURL("/redirect.html");
Tarun Bansal0b8b7afd2017-08-25 03:52:16245 }
246
247 ~ClientHintsBrowserTest() override {}
248
Mike West2fddeeb72019-02-15 11:29:48249 virtual std::unique_ptr<base::FeatureList> EnabledFeatures() {
250 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
251 feature_list->InitializeFromCommandLine("UserAgentClientHint", "");
252 return feature_list;
253 }
254
255 void SetUp() override {
256 scoped_feature_list_.InitWithFeatureList(EnabledFeatures());
257 InProcessBrowserTest::SetUp();
258 }
259
Tarun Bansal0b8b7afd2017-08-25 03:52:16260 void SetUpOnMainThread() override {
Tarun Bansal229647bd002018-02-27 17:33:36261 host_resolver()->AddRule("*", "127.0.0.1");
Tarun Bansal229647bd002018-02-27 17:33:36262
Jay Civelli1ff872d2018-03-09 21:52:16263 request_interceptor_ = std::make_unique<ThirdPartyURLLoaderInterceptor>(
264 GURL("https://foo.com/non-existing-image.jpg"));
Tarun Bansal229647bd002018-02-27 17:33:36265 base::RunLoop().RunUntilIdle();
Tarun Bansal0b8b7afd2017-08-25 03:52:16266 }
267
Jay Civelli1ff872d2018-03-09 21:52:16268 void TearDownOnMainThread() override { request_interceptor_.reset(); }
269
Tarun Bansal0b8b7afd2017-08-25 03:52:16270 void SetUpCommandLine(base::CommandLine* cmd) override {
Tarun Bansal7f3fe8c2018-04-06 22:37:47271 cmd->AppendSwitchASCII(network::switches::kForceEffectiveConnectionType,
272 net::kEffectiveConnectionType2G);
Mike West14c11102019-02-04 16:16:47273 cmd->AppendSwitchASCII(switches::kEnableBlinkFeatures,
274 "LangClientHintHeader");
Tarun Bansal0b8b7afd2017-08-25 03:52:16275 }
276
Tarun Bansal229647bd002018-02-27 17:33:36277 void SetClientHintExpectationsOnMainFrame(bool expect_client_hints) {
278 expect_client_hints_on_main_frame_ = expect_client_hints;
Tarun Bansal1965b042017-09-07 04:59:19279 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16280
Tarun Bansal229647bd002018-02-27 17:33:36281 void SetClientHintExpectationsOnSubresources(bool expect_client_hints) {
Callum May1d939742020-03-02 17:51:30282 base::AutoLock lock(expect_client_hints_on_subresources_lock_);
Tarun Bansal229647bd002018-02-27 17:33:36283 expect_client_hints_on_subresources_ = expect_client_hints;
Tarun Bansala61f0f62017-10-24 23:53:05284 }
285
Callum May1d939742020-03-02 17:51:30286 bool expect_client_hints_on_subresources() {
287 base::AutoLock lock(expect_client_hints_on_subresources_lock_);
288 return expect_client_hints_on_subresources_;
289 }
290
Tarun Bansalc211d8b2018-03-19 19:21:58291 // Verify that the user is not notified that cookies or JavaScript were
292 // blocked on the webpage due to the checks done by client hints.
293 void VerifyContentSettingsNotNotified() const {
294 content::WebContents* web_contents =
295 browser()->tab_strip_model()->GetActiveWebContents();
Clark DuVall84a33d612020-04-17 16:01:00296 EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents(
297 web_contents)
Darin Fisher42f5e7d2019-10-30 07:15:45298 ->IsContentBlocked(ContentSettingsType::COOKIES));
Tarun Bansalc211d8b2018-03-19 19:21:58299
Clark DuVall84a33d612020-04-17 16:01:00300 EXPECT_FALSE(content_settings::TabSpecificContentSettings::FromWebContents(
301 web_contents)
Darin Fisher42f5e7d2019-10-30 07:15:45302 ->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
Tarun Bansalc211d8b2018-03-19 19:21:58303 }
304
Tarun Bansalbef6d652018-10-02 18:41:01305 void SetExpectedEffectiveConnectionType(
306 net::EffectiveConnectionType effective_connection_type) {
307 expected_ect = effective_connection_type;
308 }
309
Changwan Ryu434c3a32019-07-30 23:42:58310 void SetJsEnabledForActiveView(bool enabled) {
311 content::RenderViewHost* view = browser()
312 ->tab_strip_model()
313 ->GetActiveWebContents()
314 ->GetRenderViewHost();
315 content::WebPreferences prefs = view->GetWebkitPreferences();
316 prefs.javascript_enabled = enabled;
317 view->UpdateWebkitPreferences(prefs);
318 }
319
Maks Orlovich7227ce0d2020-02-28 17:13:16320 void TestProfilesIndependent(Browser* browser_a, Browser* browser_b);
321
Tarun Bansal3b330b02017-11-09 19:03:14322 const GURL& accept_ch_with_lifetime_http_local_url() const {
323 return accept_ch_with_lifetime_http_local_url_;
324 }
Tarun Bansal9a7051f2018-07-10 18:30:05325 const GURL& http_equiv_accept_ch_with_lifetime_http_local_url() const {
326 return http_equiv_accept_ch_with_lifetime_http_local_url_;
327 }
Tarun Bansal3b330b02017-11-09 19:03:14328
Tarun Bansal1965b042017-09-07 04:59:19329 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
330 // headers.
331 const GURL& accept_ch_with_lifetime_url() const {
332 return accept_ch_with_lifetime_url_;
333 }
Tarun Bansal9a7051f2018-07-10 18:30:05334 const GURL& http_equiv_accept_ch_with_lifetime() {
335 return http_equiv_accept_ch_with_lifetime_;
336 }
Tarun Bansal1965b042017-09-07 04:59:19337
Tarun Bansal73502f92019-04-16 21:21:19338 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
339 // headers. The Accept-CH-Lifetime duration is set very short to 1 second.
340 const GURL& accept_ch_with_short_lifetime() const {
341 return accept_ch_with_short_lifetime_url_;
342 }
343
Tarun Bansal1965b042017-09-07 04:59:19344 // A URL whose response headers include only Accept-CH header.
345 const GURL& accept_ch_without_lifetime_url() const {
346 return accept_ch_without_lifetime_url_;
347 }
Tarun Bansal9a7051f2018-07-10 18:30:05348 const GURL& http_equiv_accept_ch_without_lifetime_url() const {
349 return http_equiv_accept_ch_without_lifetime_url_;
350 }
Tarun Bansal1965b042017-09-07 04:59:19351
352 // A URL whose response headers do not include either Accept-CH or
353 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
354 const GURL& without_accept_ch_without_lifetime_url() const {
355 return without_accept_ch_without_lifetime_url_;
356 }
357
Tarun Bansal3b330b02017-11-09 19:03:14358 // A URL whose response headers do not include either Accept-CH or
359 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
360 const GURL& without_accept_ch_without_lifetime_local_url() const {
361 return without_accept_ch_without_lifetime_local_url_;
362 }
363
Tarun Bansaladd5e1812018-02-09 19:07:58364 // A URL whose response headers do not include either Accept-CH or
365 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
366 // from localhost.
367 const GURL& without_accept_ch_without_lifetime_img_localhost() const {
368 return without_accept_ch_without_lifetime_img_localhost_;
369 }
370
371 // A URL whose response headers do not include either Accept-CH or
372 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image
373 // from foo.com.
374 const GURL& without_accept_ch_without_lifetime_img_foo_com() const {
375 return without_accept_ch_without_lifetime_img_foo_com_;
376 }
377
378 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
379 // headers. The response loads accept_ch_with_lifetime_url() in an iframe.
380 const GURL& accept_ch_without_lifetime_with_iframe_url() const {
381 return accept_ch_without_lifetime_with_iframe_url_;
382 }
Tarun Bansal9a7051f2018-07-10 18:30:05383 const GURL& http_equiv_accept_ch_without_lifetime_with_iframe_url() const {
384 return http_equiv_accept_ch_without_lifetime_with_iframe_url_;
385 }
Tarun Bansaladd5e1812018-02-09 19:07:58386
Tarun Bansal62cc3542018-06-27 23:53:30387 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
388 // headers. The response loads accept_ch_with_lifetime_url() as a subresource
389 // in the main frame.
390 const GURL& accept_ch_without_lifetime_with_subresource_url() const {
391 return accept_ch_without_lifetime_with_subresource_url_;
392 }
Tarun Bansal9a7051f2018-07-10 18:30:05393 const GURL& http_equiv_accept_ch_without_lifetime_with_subresource_url()
394 const {
395 return http_equiv_accept_ch_without_lifetime_with_subresource_url_;
396 }
Tarun Bansal62cc3542018-06-27 23:53:30397
398 // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
Tarun Bansal9a7051f2018-07-10 18:30:05399 // headers. The response loads accept_ch_with_lifetime_url() or
400 // http_equiv_accept_ch_with_lifetime_url() as a subresource in the iframe.
Tarun Bansal62cc3542018-06-27 23:53:30401 const GURL& accept_ch_without_lifetime_with_subresource_iframe_url() const {
402 return accept_ch_without_lifetime_with_subresource_iframe_url_;
403 }
Tarun Bansal9a7051f2018-07-10 18:30:05404 const GURL&
405 http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url() const {
406 return http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
407 }
Tarun Bansal62cc3542018-06-27 23:53:30408
Tarun Bansal9a7051f2018-07-10 18:30:05409 // A URL whose response includes only Accept-CH header. Navigating to
Tarun Bansal229647bd002018-02-27 17:33:36410 // this URL also fetches two images: One from the localhost, and one from
411 // foo.com.
412 const GURL& accept_ch_without_lifetime_img_localhost() const {
413 return accept_ch_without_lifetime_img_localhost_;
414 }
Tarun Bansal9a7051f2018-07-10 18:30:05415 const GURL& http_equiv_accept_ch_without_lifetime_img_localhost() const {
416 return http_equiv_accept_ch_without_lifetime_img_localhost_;
417 }
Tarun Bansal229647bd002018-02-27 17:33:36418
Tarun Bansal293a7b6c2018-12-05 17:41:12419 const GURL& redirect_url() const { return redirect_url_; }
420
Mike West2fddeeb72019-02-15 11:29:48421 size_t count_user_agent_hint_headers_seen() const {
Callum May7d88ff3e2019-11-12 18:21:46422 base::AutoLock lock(count_headers_lock_);
Mike West2fddeeb72019-02-15 11:29:48423 return count_user_agent_hint_headers_seen_;
424 }
425
Maks Orlovich5dcc99c2020-02-13 19:07:46426 size_t count_ua_mobile_client_hints_headers_seen() const {
427 base::AutoLock lock(count_headers_lock_);
428 return count_ua_mobile_client_hints_headers_seen_;
429 }
430
Tarun Bansal1965b042017-09-07 04:59:19431 size_t count_client_hints_headers_seen() const {
Callum May7d88ff3e2019-11-12 18:21:46432 base::AutoLock lock(count_headers_lock_);
Tarun Bansal1965b042017-09-07 04:59:19433 return count_client_hints_headers_seen_;
434 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16435
Tarun Bansal229647bd002018-02-27 17:33:36436 size_t third_party_request_count_seen() const {
437 return request_interceptor_->request_count_seen();
438 }
439
440 size_t third_party_client_hints_count_seen() const {
441 return request_interceptor_->client_hints_count_seen();
442 }
443
Mike Weste555be862019-02-20 16:17:30444 const std::string& main_frame_ua_observed() const {
445 return main_frame_ua_observed_;
446 }
447
Yoav Weissd33bacb2020-03-12 06:42:21448 const std::string& main_frame_ua_full_version_observed() const {
449 return main_frame_ua_full_version_observed_;
450 }
451
Maks Orlovich73f374d2020-04-02 12:46:13452 const std::string& main_frame_ua_mobile_observed() const {
453 return main_frame_ua_mobile_observed_;
454 }
455
456 const std::string& main_frame_ua_platform_observed() const {
457 return main_frame_ua_platform_observed_;
458 }
459
Tarun Bansalea0d8262018-05-21 16:11:50460 base::test::ScopedFeatureList scoped_feature_list_;
461
Tarun Bansal345418632018-06-29 11:07:04462 std::string intercept_iframe_resource_;
Tarun Bansal9a7051f2018-07-10 18:30:05463 bool intercept_to_http_equiv_iframe_ = false;
Callum May7d88ff3e2019-11-12 18:21:46464 mutable base::Lock count_headers_lock_;
Tarun Bansal345418632018-06-29 11:07:04465
Tarun Bansal0b8b7afd2017-08-25 03:52:16466 private:
Tarun Bansal345418632018-06-29 11:07:04467 // Intercepts only the main frame requests that contain
Tarun Bansal293a7b6c2018-12-05 17:41:12468 // "redirect" in the resource path. The intercepted requests
469 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
470 // server.
471 std::unique_ptr<net::test_server::HttpResponse> RequestHandlerToRedirect(
472 const net::test_server::HttpRequest& request) {
473 // Check if it's a main frame request.
474 if (request.relative_url.find(".html") == std::string::npos)
475 return nullptr;
476
477 if (request.GetURL().spec().find("redirect") == std::string::npos)
478 return nullptr;
479
480 std::unique_ptr<net::test_server::BasicHttpResponse> response;
481 response.reset(new net::test_server::BasicHttpResponse);
482 response->set_code(net::HTTP_FOUND);
483 response->AddCustomHeader("Location",
484 without_accept_ch_without_lifetime_url().spec());
485 return std::move(response);
486 }
487
488 // Intercepts only the main frame requests that contain
Tarun Bansal345418632018-06-29 11:07:04489 // |intercept_iframe_resource_| in the resource path. The intercepted requests
490 // are served an HTML file that fetches an iframe from a cross-origin HTTPS
491 // server.
492 std::unique_ptr<net::test_server::HttpResponse>
493 RequestHandlerToFetchCrossOriginIframe(
494 const net::test_server::HttpRequest& request) {
495 if (intercept_iframe_resource_.empty())
496 return nullptr;
497
498 // Check if it's a main frame request.
499 if (request.relative_url.find(".html") == std::string::npos)
500 return nullptr;
501
502 if (request.relative_url.find(intercept_iframe_resource_) ==
503 std::string::npos) {
504 return nullptr;
505 }
506
507 const std::string iframe_url =
Tarun Bansal9a7051f2018-07-10 18:30:05508 intercept_to_http_equiv_iframe_
509 ? https_cross_origin_server_
510 .GetURL("/http_equiv_accept_ch_with_lifetime.html")
511 .spec()
512 : https_cross_origin_server_.GetURL("/accept_ch_with_lifetime.html")
513 .spec();
Tarun Bansal345418632018-06-29 11:07:04514
515 std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
516 new net::test_server::BasicHttpResponse());
517 http_response->set_code(net::HTTP_OK);
518 http_response->set_content_type("text/html");
519 http_response->set_content(
520 "<html>"
521 "<link rel='icon' href='data:;base64,='><head></head>"
522 "Empty file which uses link-rel to disable favicon fetches. "
523 "<iframe src='" +
524 iframe_url + "'></iframe></html>");
525
526 return std::move(http_response);
527 }
528
Maks Orlovich73f374d2020-04-02 12:46:13529 static std::string UpdateHeaderObservation(
530 const net::test_server::HttpRequest& request,
531 const std::string& header) {
532 if (request.headers.find(header) != request.headers.end())
533 return request.headers.find(header)->second;
534 else
535 return "";
536 }
537
Tarun Bansal1965b042017-09-07 04:59:19538 // Called by |https_server_|.
539 void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
Tarun Bansal6bf54302017-10-02 07:39:14540 bool is_main_frame_navigation =
541 request.GetURL().spec().find(".html") != std::string::npos;
542
Tarun Bansal293a7b6c2018-12-05 17:41:12543 if (is_main_frame_navigation &&
544 request.GetURL().spec().find("redirect") != std::string::npos) {
545 return;
546 }
547
Tarun Bansal229647bd002018-02-27 17:33:36548 if (is_main_frame_navigation) {
Maks Orlovich73f374d2020-04-02 12:46:13549 main_frame_ua_observed_ = UpdateHeaderObservation(request, "sec-ch-ua");
550 main_frame_ua_full_version_observed_ =
551 UpdateHeaderObservation(request, "sec-ch-ua-full-version");
552 main_frame_ua_mobile_observed_ =
553 UpdateHeaderObservation(request, "sec-ch-ua-mobile");
554 main_frame_ua_platform_observed_ =
555 UpdateHeaderObservation(request, "sec-ch-ua-platform");
Yoav Weissd33bacb2020-03-12 06:42:21556
Tarun Bansalf9cf9892018-04-06 04:38:01557 VerifyClientHintsReceived(expect_client_hints_on_main_frame_, request);
Tarun Bansal5c28afb2018-03-17 02:55:20558 if (expect_client_hints_on_main_frame_) {
559 double value = 0.0;
560 EXPECT_TRUE(base::StringToDouble(
561 request.headers.find("device-memory")->second, &value));
562 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35563 EXPECT_TRUE(IsSimilarToDoubleABNF(
564 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42565 main_frame_device_memory_observed_ = value;
Tarun Bansal5c28afb2018-03-17 02:55:20566
567 EXPECT_TRUE(
568 base::StringToDouble(request.headers.find("dpr")->second, &value));
569 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35570 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42571 main_frame_dpr_observed_ = value;
572
Tarun Bansal5c28afb2018-03-17 02:55:20573 EXPECT_TRUE(base::StringToDouble(
574 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35575 EXPECT_TRUE(
576 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36577#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20578 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36579#else
580 EXPECT_EQ(980, value);
Tarun Bansal5c28afb2018-03-17 02:55:20581#endif
Tarun Bansal44ad96882018-03-28 17:47:42582 main_frame_viewport_width_observed_ = value;
Mike Weste555be862019-02-20 16:17:30583
Tarun Bansal7f3fe8c2018-04-06 22:37:47584 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20585 }
Tarun Bansala61f0f62017-10-24 23:53:05586 }
Tarun Bansal6bf54302017-10-02 07:39:14587
Tarun Bansal229647bd002018-02-27 17:33:36588 if (!is_main_frame_navigation) {
Callum May1d939742020-03-02 17:51:30589 VerifyClientHintsReceived(expect_client_hints_on_subresources(), request);
Tarun Bansal5c28afb2018-03-17 02:55:20590
Callum May1d939742020-03-02 17:51:30591 if (expect_client_hints_on_subresources()) {
Tarun Bansal5c28afb2018-03-17 02:55:20592 double value = 0.0;
593 EXPECT_TRUE(base::StringToDouble(
594 request.headers.find("device-memory")->second, &value));
595 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35596 EXPECT_TRUE(IsSimilarToDoubleABNF(
597 request.headers.find("device-memory")->second));
Tarun Bansal44ad96882018-03-28 17:47:42598 if (main_frame_device_memory_observed_ > 0) {
599 EXPECT_EQ(main_frame_device_memory_observed_, value);
600 }
Tarun Bansal5c28afb2018-03-17 02:55:20601
602 EXPECT_TRUE(
603 base::StringToDouble(request.headers.find("dpr")->second, &value));
604 EXPECT_LT(0.0, value);
Tarun Bansal62efba12018-05-04 22:58:35605 EXPECT_TRUE(IsSimilarToDoubleABNF(request.headers.find("dpr")->second));
Tarun Bansal44ad96882018-03-28 17:47:42606 if (main_frame_dpr_observed_ > 0) {
607 EXPECT_EQ(main_frame_dpr_observed_, value);
608 }
Tarun Bansal5c28afb2018-03-17 02:55:20609
610 EXPECT_TRUE(base::StringToDouble(
611 request.headers.find("viewport-width")->second, &value));
Tarun Bansal62efba12018-05-04 22:58:35612 EXPECT_TRUE(
613 IsSimilarToIntABNF(request.headers.find("viewport-width")->second));
Tarun Bansal79df868e2018-03-20 23:01:36614#if !defined(OS_ANDROID)
Tarun Bansal5c28afb2018-03-17 02:55:20615 EXPECT_LT(0.0, value);
Tarun Bansal79df868e2018-03-20 23:01:36616#else
617 EXPECT_EQ(980, value);
618#endif
Tarun Bansal44ad96882018-03-28 17:47:42619#if defined(OS_ANDROID)
620 // TODO(tbansal): https://crbug.com/825892: Viewport width on main
621 // frame requests may be incorrect when the Chrome window is not
622 // maximized.
623 if (main_frame_viewport_width_observed_ > 0) {
624 EXPECT_EQ(main_frame_viewport_width_observed_, value);
625 }
626#endif
Tarun Bansal7f3fe8c2018-04-06 22:37:47627 VerifyNetworkQualityClientHints(request);
Tarun Bansal5c28afb2018-03-17 02:55:20628 }
Tarun Bansala61f0f62017-10-24 23:53:05629 }
Tarun Bansal6bf54302017-10-02 07:39:14630
Mike West14c11102019-02-04 16:16:47631 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Jan Wilken Dörriea8cb56302019-06-06 18:59:36632 if (base::Contains(request.headers,
633 blink::kClientHintsHeaderMapping[i])) {
Callum May7d88ff3e2019-11-12 18:21:46634 base::AutoLock lock(count_headers_lock_);
Mike West2fddeeb72019-02-15 11:29:48635 // The user agent hint is special:
636 if (std::string(blink::kClientHintsHeaderMapping[i]) == "sec-ch-ua") {
637 count_user_agent_hint_headers_seen_++;
Maks Orlovich5dcc99c2020-02-13 19:07:46638 } else if (std::string(blink::kClientHintsHeaderMapping[i]) ==
639 "sec-ch-ua-mobile") {
640 count_ua_mobile_client_hints_headers_seen_++;
Mike West2fddeeb72019-02-15 11:29:48641 } else {
642 count_client_hints_headers_seen_++;
643 }
Tarun Bansalf9cf9892018-04-06 04:38:01644 }
645 }
646 }
Tarun Bansal1965b042017-09-07 04:59:19647
Tarun Bansalf9cf9892018-04-06 04:38:01648 void VerifyClientHintsReceived(bool expect_client_hints,
649 const net::test_server::HttpRequest& request) {
Mike West14c11102019-02-04 16:16:47650 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
651 SCOPED_TRACE(testing::Message()
652 << std::string(blink::kClientHintsHeaderMapping[i]));
Tarun Bansalf9cf9892018-04-06 04:38:01653 // Resource width client hint is only attached on image subresources.
654 if (std::string(blink::kClientHintsHeaderMapping[i]) == "width") {
655 continue;
656 }
Mike West2fddeeb72019-02-15 11:29:48657
Maks Orlovich5dcc99c2020-02-13 19:07:46658 // `Sec-CH-UA` and `Sec-CH-UA-Mobile` is attached on all requests.
659 if (std::string(blink::kClientHintsHeaderMapping[i]) == "sec-ch-ua" ||
660 std::string(blink::kClientHintsHeaderMapping[i]) ==
661 "sec-ch-ua-mobile") {
Mike West2fddeeb72019-02-15 11:29:48662 continue;
663 }
664
Jan Wilken Dörriea8cb56302019-06-06 18:59:36665 EXPECT_EQ(
666 expect_client_hints,
667 base::Contains(request.headers, blink::kClientHintsHeaderMapping[i]));
Tarun Bansalf9cf9892018-04-06 04:38:01668 }
Tarun Bansal1965b042017-09-07 04:59:19669 }
670
Tarun Bansal7f3fe8c2018-04-06 22:37:47671 void VerifyNetworkQualityClientHints(
672 const net::test_server::HttpRequest& request) const {
673 // Effective connection type is forced to 2G using command line in these
674 // tests.
Tarun Bansal509a8dd2018-04-10 17:19:16675 int rtt_value = 0.0;
Tarun Bansal7f3fe8c2018-04-06 22:37:47676 EXPECT_TRUE(
Tarun Bansal509a8dd2018-04-10 17:19:16677 base::StringToInt(request.headers.find("rtt")->second, &rtt_value));
678 EXPECT_LE(0, rtt_value);
Tarun Bansal62efba12018-05-04 22:58:35679 EXPECT_TRUE(IsSimilarToIntABNF(request.headers.find("rtt")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16680 // Verify that RTT value is a multiple of 50 milliseconds.
681 EXPECT_EQ(0, rtt_value % 50);
Tarun Bansalbef6d652018-10-02 18:41:01682 EXPECT_GE(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? 3000 : 500,
683 rtt_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47684
Tarun Bansal509a8dd2018-04-10 17:19:16685 double mbps_value = 0.0;
686 EXPECT_TRUE(base::StringToDouble(request.headers.find("downlink")->second,
687 &mbps_value));
688 EXPECT_LE(0, mbps_value);
Tarun Bansal62efba12018-05-04 22:58:35689 EXPECT_TRUE(
690 IsSimilarToDoubleABNF(request.headers.find("downlink")->second));
Tarun Bansal509a8dd2018-04-10 17:19:16691 // Verify that the mbps value is a multiple of 0.050 mbps.
692 // Allow for small amount of noise due to double to integer conversions.
693 EXPECT_NEAR(0, (static_cast<int>(mbps_value * 1000)) % 50, 1);
694 EXPECT_GE(10.0, mbps_value);
Tarun Bansal7f3fe8c2018-04-06 22:37:47695
696 EXPECT_FALSE(request.headers.find("ect")->second.empty());
Tarun Bansalceab9592018-05-01 18:57:35697
698 // TODO(tbansal): https://crbug.com/819244: When network servicification is
Tarun Bansal5ac533542018-08-10 19:45:52699 // enabled, the renderer processes do not receive notifications on
700 // change in the network quality. Hence, the network quality client hints
701 // are not set to the correct value on subresources.
702 bool is_main_frame_navigation =
703 request.GetURL().spec().find(".html") != std::string::npos;
John Abd-El-Malek67facbe82019-06-06 22:37:08704 if (is_main_frame_navigation) {
Tarun Bansalceab9592018-05-01 18:57:35705 // Effective connection type is forced to 2G using command line in these
706 // tests. RTT is expected to be 1800 msec but leave some gap to account
707 // for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01708 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
709 EXPECT_NEAR(1800, rtt_value, 360);
710 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
711 EXPECT_NEAR(450, rtt_value, 90);
712 } else {
713 NOTREACHED();
714 }
Tarun Bansalceab9592018-05-01 18:57:35715
716 // Effective connection type is forced to 2G using command line in these
717 // tests. downlink is expected to be 0.075 Mbps but leave some gap to
718 // account for added noise and randomization.
Tarun Bansalbef6d652018-10-02 18:41:01719 if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
720 EXPECT_NEAR(0.075, mbps_value, 0.05);
721 } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
722 EXPECT_NEAR(0.4, mbps_value, 0.1);
723 } else {
724 NOTREACHED();
725 }
Tarun Bansalceab9592018-05-01 18:57:35726
Tarun Bansalbef6d652018-10-02 18:41:01727 EXPECT_EQ(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? "2g" : "3g",
728 request.headers.find("ect")->second);
Tarun Bansalceab9592018-05-01 18:57:35729 }
Tarun Bansal7f3fe8c2018-04-06 22:37:47730 }
731
Tarun Bansal3b330b02017-11-09 19:03:14732 net::EmbeddedTestServer http_server_;
Tarun Bansal0b8b7afd2017-08-25 03:52:16733 net::EmbeddedTestServer https_server_;
Tarun Bansal345418632018-06-29 11:07:04734 net::EmbeddedTestServer https_cross_origin_server_;
Tarun Bansal3b330b02017-11-09 19:03:14735 GURL accept_ch_with_lifetime_http_local_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05736 GURL http_equiv_accept_ch_with_lifetime_http_local_url_;
Tarun Bansal1965b042017-09-07 04:59:19737 GURL accept_ch_with_lifetime_url_;
Tarun Bansal73502f92019-04-16 21:21:19738 GURL accept_ch_with_short_lifetime_url_;
Tarun Bansal1965b042017-09-07 04:59:19739 GURL accept_ch_without_lifetime_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05740 GURL http_equiv_accept_ch_without_lifetime_url_;
Tarun Bansal1965b042017-09-07 04:59:19741 GURL without_accept_ch_without_lifetime_url_;
Tarun Bansal3b330b02017-11-09 19:03:14742 GURL without_accept_ch_without_lifetime_local_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58743 GURL accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05744 GURL http_equiv_accept_ch_without_lifetime_with_iframe_url_;
Tarun Bansal62cc3542018-06-27 23:53:30745 GURL accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05746 GURL http_equiv_accept_ch_without_lifetime_with_subresource_url_;
Tarun Bansal62cc3542018-06-27 23:53:30747 GURL accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansal9a7051f2018-07-10 18:30:05748 GURL http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
Tarun Bansaladd5e1812018-02-09 19:07:58749 GURL without_accept_ch_without_lifetime_img_foo_com_;
750 GURL without_accept_ch_without_lifetime_img_localhost_;
Tarun Bansal229647bd002018-02-27 17:33:36751 GURL accept_ch_without_lifetime_img_localhost_;
Tarun Bansal9a7051f2018-07-10 18:30:05752 GURL http_equiv_accept_ch_without_lifetime_img_localhost_;
753 GURL http_equiv_accept_ch_with_lifetime_;
Tarun Bansal293a7b6c2018-12-05 17:41:12754 GURL redirect_url_;
Tarun Bansal1965b042017-09-07 04:59:19755
Mike Weste555be862019-02-20 16:17:30756 std::string main_frame_ua_observed_;
Yoav Weissd33bacb2020-03-12 06:42:21757 std::string main_frame_ua_full_version_observed_;
Maks Orlovich73f374d2020-04-02 12:46:13758 std::string main_frame_ua_mobile_observed_;
759 std::string main_frame_ua_platform_observed_;
Mike Weste555be862019-02-20 16:17:30760
Tarun Bansal44ad96882018-03-28 17:47:42761 double main_frame_dpr_observed_ = -1;
762 double main_frame_viewport_width_observed_ = -1;
763 double main_frame_device_memory_observed_ = -1;
764
Tarun Bansal229647bd002018-02-27 17:33:36765 // Expect client hints on all the main frame request.
766 bool expect_client_hints_on_main_frame_;
767 // Expect client hints on all the subresource requests.
Callum May1d939742020-03-02 17:51:30768 bool expect_client_hints_on_subresources_
769 GUARDED_BY(expect_client_hints_on_subresources_lock_);
770
771 base::Lock expect_client_hints_on_subresources_lock_;
Tarun Bansal229647bd002018-02-27 17:33:36772
Mike West2fddeeb72019-02-15 11:29:48773 size_t count_user_agent_hint_headers_seen_;
Maks Orlovich5dcc99c2020-02-13 19:07:46774 size_t count_ua_mobile_client_hints_headers_seen_;
Tarun Bansal1965b042017-09-07 04:59:19775 size_t count_client_hints_headers_seen_;
Tarun Bansala61f0f62017-10-24 23:53:05776
Jay Civelli1ff872d2018-03-09 21:52:16777 std::unique_ptr<ThirdPartyURLLoaderInterceptor> request_interceptor_;
Tarun Bansal229647bd002018-02-27 17:33:36778
Tarun Bansalbef6d652018-10-02 18:41:01779 // Set to 2G in SetUpCommandLine().
780 net::EffectiveConnectionType expected_ect = net::EFFECTIVE_CONNECTION_TYPE_2G;
781
Tarun Bansala61f0f62017-10-24 23:53:05782 DISALLOW_COPY_AND_ASSIGN(ClientHintsBrowserTest);
Tarun Bansal0b8b7afd2017-08-25 03:52:16783};
784
Tarun Bansal9a7051f2018-07-10 18:30:05785// True if testing for http-equiv correctness. When set to true, the tests
786// use webpages that may contain http-equiv Accept-CH and Accept-CH-Lifetime
787// headers. When set to false, the tests use webpages that set the headers in
788// the HTTP response headers.
Ilia Samsonov282c38412019-12-09 08:15:10789INSTANTIATE_TEST_SUITE_P(All,
Victor Costane5e91512019-02-13 08:24:02790 ClientHintsBrowserTest,
791 testing::Bool());
Tarun Bansal9a7051f2018-07-10 18:30:05792
Tarun Bansalea0d8262018-05-21 16:11:50793class ClientHintsAllowThirdPartyBrowserTest : public ClientHintsBrowserTest {
Mike West2fddeeb72019-02-15 11:29:48794 std::unique_ptr<base::FeatureList> EnabledFeatures() override {
795 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
796 feature_list->InitializeFromCommandLine(
797 "AllowClientHintsToThirdParty,UserAgentClientHint", "");
798 return feature_list;
Tarun Bansalea0d8262018-05-21 16:11:50799 }
800};
801
Ilia Samsonov282c38412019-12-09 08:15:10802INSTANTIATE_TEST_SUITE_P(All,
Aaron Tagliaboschia09ec442019-09-18 15:29:03803 ClientHintsAllowThirdPartyBrowserTest,
804 testing::Bool());
805
Tarun Bansal74e189d2018-05-07 19:07:35806IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, CorsChecks) {
Mike West14c11102019-02-04 16:16:47807 for (size_t i = 0; i < blink::kClientHintsMappingsCount; ++i) {
Tarun Bansal74e189d2018-05-07 19:07:35808 // Do not test for headers that have not been enabled on the blink "stable"
809 // yet.
810 if (std::string(blink::kClientHintsHeaderMapping[i]) == "rtt" ||
811 std::string(blink::kClientHintsHeaderMapping[i]) == "downlink" ||
812 std::string(blink::kClientHintsHeaderMapping[i]) == "ect") {
813 continue;
814 }
Takashi Toyoshima2e01e692018-11-16 03:23:27815 EXPECT_TRUE(network::cors::IsCorsSafelistedHeader(
Tarun Bansal74e189d2018-05-07 19:07:35816 blink::kClientHintsHeaderMapping[i], "42" /* value */));
817 }
Takashi Toyoshima2e01e692018-11-16 03:23:27818 EXPECT_FALSE(network::cors::IsCorsSafelistedHeader("not-a-client-hint-header",
Tarun Bansal74e189d2018-05-07 19:07:35819 "" /* value */));
820 EXPECT_TRUE(
Takashi Toyoshima2e01e692018-11-16 03:23:27821 network::cors::IsCorsSafelistedHeader("save-data", "on" /* value */));
Tarun Bansal74e189d2018-05-07 19:07:35822}
823
Maks Orlovichf0a2eed2020-05-02 20:08:21824IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, HttpEquivWorks) {
825 const GURL gurl = http_equiv_accept_ch_without_lifetime_img_localhost();
826 base::HistogramTester histogram_tester;
827
828 SetClientHintExpectationsOnMainFrame(false);
829 SetClientHintExpectationsOnSubresources(true);
830
831 ui_test_utils::NavigateToURL(browser(), gurl);
832 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
833}
834
Tarun Bansal0b8b7afd2017-08-25 03:52:16835// Loads a webpage that requests persisting of client hints. Verifies that
836// the browser receives the mojo notification from the renderer and persists the
Maks Orlovichf0a2eed2020-05-02 20:08:21837// client hints to the disk --- unless it's using http-equiv which shouldn't
838// persist.
Tarun Bansal9a7051f2018-07-10 18:30:05839IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, ClientHintsHttps) {
Tarun Bansal0b8b7afd2017-08-25 03:52:16840 base::HistogramTester histogram_tester;
Tarun Bansal9a7051f2018-07-10 18:30:05841 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
842 : accept_ch_with_lifetime_url();
843 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal0b8b7afd2017-08-25 03:52:16844
Maks Orlovichf0a2eed2020-05-02 20:08:21845 if (GetParam())
846 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
847 else
848 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
Tarun Bansal0b8b7afd2017-08-25 03:52:16849
850 content::FetchHistogramsFromChildProcesses();
851 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
852
Maks Orlovichf0a2eed2020-05-02 20:08:21853 if (GetParam()) {
854 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
855 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
856 } else {
857 // client_hints_url() sets the expected number of client hints.
858 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
859 expected_client_hints_number, 1);
860 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
861 // seconds.
862 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
863 3600 * 1000, 1);
864 }
Tarun Bansal0b8b7afd2017-08-25 03:52:16865}
866
Tarun Bansaladd5e1812018-02-09 19:07:58867// Test that client hints are attached to subresources only if they belong
868// to the same host as document host.
Maks Orlovichf0a2eed2020-05-02 20:08:21869IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansaladd5e1812018-02-09 19:07:58870 ClientHintsHttpsSubresourceDifferentOrigin) {
Maks Orlovichf0a2eed2020-05-02 20:08:21871 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:05872
Tarun Bansaladd5e1812018-02-09 19:07:58873 base::HistogramTester histogram_tester;
874
875 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:05876 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:58877 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
878
879 // Verify that the client hints settings for localhost have been saved.
880 ContentSettingsForOneType client_hints_settings;
881 HostContentSettingsMap* host_content_settings_map =
882 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
883 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:45884 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansaladd5e1812018-02-09 19:07:58885 ASSERT_EQ(1U, client_hints_settings.size());
886
887 // Copy the client hints setting for localhost to foo.com.
888 host_content_settings_map->SetWebsiteSettingDefaultScope(
Darin Fisher42f5e7d2019-10-30 07:15:45889 GURL("https://foo.com/"), GURL(), ContentSettingsType::CLIENT_HINTS,
Tarun Bansaladd5e1812018-02-09 19:07:58890 std::string(),
Jeremy Romanec48d7a2018-03-01 17:35:09891 std::make_unique<base::Value>(
Oksana Zhuravlovab14dc882018-04-12 17:34:57892 client_hints_settings.at(0).setting_value.Clone()));
Tarun Bansaladd5e1812018-02-09 19:07:58893
894 // Verify that client hints for the two hosts has been saved.
895 host_content_settings_map =
896 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
897 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:45898 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansaladd5e1812018-02-09 19:07:58899 ASSERT_EQ(2U, client_hints_settings.size());
900
901 // Navigating to without_accept_ch_without_lifetime_img_localhost() should
902 // attach client hints to the image subresouce contained in that page since
903 // the image is located on the same server as the document origin.
Tarun Bansal229647bd002018-02-27 17:33:36904 SetClientHintExpectationsOnMainFrame(true);
905 SetClientHintExpectationsOnSubresources(true);
Tarun Bansaladd5e1812018-02-09 19:07:58906 ui_test_utils::NavigateToURL(
907 browser(), without_accept_ch_without_lifetime_img_localhost());
908 base::RunLoop().RunUntilIdle();
909 content::FetchHistogramsFromChildProcesses();
910 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
911
Maks Orlovich5dcc99c2020-02-13 19:07:46912 // The user agent hint is attached to all three requests, as is UA-mobile:
Mike West2fddeeb72019-02-15 11:29:48913 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:46914 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:48915
Yoav Weissd33bacb2020-03-12 06:42:21916 // Expected number of hints attached to the image request, and the same number
917 // to the main frame request.
918 EXPECT_EQ(expected_client_hints_number * 2,
919 count_client_hints_headers_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58920
921 // Navigating to without_accept_ch_without_lifetime_img_foo_com() should not
922 // attach client hints to the image subresouce contained in that page since
923 // the image is located on a different server as the document origin.
Tarun Bansaladd5e1812018-02-09 19:07:58924 ui_test_utils::NavigateToURL(
925 browser(), without_accept_ch_without_lifetime_img_foo_com());
926 base::RunLoop().RunUntilIdle();
927 content::FetchHistogramsFromChildProcesses();
928 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
929
Tarun Bansalb30b7532018-03-14 21:50:38930 // The device-memory and dprheader is attached to the main frame request.
Tarun Bansal5c28afb2018-03-17 02:55:20931#if defined(OS_ANDROID)
Yoav Weissd33bacb2020-03-12 06:42:21932 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20933#else
Yoav Weissd33bacb2020-03-12 06:42:21934 EXPECT_EQ(expected_client_hints_number * 3,
935 count_client_hints_headers_seen());
Tarun Bansal5c28afb2018-03-17 02:55:20936#endif
Mike West2fddeeb72019-02-15 11:29:48937
938 // Requests to third party servers should have only one client hint attached
939 // (`Sec-CH-UA`).
Tarun Bansal229647bd002018-02-27 17:33:36940 EXPECT_EQ(1u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:46941 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansaladd5e1812018-02-09 19:07:58942}
943
Maks Orlovich7227ce0d2020-02-28 17:13:16944// Test that client hints are attached to subresources checks the right setting
945// for OTR profile.
Maks Orlovichf0a2eed2020-05-02 20:08:21946IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Maks Orlovich7227ce0d2020-02-28 17:13:16947 ClientHintsHttpsSubresourceOffTheRecord) {
Maks Orlovichf0a2eed2020-05-02 20:08:21948 const GURL gurl = accept_ch_with_lifetime_url();
Maks Orlovich7227ce0d2020-02-28 17:13:16949
950 base::HistogramTester histogram_tester;
951
952 // Add client hints for the embedded test server.
953 ui_test_utils::NavigateToURL(browser(), gurl);
954 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
955
956 // Main profile should get hints for both page and subresources.
957 SetClientHintExpectationsOnMainFrame(true);
958 SetClientHintExpectationsOnSubresources(true);
959 ui_test_utils::NavigateToURL(
960 browser(), without_accept_ch_without_lifetime_img_localhost());
961 base::RunLoop().RunUntilIdle();
962 content::FetchHistogramsFromChildProcesses();
963 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
964
965 // The user agent hint is attached to all three requests:
966 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
967 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
968
Yoav Weissd33bacb2020-03-12 06:42:21969 // Expected number of hints attached to the image request, and the same number
970 // to the main frame request.
971 EXPECT_EQ(expected_client_hints_number * 2,
972 count_client_hints_headers_seen());
Maks Orlovich7227ce0d2020-02-28 17:13:16973
974 // OTR profile should get neither.
975 Browser* otr_browser = CreateIncognitoBrowser(browser()->profile());
976 SetClientHintExpectationsOnMainFrame(false);
977 SetClientHintExpectationsOnSubresources(false);
978 ui_test_utils::NavigateToURL(
979 otr_browser, without_accept_ch_without_lifetime_img_localhost());
980}
981
Mike Weste555be862019-02-20 16:17:30982// Verify that we send only major version information in the `Sec-CH-UA` header
Yoav Weissd33bacb2020-03-12 06:42:21983// by default, regardless of opt-in.
Maks Orlovichf0a2eed2020-05-02 20:08:21984IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentVersion) {
985 const GURL gurl = accept_ch_with_lifetime_url();
Mike Weste555be862019-02-20 16:17:30986
987 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
988
989 // Navigate to a page that opts-into the header: the value should end with
990 // the major version, and not contain the full version.
991 SetClientHintExpectationsOnMainFrame(false);
992 ui_test_utils::NavigateToURL(browser(), gurl);
Aaron Tagliaboschi9f01b682020-05-05 21:03:17993 std::string expected_ua = ua.SerializeBrandVersionList();
Yoav Weissd33bacb2020-03-12 06:42:21994 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
995 EXPECT_TRUE(main_frame_ua_full_version_observed().empty());
Mike Weste555be862019-02-20 16:17:30996
Yoav Weissd33bacb2020-03-12 06:42:21997 // Navigate again, after the opt-in: the value should stay the major
Mike Weste555be862019-02-20 16:17:30998 // version.
999 SetClientHintExpectationsOnMainFrame(true);
1000 ui_test_utils::NavigateToURL(browser(), gurl);
Yoav Weissd33bacb2020-03-12 06:42:211001 std::string expected_full_version = "\"" + ua.full_version + "\"";
1002 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1003 EXPECT_EQ(main_frame_ua_full_version_observed(), expected_full_version);
Mike Weste555be862019-02-20 16:17:301004}
1005
Maks Orlovichf0a2eed2020-05-02 20:08:211006IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UAHintsTabletMode) {
1007 const GURL gurl = accept_ch_with_lifetime_url();
Maks Orlovich73f374d2020-04-02 12:46:131008
1009 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
1010
1011 // First request: only minimal hints, no tablet override.
1012 SetClientHintExpectationsOnMainFrame(false);
1013 ui_test_utils::NavigateToURL(browser(), gurl);
Aaron Tagliaboschi9f01b682020-05-05 21:03:171014 std::string expected_ua = ua.SerializeBrandVersionList();
Maks Orlovich73f374d2020-04-02 12:46:131015 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1016 EXPECT_EQ(main_frame_ua_full_version_observed(), "");
1017 EXPECT_EQ(main_frame_ua_mobile_observed(), "?0");
1018 EXPECT_EQ(main_frame_ua_platform_observed(), "");
1019
1020 // Second request: table override, all hints.
1021 chrome::ToggleRequestTabletSite(browser());
1022 SetClientHintExpectationsOnMainFrame(true);
1023 ui_test_utils::NavigateToURL(browser(), gurl);
1024 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1025 std::string expected_full_version = "\"" + ua.full_version + "\"";
1026 EXPECT_EQ(main_frame_ua_full_version_observed(), expected_full_version);
1027 EXPECT_EQ(main_frame_ua_mobile_observed(), "?1");
1028 EXPECT_EQ(main_frame_ua_platform_observed(), "\"Android\"");
1029}
1030
1031// TODO(morlovich): Move this into WebContentsImplBrowserTest once things are
1032// refactored enough that UA client hints actually work in content/
1033IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentOverrideClientHints) {
1034 content::WebContents* web_contents =
1035 browser()->tab_strip_model()->GetActiveWebContents();
1036
1037 ASSERT_TRUE(embedded_test_server()->Start());
1038 const std::string kHeaderPath = std::string("/echoheader?") +
1039 net::HttpRequestHeaders::kUserAgent +
1040 "&sec-ch-ua&sec-ch-ua-mobile";
1041 const GURL kUrl(embedded_test_server()->GetURL(kHeaderPath));
1042
1043 web_contents->SetUserAgentOverride(
1044 blink::UserAgentOverride::UserAgentOnly("foo"), false);
1045 // Not enabled first.
1046 ui_test_utils::NavigateToURL(browser(), kUrl);
1047 std::string header_value;
1048 EXPECT_TRUE(ExecuteScriptAndExtractString(
1049 web_contents,
1050 "window.domAutomationController.send(document.body.textContent);",
1051 &header_value));
1052 EXPECT_EQ(std::string::npos, header_value.find("foo")) << header_value;
1053
1054 // Actually turn it on.
1055 web_contents->GetController()
1056 .GetLastCommittedEntry()
1057 ->SetIsOverridingUserAgent(true);
1058
1059 ui_test_utils::NavigateToURL(browser(), kUrl);
1060 EXPECT_TRUE(ExecuteScriptAndExtractString(
1061 web_contents,
1062 "window.domAutomationController.send(document.body.textContent);",
1063 &header_value));
1064 // Since no value was provided for client hints, they are not sent.
1065 EXPECT_EQ("foo\nNone\nNone", header_value);
1066
1067 // Now actually provide values for the hints.
1068 blink::UserAgentOverride ua_override;
1069 ua_override.ua_string_override = "foobar";
1070 ua_override.ua_metadata_override.emplace();
1071 ua_override.ua_metadata_override->mobile = true;
Aaron Tagliaboschi9f01b682020-05-05 21:03:171072 ua_override.ua_metadata_override->brand_version_list.emplace_back(
1073 "Foobarnator", "3.14");
Maks Orlovich73f374d2020-04-02 12:46:131074 web_contents->SetUserAgentOverride(ua_override, false);
1075 ui_test_utils::NavigateToURL(browser(), kUrl);
1076 EXPECT_TRUE(ExecuteScriptAndExtractString(
1077 web_contents,
1078 "window.domAutomationController.send(document.body.textContent);",
1079 &header_value));
Aaron Tagliaboschi9f01b682020-05-05 21:03:171080 EXPECT_EQ("foobar\n\"Foobarnator\";v=\"3.14\"\n?1", header_value);
Maks Orlovich73f374d2020-04-02 12:46:131081}
1082
Maks Orlovich7227ce0d2020-02-28 17:13:161083void ClientHintsBrowserTest::TestProfilesIndependent(Browser* browser_a,
1084 Browser* browser_b) {
Maks Orlovichf0a2eed2020-05-02 20:08:211085 const GURL gurl = accept_ch_with_lifetime_url();
Maks Orlovich7227ce0d2020-02-28 17:13:161086
1087 blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
1088
1089 // Navigate |browser_a| to a page that opts-into the header: the value should
1090 // end with the major version, and not contain the full version.
1091 SetClientHintExpectationsOnMainFrame(false);
1092 ui_test_utils::NavigateToURL(browser_a, gurl);
Aaron Tagliaboschi9f01b682020-05-05 21:03:171093 std::string expected_ua = ua.SerializeBrandVersionList();
Yoav Weissd33bacb2020-03-12 06:42:211094 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1095 EXPECT_TRUE(main_frame_ua_full_version_observed().empty());
Maks Orlovich7227ce0d2020-02-28 17:13:161096
1097 // Try again on |browser_a|, the header should have an effect there.
1098 SetClientHintExpectationsOnMainFrame(true);
1099 ui_test_utils::NavigateToURL(browser_a, gurl);
Yoav Weissd33bacb2020-03-12 06:42:211100 std::string expected_full_version = "\"" + ua.full_version + "\"";
1101 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1102 EXPECT_EQ(main_frame_ua_full_version_observed(), expected_full_version);
Maks Orlovich7227ce0d2020-02-28 17:13:161103
1104 // Navigate on |browser_b|. That should still only have the major
1105 // version.
1106 SetClientHintExpectationsOnMainFrame(false);
1107 ui_test_utils::NavigateToURL(browser_b, gurl);
Yoav Weissd33bacb2020-03-12 06:42:211108 EXPECT_EQ(main_frame_ua_observed(), expected_ua);
1109 EXPECT_TRUE(main_frame_ua_full_version_observed().empty());
Maks Orlovich7227ce0d2020-02-28 17:13:161110}
1111
1112// Check that client hints attached to navigation inside OTR profiles
1113// use the right settings, regular -> OTR direction.
Maks Orlovichf0a2eed2020-05-02 20:08:211114IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent) {
Maks Orlovich7227ce0d2020-02-28 17:13:161115 TestProfilesIndependent(browser(),
1116 CreateIncognitoBrowser(browser()->profile()));
1117}
1118
1119// Check that client hints attached to navigation inside OTR profiles
1120// use the right settings, OTR -> regular direction.
Maks Orlovichf0a2eed2020-05-02 20:08:211121IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent2) {
Maks Orlovich7227ce0d2020-02-28 17:13:161122 TestProfilesIndependent(CreateIncognitoBrowser(browser()->profile()),
1123 browser());
1124}
1125
Tarun Bansalea0d8262018-05-21 16:11:501126// Test that client hints are attached to third party subresources if
1127// AllowClientHintsToThirdParty feature is enabled.
Tarun Bansal9a7051f2018-07-10 18:30:051128IN_PROC_BROWSER_TEST_P(ClientHintsAllowThirdPartyBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:501129 ClientHintsThirdPartyAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051130 const GURL gurl = GetParam()
1131 ? http_equiv_accept_ch_without_lifetime_img_localhost()
1132 : accept_ch_without_lifetime_img_localhost();
1133
Tarun Bansalea0d8262018-05-21 16:11:501134 base::HistogramTester histogram_tester;
1135
1136 SetClientHintExpectationsOnMainFrame(false);
1137 SetClientHintExpectationsOnSubresources(true);
1138
1139 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:051140 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansalea0d8262018-05-21 16:11:501141 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1142
Yoav Weissd33bacb2020-03-12 06:42:211143 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:501144
1145 // Requests to third party servers should not have client hints attached.
1146 EXPECT_EQ(1u, third_party_request_count_seen());
1147
Aaron Tagliaboschia09ec442019-09-18 15:29:031148 // Device memory, viewport width, DRP, and UA client hints should be sent to
1149 // the third-party when feature "AllowClientHintsToThirdParty" is enabled.
Maks Orlovich5dcc99c2020-02-13 19:07:461150 EXPECT_EQ(5u, third_party_client_hints_count_seen());
Tarun Bansalea0d8262018-05-21 16:11:501151}
1152
1153// Test that client hints are not attached to third party subresources if
1154// AllowClientHintsToThirdParty feature is not enabled.
Tarun Bansal9a7051f2018-07-10 18:30:051155IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansalea0d8262018-05-21 16:11:501156 ClientHintsThirdPartyNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051157 const GURL gurl = GetParam()
1158 ? http_equiv_accept_ch_without_lifetime_img_localhost()
1159 : accept_ch_without_lifetime_img_localhost();
1160
Tarun Bansalea0d8262018-05-21 16:11:501161 base::HistogramTester histogram_tester;
1162
1163 SetClientHintExpectationsOnMainFrame(false);
1164 SetClientHintExpectationsOnSubresources(true);
1165
1166 // Add client hints for the embedded test server.
Tarun Bansal9a7051f2018-07-10 18:30:051167 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansalea0d8262018-05-21 16:11:501168 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1169
Mike West2fddeeb72019-02-15 11:29:481170 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461171 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:211172 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansalea0d8262018-05-21 16:11:501173
1174 // Requests to third party servers should not have client hints attached.
1175 EXPECT_EQ(1u, third_party_request_count_seen());
1176
1177 // Client hints should not be sent to the third-party when feature
Mike West2fddeeb72019-02-15 11:29:481178 // "AllowClientHintsToThirdParty" is not enabled, with the exception of the
1179 // `Sec-CH-UA` hint, which is sent with every request.
Maks Orlovich5dcc99c2020-02-13 19:07:461180 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansalea0d8262018-05-21 16:11:501181}
1182
Tarun Bansaladd5e1812018-02-09 19:07:581183// Loads a HTTPS webpage that does not request persisting of client hints.
Tarun Bansal345418632018-06-29 11:07:041184// A same-origin iframe loaded by the webpage requests persistence of client
1185// hints. Verify that the request from the iframe is honored, and client hints
1186// preference is persisted.
Maks Orlovichf0a2eed2020-05-02 20:08:211187IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:041188 PersistenceRequestIframe_SameOrigin) {
Maks Orlovichf0a2eed2020-05-02 20:08:211189 const GURL gurl = accept_ch_without_lifetime_with_iframe_url();
Tarun Bansal345418632018-06-29 11:07:041190 base::HistogramTester histogram_tester;
1191 ContentSettingsForOneType host_settings;
1192
1193 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451194 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal345418632018-06-29 11:07:041195 &host_settings);
1196 EXPECT_EQ(0u, host_settings.size());
1197
Tarun Bansal9a7051f2018-07-10 18:30:051198 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal345418632018-06-29 11:07:041199
1200 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
1201
1202 content::FetchHistogramsFromChildProcesses();
1203 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1204
1205 // accept_ch_without_lifetime_with_iframe_url() loads
1206 // accept_ch_with_lifetime() in an iframe. The request to persist client
1207 // hints from accept_ch_with_lifetime() should be persisted.
1208 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 1);
1209 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1210 3600 * 1000, 1);
1211}
1212
1213// Loads a HTTPS webpage that does not request persisting of client hints.
1214// An iframe loaded by the webpage from an cross origin server requests
1215// persistence of client hints.
1216// Verify that the request from the cross origin iframe is not honored, and
1217// client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051218IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal345418632018-06-29 11:07:041219 DisregardPersistenceRequestIframe_CrossOrigin) {
Tarun Bansal9a7051f2018-07-10 18:30:051220 const GURL gurl =
1221 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
1222 : accept_ch_without_lifetime_with_iframe_url();
1223
1224 intercept_iframe_resource_ = gurl.path();
1225 intercept_to_http_equiv_iframe_ = GetParam();
1226
Tarun Bansaladd5e1812018-02-09 19:07:581227 base::HistogramTester histogram_tester;
1228 ContentSettingsForOneType host_settings;
1229
1230 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451231 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansaladd5e1812018-02-09 19:07:581232 &host_settings);
1233 EXPECT_EQ(0u, host_settings.size());
1234
Tarun Bansal9a7051f2018-07-10 18:30:051235 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansaladd5e1812018-02-09 19:07:581236
1237 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1238
1239 content::FetchHistogramsFromChildProcesses();
1240 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1241
1242 // accept_ch_without_lifetime_with_iframe_url() loads
Tarun Bansal345418632018-06-29 11:07:041243 // accept_ch_with_lifetime() in a cross origin iframe. The request to persist
1244 // client hints from accept_ch_with_lifetime() should be disregarded.
Tarun Bansaladd5e1812018-02-09 19:07:581245 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1246 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1247}
1248
Tarun Bansal62cc3542018-06-27 23:53:301249// Loads a HTTPS webpage that does not request persisting of client hints.
1250// A subresource loaded by the webpage requests persistence of client hints.
1251// Verify that the request from the subresource is not honored, and client hints
1252// preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051253IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:301254 DisregardPersistenceRequestSubresource) {
Tarun Bansal9a7051f2018-07-10 18:30:051255 const GURL gurl =
1256 GetParam() ? http_equiv_accept_ch_without_lifetime_with_subresource_url()
1257 : accept_ch_without_lifetime_with_subresource_url();
1258
Tarun Bansal62cc3542018-06-27 23:53:301259 base::HistogramTester histogram_tester;
1260 ContentSettingsForOneType host_settings;
1261
1262 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451263 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal62cc3542018-06-27 23:53:301264 &host_settings);
1265 EXPECT_EQ(0u, host_settings.size());
1266
Tarun Bansal9a7051f2018-07-10 18:30:051267 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:301268
1269 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1270
1271 content::FetchHistogramsFromChildProcesses();
1272 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1273
1274 // accept_ch_without_lifetime_with_subresource_url() loads
1275 // accept_ch_with_lifetime() as a subresource. The request to persist client
1276 // hints from accept_ch_with_lifetime() should be disregarded.
1277 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1278 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1279}
1280
1281// Loads a HTTPS webpage that does not request persisting of client hints.
1282// A subresource loaded by the webpage in an iframe requests persistence of
1283// client hints. Verify that the request from the subresource in the iframe
1284// is not honored, and client hints preference is not persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051285IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal62cc3542018-06-27 23:53:301286 DisregardPersistenceRequestSubresourceIframe) {
Tarun Bansal9a7051f2018-07-10 18:30:051287 const GURL gurl =
1288 GetParam()
1289 ? http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url()
1290 : accept_ch_without_lifetime_with_subresource_iframe_url();
1291
Tarun Bansal62cc3542018-06-27 23:53:301292 base::HistogramTester histogram_tester;
1293 ContentSettingsForOneType host_settings;
1294
1295 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451296 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal62cc3542018-06-27 23:53:301297 &host_settings);
1298 EXPECT_EQ(0u, host_settings.size());
1299
Tarun Bansal9a7051f2018-07-10 18:30:051300 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal62cc3542018-06-27 23:53:301301
1302 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1303
1304 content::FetchHistogramsFromChildProcesses();
1305 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1306
Tarun Bansal9a7051f2018-07-10 18:30:051307 // |gurl| loads accept_ch_with_lifetime() or
1308 // http_equiv_accept_ch_with_lifetime() as a subresource in an iframe. The
1309 // request to persist client hints from accept_ch_with_lifetime() or
1310 // http_equiv_accept_ch_with_lifetime() should be disregarded.
Tarun Bansal62cc3542018-06-27 23:53:301311 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1312 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1313}
1314
Tarun Bansal3b330b02017-11-09 19:03:141315// Loads a HTTP local webpage (which qualifies as a secure context) that
1316// requests persisting of client hints. Verifies that the browser receives the
1317// mojo notification from the renderer and persists the client hints to the
1318// disk.
Maks Orlovichf0a2eed2020-05-02 20:08:211319IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal3b330b02017-11-09 19:03:141320 ClientHintsLifetimeFollowedByNoClientHintHttpLocal) {
Maks Orlovichf0a2eed2020-05-02 20:08:211321 const GURL gurl = accept_ch_with_lifetime_http_local_url();
Tarun Bansal9a7051f2018-07-10 18:30:051322
Tarun Bansal3b330b02017-11-09 19:03:141323 base::HistogramTester histogram_tester;
1324 ContentSettingsForOneType host_settings;
1325
1326 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451327 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3b330b02017-11-09 19:03:141328 &host_settings);
1329 EXPECT_EQ(0u, host_settings.size());
1330
Tarun Bansal9a7051f2018-07-10 18:30:051331 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal3b330b02017-11-09 19:03:141332
1333 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1334
1335 content::FetchHistogramsFromChildProcesses();
1336 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1337
Yoav Weissd33bacb2020-03-12 06:42:211338 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1339 expected_client_hints_number, 1);
Tarun Bansal9a7051f2018-07-10 18:30:051340 // |gurl| sets client hints persist duration to 3600 seconds.
Tarun Bansal3b330b02017-11-09 19:03:141341 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1342 3600 * 1000, 1);
1343
1344 base::RunLoop().RunUntilIdle();
1345
1346 // Clients hints preferences for one origin should be persisted.
1347 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451348 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3b330b02017-11-09 19:03:141349 &host_settings);
1350 EXPECT_EQ(1u, host_settings.size());
1351
Tarun Bansal229647bd002018-02-27 17:33:361352 SetClientHintExpectationsOnMainFrame(true);
1353 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal3b330b02017-11-09 19:03:141354 ui_test_utils::NavigateToURL(browser(),
1355 without_accept_ch_without_lifetime_local_url());
1356
Mike West2fddeeb72019-02-15 11:29:481357 // The user agent hint is attached to all three requests:
1358 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461359 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481360
Yoav Weissd33bacb2020-03-12 06:42:211361 // Expected number of hints attached to the image request, and the same number
1362 // to the main frame request.
1363 EXPECT_EQ(expected_client_hints_number * 2,
1364 count_client_hints_headers_seen());
Tarun Bansal3b330b02017-11-09 19:03:141365}
1366
Tarun Bansal0b8b7afd2017-08-25 03:52:161367// Loads a webpage that does not request persisting of client hints.
1368IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {
1369 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:191370 ui_test_utils::NavigateToURL(browser(),
1371 without_accept_ch_without_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:161372
1373 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1374
1375 content::FetchHistogramsFromChildProcesses();
1376 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1377
1378 // no_client_hints_url() does not sets the client hints.
1379 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1380 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1381}
1382
Tarun Bansal9a7051f2018-07-10 18:30:051383IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal1965b042017-09-07 04:59:191384 ClientHintsLifetimeFollowedByNoClientHint) {
Tarun Bansal9a7051f2018-07-10 18:30:051385 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1386 : accept_ch_with_lifetime_url();
1387
Tarun Bansal1965b042017-09-07 04:59:191388 base::HistogramTester histogram_tester;
1389 ContentSettingsForOneType host_settings;
1390
1391 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451392 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191393 &host_settings);
1394 EXPECT_EQ(0u, host_settings.size());
1395
Maks Orlovichf0a2eed2020-05-02 20:08:211396 // Fetching |gurl| should persist the request for client hints iff using
1397 // headers and not http-equiv.
Tarun Bansal9a7051f2018-07-10 18:30:051398 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansal1965b042017-09-07 04:59:191399
Maks Orlovichf0a2eed2020-05-02 20:08:211400 if (GetParam())
1401 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
1402 else
1403 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
Tarun Bansal1965b042017-09-07 04:59:191404
1405 content::FetchHistogramsFromChildProcesses();
1406 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Tarun Bansal1965b042017-09-07 04:59:191407 base::RunLoop().RunUntilIdle();
1408
Maks Orlovichf0a2eed2020-05-02 20:08:211409 if (GetParam()) {
1410 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
1411 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
1412 } else {
1413 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1414 expected_client_hints_number, 1);
1415 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1416 // seconds.
1417 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1418 3600 * 1000, 1);
Tarun Bansal1965b042017-09-07 04:59:191419
Maks Orlovichf0a2eed2020-05-02 20:08:211420 // Clients hints preferences for one origin should be persisted.
1421 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1422 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
1423 std::string(), &host_settings);
1424 EXPECT_EQ(1u, host_settings.size());
1425 }
1426
1427 SetClientHintExpectationsOnMainFrame(!GetParam());
1428 SetClientHintExpectationsOnSubresources(!GetParam());
Tarun Bansal1965b042017-09-07 04:59:191429 ui_test_utils::NavigateToURL(browser(),
1430 without_accept_ch_without_lifetime_url());
Tarun Bansal6bf54302017-10-02 07:39:141431
Mike West2fddeeb72019-02-15 11:29:481432 // The user agent hint is attached to all three requests:
1433 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461434 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481435
Yoav Weissd33bacb2020-03-12 06:42:211436 // Expected number of hints attached to the image request, and the same number
1437 // to the main frame request.
Maks Orlovichf0a2eed2020-05-02 20:08:211438 EXPECT_EQ(GetParam() ? 0 : expected_client_hints_number * 2,
Yoav Weissd33bacb2020-03-12 06:42:211439 count_client_hints_headers_seen());
Tarun Bansal1965b042017-09-07 04:59:191440}
1441
Tarun Bansal73502f92019-04-16 21:21:191442// Verify that expired persistent client hint preferences are not used.
1443// Verifies this by setting Accept-CH-Lifetime value to 1 second,
1444// and loading a page after 1 second to verify that client hints are not
1445// attached.
1446IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
1447 ShortLifetimeFollowedByNoClientHint) {
1448 const GURL gurl = accept_ch_with_short_lifetime();
1449
1450 base::HistogramTester histogram_tester;
1451 ContentSettingsForOneType host_settings;
1452
1453 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451454 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal73502f92019-04-16 21:21:191455 &host_settings);
1456 EXPECT_EQ(0u, host_settings.size());
1457
1458 // Fetching |gurl| should persist the request for client hints.
1459 ui_test_utils::NavigateToURL(browser(), gurl);
1460
1461 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1462
1463 content::FetchHistogramsFromChildProcesses();
1464 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1465
Yoav Weissd33bacb2020-03-12 06:42:211466 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1467 expected_client_hints_number, 1);
Tarun Bansal73502f92019-04-16 21:21:191468 // |gurl| sets client hints persist duration to 1 second.
1469 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration", 1 * 1000,
1470 1);
1471 base::RunLoop().RunUntilIdle();
1472
1473 // Clients hints preferences for one origin should be persisted.
1474 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451475 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal73502f92019-04-16 21:21:191476 &host_settings);
1477 EXPECT_EQ(1u, host_settings.size());
1478
1479 // Sleep for a duration longer than 1 second (duration of persisted client
1480 // hints).
1481 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1001));
1482
1483 SetClientHintExpectationsOnMainFrame(false);
1484 SetClientHintExpectationsOnSubresources(false);
1485 ui_test_utils::NavigateToURL(browser(),
1486 without_accept_ch_without_lifetime_url());
1487
1488 // The user agent hint is attached to all three requests:
1489 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461490 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansal73502f92019-04-16 21:21:191491
1492 // No client hints are attached to the requests since the persisted hints must
1493 // be expired.
1494 EXPECT_EQ(0u, count_client_hints_headers_seen());
1495}
1496
Tarun Bansal293a7b6c2018-12-05 17:41:121497// The test first fetches a page that sets Accept-CH-Lifetime. Next, it fetches
1498// a URL from a different origin. However, that URL response redirects to the
1499// same origin from where the first page was fetched. The test verifies that
1500// on receiving redirect to an origin for which the browser has persisted client
1501// hints prefs, the browser attaches the client hints headers when fetching the
1502// redirected URL.
Maks Orlovichf0a2eed2020-05-02 20:08:211503IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal293a7b6c2018-12-05 17:41:121504 ClientHintsLifetimeFollowedByRedirectToNoClientHint) {
Maks Orlovichf0a2eed2020-05-02 20:08:211505 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal293a7b6c2018-12-05 17:41:121506
1507 base::HistogramTester histogram_tester;
1508 ContentSettingsForOneType host_settings;
1509
1510 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451511 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal293a7b6c2018-12-05 17:41:121512 &host_settings);
1513 EXPECT_EQ(0u, host_settings.size());
1514
1515 // Fetching |gurl| should persist the request for client hints.
1516 ui_test_utils::NavigateToURL(browser(), gurl);
1517
1518 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1519
1520 content::FetchHistogramsFromChildProcesses();
1521 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1522
Yoav Weissd33bacb2020-03-12 06:42:211523 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1524 expected_client_hints_number, 1);
Tarun Bansal293a7b6c2018-12-05 17:41:121525 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1526 // seconds.
1527 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1528 3600 * 1000, 1);
1529 base::RunLoop().RunUntilIdle();
1530
1531 // Clients hints preferences for one origin should be persisted.
1532 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451533 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal293a7b6c2018-12-05 17:41:121534 &host_settings);
1535 EXPECT_EQ(1u, host_settings.size());
1536
1537 SetClientHintExpectationsOnMainFrame(true);
1538 SetClientHintExpectationsOnSubresources(true);
1539 ui_test_utils::NavigateToURL(browser(), redirect_url());
1540
Mike West2fddeeb72019-02-15 11:29:481541 // The user agent hint is attached to all three requests:
1542 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461543 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481544
Yoav Weissd33bacb2020-03-12 06:42:211545 // Expected number of hints attached to the image request, and the same number
1546 // to the main frame request.
1547 EXPECT_EQ(expected_client_hints_number * 2,
1548 count_client_hints_headers_seen());
Tarun Bansal293a7b6c2018-12-05 17:41:121549}
1550
Tarun Bansala0c1fc32018-10-03 16:14:521551// Ensure that even when cookies are blocked, client hint preferences are
Tarun Bansala61f0f62017-10-24 23:53:051552// persisted.
Maks Orlovichf0a2eed2020-05-02 20:08:211553IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521554 ClientHintsLifetimePersistedCookiesBlocked) {
Maks Orlovichf0a2eed2020-05-02 20:08:211555 const GURL gurl_with = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:051556
Tarun Bansala61f0f62017-10-24 23:53:051557 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1558 CookieSettingsFactory::GetForProfile(browser()->profile());
1559 base::HistogramTester histogram_tester;
1560 ContentSettingsForOneType host_settings;
1561
1562 // Block cookies.
1563 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansala0c1fc32018-10-03 16:14:521564 ->SetContentSettingDefaultScope(gurl_with, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451565 ContentSettingsType::COOKIES,
Tarun Bansala61f0f62017-10-24 23:53:051566 std::string(), CONTENT_SETTING_BLOCK);
1567
Tarun Bansala0c1fc32018-10-03 16:14:521568 // Fetching |gurl_with| should persist the request for client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051569 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala0c1fc32018-10-03 16:14:521570 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 1);
Tarun Bansala61f0f62017-10-24 23:53:051571 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451572 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051573 &host_settings);
1574 EXPECT_EQ(1u, host_settings.size());
Tarun Bansala0c1fc32018-10-03 16:14:521575 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051576}
1577
Maks Orlovichf0a2eed2020-05-02 20:08:211578IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521579 ClientHintsLifetimeAttachedCookiesBlocked) {
Maks Orlovichf0a2eed2020-05-02 20:08:211580 const GURL gurl_with = accept_ch_with_lifetime_url();
1581 const GURL gurl_without = accept_ch_without_lifetime_url();
Tarun Bansala61f0f62017-10-24 23:53:051582 base::HistogramTester histogram_tester;
1583 ContentSettingsForOneType host_settings;
1584
1585 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451586 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051587 &host_settings);
1588 EXPECT_EQ(0u, host_settings.size());
1589
Tarun Bansal9a7051f2018-07-10 18:30:051590 // Fetching |gurl_with| should persist the request for client hints.
1591 ui_test_utils::NavigateToURL(browser(), gurl_with);
Tarun Bansala61f0f62017-10-24 23:53:051592 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1593 content::FetchHistogramsFromChildProcesses();
1594 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Maks Orlovichf0a2eed2020-05-02 20:08:211595 base::RunLoop().RunUntilIdle();
Tarun Bansala61f0f62017-10-24 23:53:051596
Yoav Weissd33bacb2020-03-12 06:42:211597 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1598 expected_client_hints_number, 1);
Tarun Bansal9a7051f2018-07-10 18:30:051599 // |gurl_with| tries to set client hints persist duration to 3600 seconds.
Tarun Bansala61f0f62017-10-24 23:53:051600 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1601 3600 * 1000, 1);
Tarun Bansala61f0f62017-10-24 23:53:051602
1603 // Clients hints preferences for one origin should be persisted.
1604 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451605 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051606 &host_settings);
1607 EXPECT_EQ(1u, host_settings.size());
1608
Tarun Bansala0c1fc32018-10-03 16:14:521609 // Block the cookies: Client hints should be attached.
Tarun Bansala61f0f62017-10-24 23:53:051610 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051611 ->SetContentSettingDefaultScope(gurl_without, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451612 ContentSettingsType::COOKIES,
Tarun Bansala61f0f62017-10-24 23:53:051613 std::string(), CONTENT_SETTING_BLOCK);
1614
Tarun Bansal229647bd002018-02-27 17:33:361615 SetClientHintExpectationsOnMainFrame(true);
1616 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051617 ui_test_utils::NavigateToURL(browser(),
1618 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361619
Mike West2fddeeb72019-02-15 11:29:481620 // The user agent hint is attached to all three requests:
1621 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461622 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481623
Yoav Weissd33bacb2020-03-12 06:42:211624 // Expected number of hints attached to the image request, and the same number
1625 // to the main frame request.
1626 EXPECT_EQ(expected_client_hints_number * 2,
1627 count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051628
1629 // Clear settings.
1630 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451631 ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
Tarun Bansala61f0f62017-10-24 23:53:051632}
1633
1634// Ensure that when the JavaScript is blocked, client hint preferences are not
1635// persisted.
Tarun Bansal9a7051f2018-07-10 18:30:051636IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051637 ClientHintsLifetimeNotPersistedJavaScriptBlocked) {
1638 ContentSettingsForOneType host_settings;
1639
1640 // Start a navigation. This navigation makes it possible to block JavaScript
1641 // later.
1642 ui_test_utils::NavigateToURL(browser(),
1643 without_accept_ch_without_lifetime_url());
1644
Tarun Bansal9a7051f2018-07-10 18:30:051645 const GURL gurl =
1646 GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
1647 : accept_ch_with_lifetime_url();
1648
Tarun Bansala61f0f62017-10-24 23:53:051649 // Block the JavaScript: Client hint preferences should not be persisted.
1650 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051651 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451652 ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051653 std::string(), CONTENT_SETTING_BLOCK);
1654 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1655 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451656 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051657 &host_settings);
1658 EXPECT_EQ(0u, host_settings.size());
Tarun Bansalc211d8b2018-03-19 19:21:581659 VerifyContentSettingsNotNotified();
Tarun Bansala61f0f62017-10-24 23:53:051660
1661 // Allow the JavaScript: Client hint preferences should be persisted.
1662 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051663 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451664 ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051665 std::string(), CONTENT_SETTING_ALLOW);
1666 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
1667 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451668 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051669 &host_settings);
1670 EXPECT_EQ(1u, host_settings.size());
Tarun Bansal593790112018-03-20 04:53:341671
1672 // Clear settings.
1673 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451674 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:051675}
1676
1677// Ensure that when the JavaScript is blocked, persisted client hints are not
1678// attached to the request headers.
Maks Orlovichf0a2eed2020-05-02 20:08:211679IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansala61f0f62017-10-24 23:53:051680 ClientHintsLifetimeNotAttachedJavaScriptBlocked) {
Maks Orlovichf0a2eed2020-05-02 20:08:211681 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:051682
Tarun Bansala61f0f62017-10-24 23:53:051683 base::HistogramTester histogram_tester;
1684 ContentSettingsForOneType host_settings;
1685
1686 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451687 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051688 &host_settings);
1689 EXPECT_EQ(0u, host_settings.size());
1690
1691 // Fetching accept_ch_with_lifetime_url() should persist the request for
1692 // client hints.
Tarun Bansal9a7051f2018-07-10 18:30:051693 ui_test_utils::NavigateToURL(browser(), gurl);
Tarun Bansala61f0f62017-10-24 23:53:051694 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1695 content::FetchHistogramsFromChildProcesses();
1696 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
Mike West2fddeeb72019-02-15 11:29:481697 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461698 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051699
Yoav Weissd33bacb2020-03-12 06:42:211700 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1701 expected_client_hints_number, 1);
Tarun Bansala61f0f62017-10-24 23:53:051702 // accept_ch_with_lifetime_url() tries to set client hints persist duration to
1703 // 3600 seconds.
1704 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1705 3600 * 1000, 1);
1706 base::RunLoop().RunUntilIdle();
1707
1708 // Clients hints preferences for one origin should be persisted.
1709 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451710 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansala61f0f62017-10-24 23:53:051711 &host_settings);
1712 EXPECT_EQ(1u, host_settings.size());
1713
Changwan Ryu434c3a32019-07-30 23:42:581714 // Block JavaScript via WebPreferences: Client hints should not be attached.
1715 SetJsEnabledForActiveView(false);
1716
1717 SetClientHintExpectationsOnMainFrame(false);
1718 SetClientHintExpectationsOnSubresources(false);
1719 ui_test_utils::NavigateToURL(browser(),
1720 without_accept_ch_without_lifetime_url());
1721
1722 EXPECT_EQ(0u, count_client_hints_headers_seen());
1723 VerifyContentSettingsNotNotified();
1724 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461725 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Changwan Ryu434c3a32019-07-30 23:42:581726
1727 SetJsEnabledForActiveView(true);
1728
1729 // Block JavaScript via ContentSetting: Client hints should not be attached.
Tarun Bansala61f0f62017-10-24 23:53:051730 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1731 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
Darin Fisher42f5e7d2019-10-30 07:15:451732 GURL(), ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051733 std::string(), CONTENT_SETTING_BLOCK);
1734 ui_test_utils::NavigateToURL(browser(),
1735 without_accept_ch_without_lifetime_url());
1736 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581737 VerifyContentSettingsNotNotified();
Mike West2fddeeb72019-02-15 11:29:481738 EXPECT_EQ(1u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461739 EXPECT_EQ(1u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051740
Changwan Ryu434c3a32019-07-30 23:42:581741 // Allow JavaScript: Client hints should now be attached.
Tarun Bansala61f0f62017-10-24 23:53:051742 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1743 ->SetContentSettingDefaultScope(without_accept_ch_without_lifetime_url(),
Darin Fisher42f5e7d2019-10-30 07:15:451744 GURL(), ContentSettingsType::JAVASCRIPT,
Tarun Bansala61f0f62017-10-24 23:53:051745 std::string(), CONTENT_SETTING_ALLOW);
1746
Tarun Bansal229647bd002018-02-27 17:33:361747 SetClientHintExpectationsOnMainFrame(true);
1748 SetClientHintExpectationsOnSubresources(true);
Tarun Bansala61f0f62017-10-24 23:53:051749 ui_test_utils::NavigateToURL(browser(),
1750 without_accept_ch_without_lifetime_url());
Tarun Bansal79df868e2018-03-20 23:01:361751
Mike West2fddeeb72019-02-15 11:29:481752 // The user agent hint is attached to all three requests:
1753 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461754 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481755
Yoav Weissd33bacb2020-03-12 06:42:211756 // Expected number of hints attached to the image request, and the same number
1757 // to the main frame request.
1758 EXPECT_EQ(expected_client_hints_number * 2,
1759 count_client_hints_headers_seen());
Tarun Bansala61f0f62017-10-24 23:53:051760
1761 // Clear settings.
1762 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451763 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansala61f0f62017-10-24 23:53:051764}
1765
Tarun Bansal73502f92019-04-16 21:21:191766// Test that if the content settings are malformed, then the browser does not
1767// crash.
1768IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
1769 ClientHintsMalformedContentSettings) {
1770 ContentSettingsForOneType client_hints_settings;
1771 HostContentSettingsMap* host_content_settings_map =
1772 HostContentSettingsMapFactory::GetForProfile(browser()->profile());
1773
1774 // Add setting for the host.
1775 std::unique_ptr<base::ListValue> expiration_times_list =
1776 std::make_unique<base::ListValue>();
1777 expiration_times_list->AppendInteger(42 /* client hint value */);
1778 auto expiration_times_dictionary = std::make_unique<base::DictionaryValue>();
1779 expiration_times_dictionary->SetList("client_hints",
1780 std::move(expiration_times_list));
Aaron Tagliaboschi3c96a682019-10-29 18:10:281781 expiration_times_dictionary->SetDouble(
1782 "expiration_time",
1783 (base::Time::Now() + base::TimeDelta::FromDays(1)).ToDoubleT());
Tarun Bansal73502f92019-04-16 21:21:191784 host_content_settings_map->SetWebsiteSettingDefaultScope(
1785 without_accept_ch_without_lifetime_url(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451786 ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal73502f92019-04-16 21:21:191787 std::make_unique<base::Value>(expiration_times_dictionary->Clone()));
1788
1789 // Reading the settings should now return one setting.
1790 host_content_settings_map->GetSettingsForOneType(
Darin Fisher42f5e7d2019-10-30 07:15:451791 ContentSettingsType::CLIENT_HINTS, std::string(), &client_hints_settings);
Tarun Bansal73502f92019-04-16 21:21:191792 EXPECT_EQ(1U, client_hints_settings.size());
1793
1794 SetClientHintExpectationsOnMainFrame(false);
1795 SetClientHintExpectationsOnSubresources(false);
1796 ui_test_utils::NavigateToURL(browser(),
1797 without_accept_ch_without_lifetime_url());
1798}
1799
Tarun Bansal229647bd002018-02-27 17:33:361800// Ensure that when the JavaScript is blocked, client hints requested using
Tarun Bansal3f343d7c2018-03-02 18:48:001801// Accept-CH are not attached to the request headers for subresources.
Tarun Bansal9a7051f2018-07-10 18:30:051802IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansal229647bd002018-02-27 17:33:361803 ClientHintsNoLifetimeScriptNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051804 const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
1805 : accept_ch_with_lifetime_url();
1806
Tarun Bansal1965b042017-09-07 04:59:191807 base::HistogramTester histogram_tester;
1808 ContentSettingsForOneType host_settings;
1809
1810 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451811 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191812 &host_settings);
1813 EXPECT_EQ(0u, host_settings.size());
1814
Tarun Bansal3f343d7c2018-03-02 18:48:001815 // Block the Javascript: Client hints should not be attached.
1816 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361817 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1818 ->SetContentSettingDefaultScope(
1819 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451820 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361821 CONTENT_SETTING_BLOCK);
1822 ui_test_utils::NavigateToURL(browser(),
1823 accept_ch_without_lifetime_img_localhost());
Mike West2fddeeb72019-02-15 11:29:481824 EXPECT_EQ(0u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461825 EXPECT_EQ(0u, count_ua_mobile_client_hints_headers_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001826 EXPECT_EQ(0u, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361827 EXPECT_EQ(1u, third_party_request_count_seen());
Tarun Bansal3f343d7c2018-03-02 18:48:001828 EXPECT_EQ(0u, third_party_client_hints_count_seen());
Tarun Bansal1965b042017-09-07 04:59:191829
Tarun Bansal3f343d7c2018-03-02 18:48:001830 // Allow the Javascript: Client hints should now be attached.
Tarun Bansal229647bd002018-02-27 17:33:361831 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1832 ->SetContentSettingDefaultScope(
1833 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451834 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361835 CONTENT_SETTING_ALLOW);
Tarun Bansal1965b042017-09-07 04:59:191836
Tarun Bansal229647bd002018-02-27 17:33:361837 SetClientHintExpectationsOnSubresources(true);
1838 ui_test_utils::NavigateToURL(browser(),
1839 accept_ch_without_lifetime_img_localhost());
Tarun Bansal3f343d7c2018-03-02 18:48:001840
Mike West2fddeeb72019-02-15 11:29:481841 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461842 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:211843 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361844 EXPECT_EQ(2u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461845 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansalc211d8b2018-03-19 19:21:581846 VerifyContentSettingsNotNotified();
Tarun Bansal1965b042017-09-07 04:59:191847
Tarun Bansal229647bd002018-02-27 17:33:361848 // Clear settings.
1849 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451850 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansal1965b042017-09-07 04:59:191851
Tarun Bansal229647bd002018-02-27 17:33:361852 // Block the Javascript again: Client hints should not be attached.
Tarun Bansal3f343d7c2018-03-02 18:48:001853 SetClientHintExpectationsOnSubresources(false);
Tarun Bansal229647bd002018-02-27 17:33:361854 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
1855 ->SetContentSettingDefaultScope(
1856 accept_ch_without_lifetime_img_localhost(), GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451857 ContentSettingsType::JAVASCRIPT, std::string(),
Tarun Bansal229647bd002018-02-27 17:33:361858 CONTENT_SETTING_BLOCK);
1859 ui_test_utils::NavigateToURL(browser(),
1860 accept_ch_without_lifetime_img_localhost());
Mike West2fddeeb72019-02-15 11:29:481861 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461862 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:211863 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansal229647bd002018-02-27 17:33:361864 EXPECT_EQ(3u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461865 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341866
1867 // Clear settings.
1868 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451869 ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
Tarun Bansal229647bd002018-02-27 17:33:361870}
1871
Tarun Bansala0c1fc32018-10-03 16:14:521872// Ensure that when the cookies is blocked, client hints are attached to the
Tarun Bansal3f343d7c2018-03-02 18:48:001873// request headers.
Tarun Bansal9a7051f2018-07-10 18:30:051874IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
Tarun Bansala0c1fc32018-10-03 16:14:521875 ClientHintsLifetimeCookiesNotAllowed) {
Tarun Bansal9a7051f2018-07-10 18:30:051876 const GURL gurl = GetParam()
1877 ? http_equiv_accept_ch_without_lifetime_img_localhost()
1878 : accept_ch_without_lifetime_img_localhost();
1879
Tarun Bansal229647bd002018-02-27 17:33:361880 base::HistogramTester histogram_tester;
1881 ContentSettingsForOneType host_settings;
1882 scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
1883 CookieSettingsFactory::GetForProfile(browser()->profile());
1884
Tarun Bansal1965b042017-09-07 04:59:191885 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451886 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal1965b042017-09-07 04:59:191887 &host_settings);
1888 EXPECT_EQ(0u, host_settings.size());
1889
Tarun Bansal229647bd002018-02-27 17:33:361890 // Block cookies.
1891 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Tarun Bansal9a7051f2018-07-10 18:30:051892 ->SetContentSettingDefaultScope(gurl, GURL(),
Darin Fisher42f5e7d2019-10-30 07:15:451893 ContentSettingsType::COOKIES,
Tarun Bansal9a7051f2018-07-10 18:30:051894 std::string(), CONTENT_SETTING_BLOCK);
Tarun Bansal229647bd002018-02-27 17:33:361895 base::RunLoop().RunUntilIdle();
1896
Tarun Bansal229647bd002018-02-27 17:33:361897 SetClientHintExpectationsOnSubresources(true);
Tarun Bansal9a7051f2018-07-10 18:30:051898 ui_test_utils::NavigateToURL(browser(), gurl);
Mike West2fddeeb72019-02-15 11:29:481899 EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461900 EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:211901 EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
Tarun Bansala0c1fc32018-10-03 16:14:521902 EXPECT_EQ(1u, third_party_request_count_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461903 EXPECT_EQ(2u, third_party_client_hints_count_seen());
Tarun Bansal593790112018-03-20 04:53:341904
1905 // Clear settings.
1906 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451907 ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
Tarun Bansal1965b042017-09-07 04:59:191908}
1909
Tarun Bansal3ce0ca42018-06-25 22:52:221910// Verify that client hints are sent in the incognito profiles, and server
1911// client hint opt-ins are honored within the incognito profile.
Maks Orlovichf0a2eed2020-05-02 20:08:211912IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
Tarun Bansal3ce0ca42018-06-25 22:52:221913 ClientHintsLifetimeFollowedByNoClientHintIncognito) {
Maks Orlovichf0a2eed2020-05-02 20:08:211914 const GURL gurl = accept_ch_with_lifetime_url();
Tarun Bansal9a7051f2018-07-10 18:30:051915
Tarun Bansal3ce0ca42018-06-25 22:52:221916 base::HistogramTester histogram_tester;
1917 Browser* incognito = CreateIncognitoBrowser();
1918 ContentSettingsForOneType host_settings;
1919
1920 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451921 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3ce0ca42018-06-25 22:52:221922 &host_settings);
1923 EXPECT_EQ(0u, host_settings.size());
1924
Tarun Bansal9a7051f2018-07-10 18:30:051925 // Fetching |gurl| should persist the request for client hints.
1926 ui_test_utils::NavigateToURL(incognito, gurl);
Tarun Bansal3ce0ca42018-06-25 22:52:221927
1928 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
1929
1930 content::FetchHistogramsFromChildProcesses();
1931 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
1932
Yoav Weissd33bacb2020-03-12 06:42:211933 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
1934 expected_client_hints_number, 1);
Tarun Bansal3ce0ca42018-06-25 22:52:221935 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
1936 // seconds.
1937 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
1938 3600 * 1000, 1);
1939 base::RunLoop().RunUntilIdle();
1940
1941 // Clients hints preferences for one origin should be persisted.
1942 HostContentSettingsMapFactory::GetForProfile(incognito->profile())
Darin Fisher42f5e7d2019-10-30 07:15:451943 ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS, std::string(),
Tarun Bansal3ce0ca42018-06-25 22:52:221944 &host_settings);
1945 EXPECT_EQ(1u, host_settings.size());
1946
1947 SetClientHintExpectationsOnMainFrame(true);
1948 SetClientHintExpectationsOnSubresources(true);
1949 ui_test_utils::NavigateToURL(incognito,
1950 without_accept_ch_without_lifetime_url());
1951
Mike West2fddeeb72019-02-15 11:29:481952 // The user agent hint is attached to all three requests:
1953 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461954 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481955
Yoav Weissd33bacb2020-03-12 06:42:211956 // Expected number of hints attached to the image request, and the same number
1957 // to the main frame request.
1958 EXPECT_EQ(expected_client_hints_number * 2,
1959 count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:221960
1961 // Navigate using regular profile. Client hints should not be send.
1962 SetClientHintExpectationsOnMainFrame(false);
1963 SetClientHintExpectationsOnSubresources(false);
1964 ui_test_utils::NavigateToURL(browser(),
1965 without_accept_ch_without_lifetime_url());
1966
Mike West2fddeeb72019-02-15 11:29:481967 // The user agent hint is attached to the two new requests.
1968 EXPECT_EQ(5u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:461969 EXPECT_EQ(5u, count_ua_mobile_client_hints_headers_seen());
Mike West2fddeeb72019-02-15 11:29:481970
1971 // No additional hints are sent.
Yoav Weissd33bacb2020-03-12 06:42:211972 EXPECT_EQ(expected_client_hints_number * 2,
1973 count_client_hints_headers_seen());
Tarun Bansal3ce0ca42018-06-25 22:52:221974}
Tarun Bansalbef6d652018-10-02 18:41:011975
1976class ClientHintsWebHoldbackBrowserTest : public ClientHintsBrowserTest {
1977 public:
1978 ClientHintsWebHoldbackBrowserTest() : ClientHintsBrowserTest() {
1979 ConfigureHoldbackExperiment();
1980 }
1981
1982 net::EffectiveConnectionType web_effective_connection_type_override() const {
1983 return web_effective_connection_type_override_;
1984 }
1985
Mike West2fddeeb72019-02-15 11:29:481986 std::unique_ptr<base::FeatureList> EnabledFeatures() override {
Tarun Bansalbef6d652018-10-02 18:41:011987 base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
1988 const std::string kTrialName = "TrialFoo";
1989 const std::string kGroupName = "GroupFoo"; // Value not used
1990
1991 scoped_refptr<base::FieldTrial> trial =
1992 base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
1993
1994 std::map<std::string, std::string> params;
1995
1996 params["web_effective_connection_type_override"] =
1997 net::GetNameForEffectiveConnectionType(
1998 web_effective_connection_type_override_);
Mike West2fddeeb72019-02-15 11:29:481999 EXPECT_TRUE(
Tarun Bansalbef6d652018-10-02 18:41:012000 base::FieldTrialParamAssociator::GetInstance()
2001 ->AssociateFieldTrialParams(kTrialName, kGroupName, params));
2002
2003 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
Mike West2fddeeb72019-02-15 11:29:482004 feature_list->InitializeFromCommandLine("UserAgentClientHint", "");
Tarun Bansalbef6d652018-10-02 18:41:012005 feature_list->RegisterFieldTrialOverride(
2006 features::kNetworkQualityEstimatorWebHoldback.name,
2007 base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
Mike West2fddeeb72019-02-15 11:29:482008 return feature_list;
Tarun Bansalbef6d652018-10-02 18:41:012009 }
2010
Mike West2fddeeb72019-02-15 11:29:482011 private:
2012 void ConfigureHoldbackExperiment() {}
2013
Tarun Bansalbef6d652018-10-02 18:41:012014 const net::EffectiveConnectionType web_effective_connection_type_override_ =
2015 net::EFFECTIVE_CONNECTION_TYPE_3G;
Tarun Bansalbef6d652018-10-02 18:41:012016};
2017
2018// Make sure that when NetInfo holdback experiment is enabled, the NetInfo APIs
2019// and client hints return the overridden values. Verify that the client hints
2020// are overridden on both main frame and subresource requests.
2021IN_PROC_BROWSER_TEST_F(ClientHintsWebHoldbackBrowserTest,
2022 EffectiveConnectionTypeChangeNotified) {
2023 SetExpectedEffectiveConnectionType(web_effective_connection_type_override());
2024
2025 SetClientHintExpectationsOnMainFrame(false);
2026 SetClientHintExpectationsOnSubresources(true);
2027
2028 base::RunLoop().RunUntilIdle();
2029
2030 EXPECT_TRUE(embedded_test_server()->Start());
2031 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
2032 EXPECT_EQ(0u, count_client_hints_headers_seen());
2033 EXPECT_EQ(0u, third_party_request_count_seen());
2034 EXPECT_EQ(0u, third_party_client_hints_count_seen());
2035
2036 SetClientHintExpectationsOnMainFrame(true);
2037 SetClientHintExpectationsOnSubresources(true);
2038 ui_test_utils::NavigateToURL(
2039 browser(), accept_ch_without_lifetime_with_subresource_url());
2040 base::RunLoop().RunUntilIdle();
2041 content::FetchHistogramsFromChildProcesses();
2042 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
2043
Mike West2fddeeb72019-02-15 11:29:482044 EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
Maks Orlovich5dcc99c2020-02-13 19:07:462045 EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
Yoav Weissd33bacb2020-03-12 06:42:212046 EXPECT_EQ(expected_client_hints_number * 2,
2047 count_client_hints_headers_seen());
Tarun Bansalbef6d652018-10-02 18:41:012048 EXPECT_EQ(0u, third_party_request_count_seen());
2049 EXPECT_EQ(0u, third_party_client_hints_count_seen());
2050}