OLD | NEW |
---|---|
(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_throttle.h" | |
6 | |
7 #include <memory> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/callback.h" | |
11 #include "base/command_line.h" | |
12 #include "content/public/browser/content_browser_client.h" | |
13 #include "content/public/browser/web_contents.h" | |
14 #include "content/public/common/content_switches.h" | |
15 #include "content/public/test/content_browser_test.h" | |
16 #include "content/public/test/content_browser_test_utils.h" | |
17 #include "content/public/test/test_navigation_observer.h" | |
18 #include "content/shell/browser/shell.h" | |
19 #include "net/dns/mock_host_resolver.h" | |
20 #include "net/test/embedded_test_server/http_request.h" | |
21 #include "net/test/embedded_test_server/http_response.h" | |
22 #include "testing/gmock/include/gmock/gmock.h" | |
23 #include "url/origin.h" | |
24 #include "url/url_constants.h" | |
25 | |
26 using testing::_; | |
27 | |
28 namespace content { | |
29 | |
30 namespace { | |
31 | |
32 class TestContentBrowserClient : public ContentBrowserClient { | |
33 public: | |
34 MOCK_METHOD5(ClearSiteData, void( | |
35 content::BrowserContext* browser_context, const url::Origin& origin, | |
36 bool remove_cookies, bool remove_storage, bool remove_cache)); | |
37 }; | |
38 | |
39 } // namespace | |
40 | |
41 | |
42 class ClearSiteDataThrottleBrowsertest : public ContentBrowserTest { | |
43 public: | |
44 void SetUpCommandLine(base::CommandLine* command_line) override { | |
45 command_line->AppendSwitch( | |
46 switches::kEnableExperimentalWebPlatformFeatures); | |
47 } | |
48 | |
49 void SetUpOnMainThread() override { | |
50 SetBrowserClientForTesting(&test_client_); | |
51 | |
52 // Header to be served by default. | |
53 SetHeaderValue("{ \"types\": [ \"cookies\" ] }"); | |
54 | |
55 // Run three HTTPS servers, each serving 127.0.0.1 on a different port. | |
Mike West
2016/06/20 07:57:38
Please add some tests that test the registrable do
msramek
2016/07/15 16:47:39
Done.
I was originally avoiding host_resolver(),
| |
56 origin1_server_.reset(new net::EmbeddedTestServer( | |
57 net::test_server::EmbeddedTestServer::TYPE_HTTPS)); | |
58 origin1_server_->RegisterRequestHandler( | |
59 base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequestForOrigin1, | |
60 base::Unretained(this))); | |
61 | |
62 origin2_server_.reset(new net::EmbeddedTestServer( | |
63 net::test_server::EmbeddedTestServer::TYPE_HTTPS)); | |
64 origin2_server_->RegisterRequestHandler( | |
65 base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequestForOrigin2, | |
66 base::Unretained(this))); | |
67 | |
68 origin3_server_.reset(new net::EmbeddedTestServer( | |
69 net::test_server::EmbeddedTestServer::TYPE_HTTPS)); | |
70 origin3_server_->RegisterRequestHandler( | |
71 base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequestForOrigin3, | |
72 base::Unretained(this))); | |
73 | |
74 ASSERT_TRUE(origin1_server_->Start()); | |
75 ASSERT_TRUE(origin2_server_->Start()); | |
76 ASSERT_TRUE(origin3_server_->Start()); | |
77 } | |
78 | |
79 // Getters for the testing server origins, i.e. http(s)://127.0.0.1:<port>. | |
80 GURL origin1() { return origin1_server_->base_url(); } | |
81 GURL origin2() { return origin2_server_->base_url(); } | |
82 GURL origin3() { return origin3_server_->base_url(); } | |
83 | |
84 // Defines which of the three origins should send the Clear-Site-Data header. | |
85 // This is used for testing of the redirect chain where either the start, | |
86 // middle, or end of the chain sends the header. | |
Mike West
2016/06/20 07:57:38
What about when two (or all three) send the header
msramek
2016/07/15 16:47:39
Added tests for that.
I'll implement the serializ
| |
87 void SetOriginThatShouldSendClearSiteData(const GURL& origin) { | |
88 origin_that_should_send_clear_site_data_ = origin; | |
89 } | |
90 | |
91 // Finds out which of the three server origins should send Clear-Site-Data. | |
92 GURL OriginThatShouldSendClearSiteData() { | |
93 return origin_that_should_send_clear_site_data_; | |
94 } | |
95 | |
96 // Sets the desired Clear-Site-Data header value to be sent by the servers. | |
97 void SetHeaderValue(const std::string& value) { | |
98 header_value_ = value; | |
99 } | |
100 | |
101 TestContentBrowserClient* GetContentBrowserClient() { | |
102 return &test_client_; | |
103 } | |
104 | |
105 // Navigates over the redirect chain origin1()->origin2()->origin3(), sending | |
106 // the Clear-Site-Data header on |origin_to_test|. | |
107 void TestRedirectChainWithHeaderOn(const GURL& origin_to_test) { | |
108 SCOPED_TRACE( | |
109 "ClearSiteData() should have been called for " + origin_to_test.spec()); | |
110 SetOriginThatShouldSendClearSiteData(origin_to_test); | |
111 | |
112 // The |tested_origin| is expected to call ClearSiteData(). The other two | |
113 // origins are not expected to call it. | |
114 const GURL origins[] = {origin1(), origin2(), origin3()}; | |
115 for (const GURL& origin : origins) { | |
116 EXPECT_CALL( | |
117 *GetContentBrowserClient(), | |
118 ClearSiteData( | |
119 shell()->web_contents()->GetBrowserContext(), | |
120 url::Origin(origin), | |
121 _, _, _)).Times(origin == origin_to_test ? 1 : 0); | |
122 } | |
123 | |
124 // Navigate to the first origin of the redirect chain. | |
125 TestNavigationObserver observer(shell()->web_contents()); | |
126 NavigateToURL(shell(), origin1()); | |
127 observer.Wait(); | |
128 | |
129 // We reached the end of the redirect chain. | |
130 EXPECT_EQ(origin3(), shell()->web_contents()->GetURL()); | |
131 } | |
132 | |
133 private: | |
134 // Requests to origin1() always redirect to origin2(). | |
135 std::unique_ptr<net::test_server::HttpResponse> HandleRequestForOrigin1( | |
136 const net::test_server::HttpRequest& request) { | |
137 std::unique_ptr<net::test_server::BasicHttpResponse> response( | |
138 new net::test_server::BasicHttpResponse()); | |
139 response->set_code(net::HTTP_FOUND); | |
140 response->AddCustomHeader( | |
141 "Location", origin2_server_->base_url().spec()); | |
142 | |
143 if (origin1() == OriginThatShouldSendClearSiteData()) { | |
144 response->AddCustomHeader("Clear-Site-Data", header_value_); | |
145 } | |
146 | |
147 return std::move(response); | |
148 } | |
149 | |
150 // Requests to origin2() always redirect to origin3(). | |
151 std::unique_ptr<net::test_server::HttpResponse> HandleRequestForOrigin2( | |
152 const net::test_server::HttpRequest& request) { | |
153 std::unique_ptr<net::test_server::BasicHttpResponse> response( | |
154 new net::test_server::BasicHttpResponse()); | |
155 response->set_code(net::HTTP_FOUND); | |
156 response->AddCustomHeader( | |
157 "Location", origin3_server_->base_url().spec()); | |
158 | |
159 if (origin2() == OriginThatShouldSendClearSiteData()) | |
160 response->AddCustomHeader("Clear-Site-Data", header_value_); | |
161 | |
162 return std::move(response); | |
163 } | |
164 | |
165 // Requests to origin3() always successfully return an empty content. | |
166 std::unique_ptr<net::test_server::HttpResponse> HandleRequestForOrigin3( | |
167 const net::test_server::HttpRequest& request) { | |
168 std::unique_ptr<net::test_server::BasicHttpResponse> response( | |
169 new net::test_server::BasicHttpResponse()); | |
170 response->set_code(net::HTTP_OK); | |
171 | |
172 if (origin3() == OriginThatShouldSendClearSiteData()) | |
173 response->AddCustomHeader("Clear-Site-Data", header_value_); | |
174 | |
175 return std::move(response); | |
176 } | |
177 | |
178 TestContentBrowserClient test_client_; | |
179 std::unique_ptr<net::EmbeddedTestServer> origin1_server_; | |
180 std::unique_ptr<net::EmbeddedTestServer> origin2_server_; | |
181 std::unique_ptr<net::EmbeddedTestServer> origin3_server_; | |
182 GURL origin_that_should_send_clear_site_data_; | |
183 std::string header_value_; | |
184 }; | |
185 | |
186 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, RedirectStart) { | |
187 TestRedirectChainWithHeaderOn(origin1()); | |
188 } | |
189 | |
190 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, RedirectMiddle) { | |
191 TestRedirectChainWithHeaderOn(origin2()); | |
192 } | |
193 | |
194 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, RedirectEnd) { | |
195 TestRedirectChainWithHeaderOn(origin3()); | |
196 } | |
197 | |
198 // Tests that the Clear-Site-Data header is ignored for insecure origins. | |
199 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, Insecure) { | |
200 // ClearSiteData() should not be called for origin3() ... | |
201 SetOriginThatShouldSendClearSiteData(origin3()); | |
202 EXPECT_CALL( | |
203 *GetContentBrowserClient(), ClearSiteData(_, _, _, _, _)).Times(0); | |
204 | |
205 // ... when we navigate to it on HTTP instead of HTTPS. | |
206 GURL::Replacements replace_scheme; | |
207 std::string new_scheme = url::kHttpScheme; | |
208 replace_scheme.SetSchemeStr(new_scheme); | |
209 GURL origin3_on_http = origin3().ReplaceComponents(replace_scheme); | |
210 ASSERT_TRUE(origin3_on_http.is_valid()); | |
211 ASSERT_TRUE(!origin3_on_http.SchemeIsCryptographic()); | |
212 | |
213 TestNavigationObserver observer(shell()->web_contents()); | |
214 NavigateToURL(shell(), origin3_on_http); | |
215 observer.Wait(); | |
216 } | |
217 | |
218 // Tests that ClearSiteData() is called for the correct datatypes. | |
219 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, Types) { | |
220 SetOriginThatShouldSendClearSiteData(origin3()); | |
221 | |
222 struct TestCase { | |
223 const char* value; | |
224 bool remove_cookies; | |
225 bool remove_storage; | |
226 bool remove_cache; | |
227 } test_cases[] = { | |
228 { "{ \"types\": [ \"cookies\" ] }", true, false, false}, | |
229 { "{ \"types\": [ \"storage\" ] }", false, true, false}, | |
230 { "{ \"types\": [ \"cache\" ] }", false, false, true}, | |
231 { "{ \"types\": [ \"cookies\", \"storage\" ] }", true, true, false}, | |
232 { "{ \"types\": [ \"cookies\", \"cache\" ] }", true, false, true}, | |
233 { "{ \"types\": [ \"storage\", \"cache\" ] }", false, true, true}, | |
234 { "{ \"types\": [ \"cookies\", \"storage\", \"cache\" ] }", | |
235 true, true, true}, | |
236 }; | |
237 | |
238 for (const TestCase& test_case : test_cases) { | |
239 SetHeaderValue(test_case.value); | |
240 | |
241 EXPECT_CALL( | |
242 *GetContentBrowserClient(), | |
243 ClearSiteData( | |
244 shell()->web_contents()->GetBrowserContext(), | |
245 url::Origin(origin3()), | |
246 test_case.remove_cookies, | |
247 test_case.remove_storage, | |
248 test_case.remove_cache)); | |
249 | |
250 TestNavigationObserver observer(shell()->web_contents()); | |
251 NavigateToURL(shell(), origin3()); | |
252 observer.Wait(); | |
253 } | |
254 } | |
255 | |
256 } // namespace content | |
OLD | NEW |