blob: 419e74ec0c0f959573ba419cbcee9fd96fc36e9a [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
5#include "base/command_line.h"
6#include "base/test/histogram_tester.h"
Tarun Bansal1965b042017-09-07 04:59:197#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:168#include "chrome/browser/metrics/subprocess_metrics_provider.h"
9#include "chrome/browser/net/url_request_mock_util.h"
10#include "chrome/browser/profiles/profile.h"
Tarun Bansal1965b042017-09-07 04:59:1911#include "chrome/browser/ui/browser.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1612#include "chrome/test/base/in_process_browser_test.h"
13#include "chrome/test/base/ui_test_utils.h"
Tarun Bansal1965b042017-09-07 04:59:1914#include "components/content_settings/core/browser/host_content_settings_map.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1615#include "content/public/browser/browser_thread.h"
Tarun Bansal1965b042017-09-07 04:59:1916#include "content/public/common/browser_side_navigation_policy.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1617#include "content/public/common/content_switches.h"
18#include "content/public/test/browser_test_utils.h"
19#include "content/public/test/test_utils.h"
20#include "net/test/embedded_test_server/embedded_test_server.h"
Tarun Bansal1965b042017-09-07 04:59:1921#include "net/test/embedded_test_server/http_request.h"
Tarun Bansal0b8b7afd2017-08-25 03:52:1622
23class ClientHintsBrowserTest : public InProcessBrowserTest {
24 public:
25 ClientHintsBrowserTest()
Tarun Bansal1965b042017-09-07 04:59:1926 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
27 expect_client_hints_(false),
28 count_client_hints_headers_seen_(0) {
Tarun Bansal0b8b7afd2017-08-25 03:52:1629 https_server_.ServeFilesFromSourceDirectory(
30 "chrome/test/data/client_hints");
Tarun Bansal1965b042017-09-07 04:59:1931
32 https_server_.RegisterRequestMonitor(
33 base::Bind(&ClientHintsBrowserTest::MonitorResourceRequest,
34 base::Unretained(this)));
35
Tarun Bansal0b8b7afd2017-08-25 03:52:1636 EXPECT_TRUE(https_server_.Start());
37
Tarun Bansal1965b042017-09-07 04:59:1938 accept_ch_with_lifetime_url_ =
39 https_server_.GetURL("/accept_ch_with_lifetime.html");
40 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
41 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal0b8b7afd2017-08-25 03:52:1642
Tarun Bansal1965b042017-09-07 04:59:1943 accept_ch_without_lifetime_url_ =
44 https_server_.GetURL("/accept_ch_without_lifetime.html");
45 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsHTTPOrHTTPS());
46 EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
47
48 without_accept_ch_without_lifetime_url_ =
49 https_server_.GetURL("/without_accept_ch_without_lifetime.html");
50 EXPECT_TRUE(without_accept_ch_without_lifetime_url_.SchemeIsHTTPOrHTTPS());
51 EXPECT_TRUE(
52 without_accept_ch_without_lifetime_url_.SchemeIsCryptographic());
Tarun Bansal0b8b7afd2017-08-25 03:52:1653 }
54
55 ~ClientHintsBrowserTest() override {}
56
57 void SetUpOnMainThread() override {
58 content::BrowserThread::PostTask(
59 content::BrowserThread::IO, FROM_HERE,
60 base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
61 }
62
63 void SetUpCommandLine(base::CommandLine* cmd) override {
64 cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
65 }
66
Tarun Bansal1965b042017-09-07 04:59:1967 void SetClientHintExpectations(bool expect_client_hints) {
68 expect_client_hints_ = expect_client_hints;
69 }
Tarun Bansal0b8b7afd2017-08-25 03:52:1670
Tarun Bansal1965b042017-09-07 04:59:1971 // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
72 // headers.
73 const GURL& accept_ch_with_lifetime_url() const {
74 return accept_ch_with_lifetime_url_;
75 }
76
77 // A URL whose response headers include only Accept-CH header.
78 const GURL& accept_ch_without_lifetime_url() const {
79 return accept_ch_without_lifetime_url_;
80 }
81
82 // A URL whose response headers do not include either Accept-CH or
83 // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
84 const GURL& without_accept_ch_without_lifetime_url() const {
85 return without_accept_ch_without_lifetime_url_;
86 }
87
88 size_t count_client_hints_headers_seen() const {
89 return count_client_hints_headers_seen_;
90 }
Tarun Bansal0b8b7afd2017-08-25 03:52:1691
92 private:
Tarun Bansal1965b042017-09-07 04:59:1993 // Called by |https_server_|.
94 void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
95 if (!content::IsBrowserSideNavigationEnabled() ||
96 request.GetURL() != without_accept_ch_without_lifetime_url()) {
97 // When browser side navigation is enabled, client hints are currently not
98 // attached to the main frame request.
99 EXPECT_EQ(expect_client_hints_,
100 request.headers.find("dpr") != request.headers.end());
101 EXPECT_EQ(expect_client_hints_, request.headers.find("viewport-width") !=
102 request.headers.end());
103 }
104 if (request.headers.find("dpr") != request.headers.end())
105 count_client_hints_headers_seen_++;
106
107 if (request.headers.find("viewport-width") != request.headers.end())
108 count_client_hints_headers_seen_++;
109 }
110
Tarun Bansal0b8b7afd2017-08-25 03:52:16111 net::EmbeddedTestServer https_server_;
Tarun Bansal1965b042017-09-07 04:59:19112 GURL accept_ch_with_lifetime_url_;
113 GURL accept_ch_without_lifetime_url_;
114 GURL without_accept_ch_without_lifetime_url_;
115
116 bool expect_client_hints_;
117 size_t count_client_hints_headers_seen_;
Tarun Bansal0b8b7afd2017-08-25 03:52:16118};
119
120// Loads a webpage that requests persisting of client hints. Verifies that
121// the browser receives the mojo notification from the renderer and persists the
122// client hints to the disk.
123IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttps) {
124 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:19125 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16126
127 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
128
129 content::FetchHistogramsFromChildProcesses();
130 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
131
132 // client_hints_url() sets two client hints.
133 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 2, 1);
Tarun Bansal1965b042017-09-07 04:59:19134 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
135 // seconds.
Tarun Bansal0b8b7afd2017-08-25 03:52:16136 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
137 3600 * 1000, 1);
138}
139
140// Loads a webpage that does not request persisting of client hints.
141IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {
142 base::HistogramTester histogram_tester;
Tarun Bansal1965b042017-09-07 04:59:19143 ui_test_utils::NavigateToURL(browser(),
144 without_accept_ch_without_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16145
146 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
147
148 content::FetchHistogramsFromChildProcesses();
149 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
150
151 // no_client_hints_url() does not sets the client hints.
152 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
153 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
154}
155
Tarun Bansal1965b042017-09-07 04:59:19156IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
157 ClientHintsLifetimeFollowedByNoClientHint) {
158 base::HistogramTester histogram_tester;
159 ContentSettingsForOneType host_settings;
160
161 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
162 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
163 &host_settings);
164 EXPECT_EQ(0u, host_settings.size());
165
166 // Fetching accept_ch_with_lifetime_url() should persist the request for
167 // client hints.
168 ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
169
170 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
171
172 content::FetchHistogramsFromChildProcesses();
173 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
174
175 // client_hints_url() sets two client hints.
176 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 2, 1);
177 // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
178 // seconds.
179 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
180 3600 * 1000, 1);
181 base::RunLoop().RunUntilIdle();
182
183 // Clients hints preferences for one origin should be persisted.
184 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
185 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
186 &host_settings);
187 EXPECT_EQ(1u, host_settings.size());
188
189 SetClientHintExpectations(true);
190 ui_test_utils::NavigateToURL(browser(),
191 without_accept_ch_without_lifetime_url());
192 if (content::IsBrowserSideNavigationEnabled()) {
193 // When browser side navigation is enabled, two client hints are attached to
194 // the image request.
195 EXPECT_EQ(2u, count_client_hints_headers_seen());
196 } else {
197 // When browser side navigation is not enabled, two client hints are
198 // attached to both the HTML and the image requests.
199 EXPECT_EQ(4u, count_client_hints_headers_seen());
200 }
201}
202
203IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
204 ClientHintsNoLifetimeFollowedByNoClientHint) {
205 base::HistogramTester histogram_tester;
206 ContentSettingsForOneType host_settings;
207
208 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
209 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
210 &host_settings);
211 EXPECT_EQ(0u, host_settings.size());
212
213 // Fetching accept_ch_without_lifetime_url() should not persist the request
214 // for client hints.
215 ui_test_utils::NavigateToURL(browser(), accept_ch_without_lifetime_url());
216
217 histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
218
219 content::FetchHistogramsFromChildProcesses();
220 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
221
222 histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
223 histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
224 base::RunLoop().RunUntilIdle();
225
226 // Clients hints preferences should not be persisted.
227 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
228 ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
229 &host_settings);
230 EXPECT_EQ(0u, host_settings.size());
231
232 // Next request should not have client hint headers attached.
233 ui_test_utils::NavigateToURL(browser(),
234 without_accept_ch_without_lifetime_url());
235}
236
Tarun Bansal0b8b7afd2017-08-25 03:52:16237// Check the client hints for the given URL in an incognito window.
238// Start incognito browser twice to ensure that client hints prefs are
239// not carried over.
240IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttpsIncognito) {
241 for (size_t i = 0; i < 2; ++i) {
242 base::HistogramTester histogram_tester;
243
244 Browser* incognito = CreateIncognitoBrowser();
Tarun Bansal1965b042017-09-07 04:59:19245 ui_test_utils::NavigateToURL(incognito, accept_ch_with_lifetime_url());
Tarun Bansal0b8b7afd2017-08-25 03:52:16246
247 histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
248
249 content::FetchHistogramsFromChildProcesses();
250 SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
251
Tarun Bansal1965b042017-09-07 04:59:19252 // accept_ch_with_lifetime_url() sets two client hints.
Tarun Bansal0b8b7afd2017-08-25 03:52:16253 histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize", 2, 1);
254
255 // At least one renderer must have been created. All the renderers created
256 // must have read 0 client hints.
257 EXPECT_LE(1u,
258 histogram_tester.GetAllSamples("ClientHints.CountRulesReceived")
259 .size());
260 for (const auto& bucket :
261 histogram_tester.GetAllSamples("ClientHints.CountRulesReceived")) {
262 EXPECT_EQ(0, bucket.min);
263 }
264 // |url| sets client hints persist duration to 3600 seconds.
265 histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
266 3600 * 1000, 1);
267
268 CloseBrowserSynchronously(incognito);
269 }
270}