Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Side by Side Diff: content/browser/browsing_data/clear_site_data_header_observer_browsertest.cc

Issue 2025683003: First experimental implementation of the Clear-Site-Data header (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments, git cl format Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "content/browser/browsing_data/clear_site_data_header_observer.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "components/network_session_configurator/switches.h"
13 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/common/content_switches.h"
16 #include "content/public/test/content_browser_test.h"
17 #include "content/public/test/content_browser_test_utils.h"
18 #include "content/public/test/test_navigation_observer.h"
19 #include "content/shell/browser/shell.h"
20 #include "net/base/escape.h"
21 #include "net/base/url_util.h"
22 #include "net/dns/mock_host_resolver.h"
23 #include "net/test/embedded_test_server/http_request.h"
24 #include "net/test/embedded_test_server/http_response.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "url/origin.h"
27 #include "url/url_constants.h"
28
29 using testing::_;
30
31 namespace content {
32
33 namespace {
34
35 class TestContentBrowserClient : public ContentBrowserClient {
36 public:
37 MOCK_METHOD5(ClearSiteData,
38 void(content::BrowserContext* browser_context,
39 const url::Origin& origin,
40 bool remove_cookies,
41 bool remove_storage,
42 bool remove_cache));
43 };
44
45 // Adds a key=value pair to the url's query.
46 void AddQuery(GURL* url, const std::string& key, const std::string& value) {
47 *url = GURL(url->spec() + (url->has_query() ? "&" : "?") + key + "=" +
48 net::EscapeQueryParamValue(value, false));
49 }
50
51 // A value of the Clear-Site-Data header that requests cookie deletion. Reused
52 // in tests that need a valid header but do not depend on its value.
53 static const char* kClearCookiesHeader = "{ \"types\": [ \"cookies\" ] }";
54
55 } // namespace
56
57 class ClearSiteDataHeaderObserverBrowsertest : public ContentBrowserTest {
58 public:
59 void SetUpCommandLine(base::CommandLine* command_line) override {
60 ContentBrowserTest::SetUpCommandLine(command_line);
61 command_line->AppendSwitch(
62 switches::kEnableExperimentalWebPlatformFeatures);
63
64 // We're redirecting all hosts to localhost even on HTTPS, so we'll get
65 // certificate errors.
66 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
67 }
68
69 void SetUpOnMainThread() override {
70 ContentBrowserTest::SetUpOnMainThread();
71
72 SetBrowserClientForTesting(&test_client_);
73
74 // Set up HTTP and HTTPS test servers that handle all hosts.
75 host_resolver()->AddRule("*", "127.0.0.1");
76
77 embedded_test_server()->RegisterRequestHandler(
78 base::Bind(&ClearSiteDataHeaderObserverBrowsertest::HandleRequest,
79 base::Unretained(this)));
80 ASSERT_TRUE(embedded_test_server()->Start());
81
82 https_server_.reset(new net::EmbeddedTestServer(
83 net::test_server::EmbeddedTestServer::TYPE_HTTPS));
84 https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
85 https_server_->RegisterRequestHandler(
86 base::Bind(&ClearSiteDataHeaderObserverBrowsertest::HandleRequest,
87 base::Unretained(this)));
88 ASSERT_TRUE(https_server_->Start());
89 }
90
91 TestContentBrowserClient* GetContentBrowserClient() { return &test_client_; }
92
93 net::EmbeddedTestServer* https_server() { return https_server_.get(); }
94
95 private:
96 // Handles all requests. If the request url query contains a "header" key,
97 // responds with the "Clear-Site-Data" header of the corresponding value.
98 // If the query contains a "redirect" key, responds with a redirect to a url
99 // given by the corresponding value.
100 //
101 // Example: "https://localhost/?header={}&redirect=example.com" will respond
102 // with headers
103 // Clear-Site-Data: {}
104 // Location: example.com
105 std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
106 const net::test_server::HttpRequest& request) {
107 std::unique_ptr<net::test_server::BasicHttpResponse> response(
108 new net::test_server::BasicHttpResponse());
109
110 std::string value;
111 if (net::GetValueForKeyInQuery(request.GetURL(), "header", &value))
112 response->AddCustomHeader("Clear-Site-Data", value);
113
114 if (net::GetValueForKeyInQuery(request.GetURL(), "redirect", &value)) {
115 response->set_code(net::HTTP_FOUND);
116 response->AddCustomHeader("Location", value);
117 } else {
118 response->set_code(net::HTTP_OK);
119 }
120
121 return std::move(response);
122 }
123
124 TestContentBrowserClient test_client_;
125 std::unique_ptr<net::EmbeddedTestServer> https_server_;
126 std::map<GURL, std::string> headers_;
127 std::map<GURL, GURL> redirects_;
128 };
129
130 // Tests that the header is recognized on the beginning, in the middle, and on
131 // the end of a redirect chain. Each of the three parts of the chain may or
132 // may not send the header, so there are 8 configurations to test.
133 IN_PROC_BROWSER_TEST_F(ClearSiteDataHeaderObserverBrowsertest, Redirect) {
134 GURL base_urls[3] = {
135 https_server()->GetURL("origin1.com", "/"),
136 https_server()->GetURL("origin2.com", "/foo/bar"),
137 https_server()->GetURL("origin3.com", "/index.html"),
138 };
139
140 // Iterate through the configurations. URLs whose index is matched by the mask
141 // will send the header, the others won't.
142 for (int mask = 0; mask < (1 << 3); ++mask) {
143 GURL urls[3];
144
145 // Set up the expectations.
146 for (int i = 0; i < 3; ++i) {
147 urls[i] = base_urls[i];
148 if (mask & (1 << i))
149 AddQuery(&urls[i], "header", kClearCookiesHeader);
150
151 EXPECT_CALL(*GetContentBrowserClient(),
152 ClearSiteData(shell()->web_contents()->GetBrowserContext(),
153 url::Origin(urls[i]), _, _, _))
154 .Times((mask & (1 << i)) ? 1 : 0);
155 }
156
157 // Set up redirects between urls 0 --> 1 --> 2.
158 AddQuery(&urls[1], "redirect", urls[2].spec());
159 AddQuery(&urls[0], "redirect", urls[1].spec());
160
161 // Navigate to the first url of the redirect chain.
162 NavigateToURL(shell(), urls[0]);
163
164 // We reached the end of the redirect chain.
165 EXPECT_EQ(urls[2], shell()->web_contents()->GetURL());
166
167 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
168 }
169 }
170
171 // Tests that the Clear-Site-Data header is ignored for insecure origins.
172 IN_PROC_BROWSER_TEST_F(ClearSiteDataHeaderObserverBrowsertest, Insecure) {
173 // ClearSiteData() should not be called on HTTP.
174 GURL url = embedded_test_server()->GetURL("example.com", "/");
175 AddQuery(&url, "header", kClearCookiesHeader);
176 ASSERT_FALSE(url.SchemeIsCryptographic());
177
178 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _))
179 .Times(0);
180
181 NavigateToURL(shell(), url);
182 }
183
184 // Tests that ClearSiteData() is called for the correct datatypes.
185 IN_PROC_BROWSER_TEST_F(ClearSiteDataHeaderObserverBrowsertest, Types) {
186 GURL base_url = https_server()->GetURL("example.com", "/");
187
188 struct TestCase {
189 const char* value;
190 bool remove_cookies;
191 bool remove_storage;
192 bool remove_cache;
193 } test_cases[] = {
194 {"{ \"types\": [ \"cookies\" ] }", true, false, false},
195 {"{ \"types\": [ \"storage\" ] }", false, true, false},
196 {"{ \"types\": [ \"cache\" ] }", false, false, true},
197 {"{ \"types\": [ \"cookies\", \"storage\" ] }", true, true, false},
198 {"{ \"types\": [ \"cookies\", \"cache\" ] }", true, false, true},
199 {"{ \"types\": [ \"storage\", \"cache\" ] }", false, true, true},
200 {"{ \"types\": [ \"cookies\", \"storage\", \"cache\" ] }", true, true,
201 true},
202 };
203
204 for (const TestCase& test_case : test_cases) {
205 GURL url = base_url;
206 AddQuery(&url, "header", test_case.value);
207
208 EXPECT_CALL(
209 *GetContentBrowserClient(),
210 ClearSiteData(shell()->web_contents()->GetBrowserContext(),
211 url::Origin(url), test_case.remove_cookies,
212 test_case.remove_storage, test_case.remove_cache));
213
214 NavigateToURL(shell(), url);
215
216 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
217 }
218 }
219
220 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698