OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/link_header_support.h" | 5 #include "components/link_header_util/link_header_util.h" |
6 | 6 |
7 #include "base/command_line.h" | |
8 #include "base/logging.h" | 7 #include "base/logging.h" |
9 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
10 #include "content/browser/service_worker/embedded_worker_test_helper.h" | |
11 #include "content/browser/service_worker/service_worker_context_wrapper.h" | |
12 #include "content/browser/service_worker/service_worker_registration.h" | |
13 #include "content/public/browser/resource_request_info.h" | |
14 #include "content/public/common/content_switches.h" | |
15 #include "content/public/test/mock_resource_context.h" | |
16 #include "content/public/test/test_browser_thread_bundle.h" | |
17 #include "net/http/http_response_headers.h" | |
18 #include "net/url_request/url_request_test_job.h" | |
19 #include "net/url_request/url_request_test_util.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
21 | 10 |
22 namespace content { | 11 namespace link_header_util { |
23 | 12 |
24 namespace { | 13 namespace { |
25 | 14 |
| 15 void SplitLinkHeaderForTesting(const std::string& header, |
| 16 std::vector<std::string>* values) { |
| 17 std::vector<StringIteratorPair> values_iterators = SplitLinkHeader(header); |
| 18 values->clear(); |
| 19 for (const auto& pair : values_iterators) |
| 20 values->push_back(std::string(pair.first, pair.second)); |
| 21 } |
| 22 |
| 23 bool ParseLinkHeaderValueForTesting( |
| 24 std::string value, |
| 25 std::string* url, |
| 26 std::unordered_map<std::string, base::Optional<std::string>>* params) { |
| 27 return ParseLinkHeaderValue(value.begin(), value.end(), url, params); |
| 28 } |
| 29 |
26 TEST(LinkHeaderTest, SplitEmpty) { | 30 TEST(LinkHeaderTest, SplitEmpty) { |
27 std::vector<std::string> values; | 31 std::vector<std::string> values; |
28 SplitLinkHeaderForTesting("", &values); | 32 SplitLinkHeaderForTesting("", &values); |
29 ASSERT_EQ(0u, values.size()); | 33 ASSERT_EQ(0u, values.size()); |
30 } | 34 } |
31 | 35 |
32 TEST(LinkHeaderTest, SplitSimple) { | 36 TEST(LinkHeaderTest, SplitSimple) { |
33 std::vector<std::string> values; | 37 std::vector<std::string> values; |
34 SplitLinkHeaderForTesting("hello", &values); | 38 SplitLinkHeaderForTesting("hello", &values); |
35 ASSERT_EQ(1u, values.size()); | 39 ASSERT_EQ(1u, values.size()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 void PrintTo(const SimpleParseTestData& test, std::ostream* os) { | 90 void PrintTo(const SimpleParseTestData& test, std::ostream* os) { |
87 *os << ::testing::PrintToString(test.link); | 91 *os << ::testing::PrintToString(test.link); |
88 } | 92 } |
89 | 93 |
90 class SimpleParseTest : public ::testing::TestWithParam<SimpleParseTestData> {}; | 94 class SimpleParseTest : public ::testing::TestWithParam<SimpleParseTestData> {}; |
91 | 95 |
92 TEST_P(SimpleParseTest, Simple) { | 96 TEST_P(SimpleParseTest, Simple) { |
93 const SimpleParseTestData test = GetParam(); | 97 const SimpleParseTestData test = GetParam(); |
94 | 98 |
95 std::string url; | 99 std::string url; |
96 std::unordered_map<std::string, std::string> params; | 100 std::unordered_map<std::string, base::Optional<std::string>> params; |
97 EXPECT_EQ(test.valid, | 101 EXPECT_EQ(test.valid, |
98 ParseLinkHeaderValueForTesting(test.link, &url, ¶ms)); | 102 ParseLinkHeaderValueForTesting(test.link, &url, ¶ms)); |
99 if (test.valid) { | 103 if (test.valid) { |
100 EXPECT_EQ(test.url, url); | 104 EXPECT_EQ(test.url, url); |
101 EXPECT_EQ(test.rel, params["rel"]); | 105 EXPECT_EQ(test.rel, params["rel"].value_or("")); |
102 EXPECT_EQ(test.as, params["as"]); | 106 EXPECT_EQ(test.as, params["as"].value_or("")); |
103 } | 107 } |
104 } | 108 } |
105 | 109 |
106 // Test data mostly copied from blink::LinkHeaderTest. Expectations for some | 110 // Test data mostly copied from blink::LinkHeaderTest. Expectations for some |
107 // test cases are different though. Mostly because blink::LinkHeader is stricter | 111 // test cases are different though. Mostly because blink::LinkHeader is stricter |
108 // about validity while parsing (primarily things like mismatched quotes), and | 112 // about validity while parsing (primarily things like mismatched quotes), and |
109 // factors in knowledge about semantics of Link headers (parameters that are | 113 // factors in knowledge about semantics of Link headers (parameters that are |
110 // required to have a value if they occur, some parameters are auto-lower-cased, | 114 // required to have a value if they occur, some parameters are auto-lower-cased, |
111 // headers with an "anchor" parameter are rejected by base::LinkHeader). | 115 // headers with an "anchor" parameter are rejected by base::LinkHeader). |
112 // The code this tests purely parses without actually interpreting the data, as | 116 // The code this tests purely parses without actually interpreting the data, as |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 {"<simple.css>; rel=\"", true, "simple.css", "", ""}, | 215 {"<simple.css>; rel=\"", true, "simple.css", "", ""}, |
212 {"simple.css; rel=prefetch", false}, | 216 {"simple.css; rel=prefetch", false}, |
213 {"<simple.css>; rel=prefetch; rel=foobar", true, "simple.css", "prefetch", | 217 {"<simple.css>; rel=prefetch; rel=foobar", true, "simple.css", "prefetch", |
214 ""}, | 218 ""}, |
215 }; | 219 }; |
216 | 220 |
217 INSTANTIATE_TEST_CASE_P(LinkHeaderTest, | 221 INSTANTIATE_TEST_CASE_P(LinkHeaderTest, |
218 SimpleParseTest, | 222 SimpleParseTest, |
219 testing::ValuesIn(simple_parse_tests)); | 223 testing::ValuesIn(simple_parse_tests)); |
220 | 224 |
221 void SaveFoundRegistrationsCallback( | |
222 ServiceWorkerStatusCode expected_status, | |
223 bool* called, | |
224 std::vector<ServiceWorkerRegistrationInfo>* registrations, | |
225 ServiceWorkerStatusCode status, | |
226 const std::vector<ServiceWorkerRegistrationInfo>& result) { | |
227 EXPECT_EQ(expected_status, status); | |
228 *called = true; | |
229 *registrations = result; | |
230 } | |
231 | |
232 ServiceWorkerContextWrapper::GetRegistrationsInfosCallback | |
233 SaveFoundRegistrations( | |
234 ServiceWorkerStatusCode expected_status, | |
235 bool* called, | |
236 std::vector<ServiceWorkerRegistrationInfo>* registrations) { | |
237 *called = false; | |
238 return base::Bind(&SaveFoundRegistrationsCallback, expected_status, called, | |
239 registrations); | |
240 } | |
241 | |
242 class LinkHeaderServiceWorkerTest : public ::testing::Test { | |
243 public: | |
244 LinkHeaderServiceWorkerTest() | |
245 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), | |
246 resource_context_(&request_context_) { | |
247 base::CommandLine::ForCurrentProcess()->AppendSwitch( | |
248 switches::kEnableExperimentalWebPlatformFeatures); | |
249 } | |
250 ~LinkHeaderServiceWorkerTest() override {} | |
251 | |
252 void SetUp() override { | |
253 helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); | |
254 } | |
255 | |
256 void TearDown() override { helper_.reset(); } | |
257 | |
258 ServiceWorkerContextWrapper* context_wrapper() { | |
259 return helper_->context_wrapper(); | |
260 } | |
261 | |
262 void ProcessLinkHeader(const GURL& request_url, | |
263 const std::string& link_header) { | |
264 scoped_ptr<net::URLRequest> request = request_context_.CreateRequest( | |
265 request_url, net::DEFAULT_PRIORITY, &request_delegate_); | |
266 ResourceRequestInfo::AllocateForTesting( | |
267 request.get(), RESOURCE_TYPE_SCRIPT, &resource_context_, | |
268 -1 /* render_process_id */, -1 /* render_view_id */, | |
269 -1 /* render_frame_id */, false /* is_main_frame */, | |
270 false /* parent_is_main_frame */, true /* allow_download */, | |
271 true /* is_async */, false /* is_using_lofi */); | |
272 | |
273 ProcessLinkHeaderForRequest(request.get(), link_header, context_wrapper()); | |
274 base::RunLoop().RunUntilIdle(); | |
275 } | |
276 | |
277 std::vector<ServiceWorkerRegistrationInfo> GetRegistrations() { | |
278 bool called; | |
279 std::vector<ServiceWorkerRegistrationInfo> registrations; | |
280 context_wrapper()->GetAllRegistrations( | |
281 SaveFoundRegistrations(SERVICE_WORKER_OK, &called, ®istrations)); | |
282 base::RunLoop().RunUntilIdle(); | |
283 EXPECT_TRUE(called); | |
284 return registrations; | |
285 } | |
286 | |
287 private: | |
288 TestBrowserThreadBundle thread_bundle_; | |
289 scoped_ptr<EmbeddedWorkerTestHelper> helper_; | |
290 net::TestURLRequestContext request_context_; | |
291 net::TestDelegate request_delegate_; | |
292 MockResourceContext resource_context_; | |
293 }; | |
294 | |
295 TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) { | |
296 ProcessLinkHeader(GURL("https://example.com/foo/bar/"), | |
297 "<../foo.js>; rel=serviceworker"); | |
298 | |
299 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
300 ASSERT_EQ(1u, registrations.size()); | |
301 EXPECT_EQ(GURL("https://example.com/foo/"), registrations[0].pattern); | |
302 EXPECT_EQ(GURL("https://example.com/foo/foo.js"), | |
303 registrations[0].active_version.script_url); | |
304 } | |
305 | |
306 TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) { | |
307 ProcessLinkHeader(GURL("https://example.com/foo/bar/"), | |
308 "<../bar.js>; rel=serviceworker; scope=\"scope#ref\""); | |
309 | |
310 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
311 ASSERT_EQ(1u, registrations.size()); | |
312 EXPECT_EQ(GURL("https://example.com/foo/bar/scope"), | |
313 registrations[0].pattern); | |
314 EXPECT_EQ(GURL("https://example.com/foo/bar.js"), | |
315 registrations[0].active_version.script_url); | |
316 } | |
317 | |
318 TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) { | |
319 ProcessLinkHeader(GURL("https://example.com/foo/bar/"), | |
320 "<bar.js>; rel=serviceworker; " | |
321 "scope=\"https://example.com:443/foo/bar/scope\""); | |
322 | |
323 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
324 ASSERT_EQ(1u, registrations.size()); | |
325 EXPECT_EQ(GURL("https://example.com/foo/bar/scope"), | |
326 registrations[0].pattern); | |
327 EXPECT_EQ(GURL("https://example.com/foo/bar/bar.js"), | |
328 registrations[0].active_version.script_url); | |
329 } | |
330 | |
331 TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeDifferentOrigin) { | |
332 ProcessLinkHeader( | |
333 GURL("https://example.com/foobar/"), | |
334 "<bar.js>; rel=serviceworker; scope=\"https://google.com/scope\""); | |
335 | |
336 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
337 ASSERT_EQ(0u, registrations.size()); | |
338 } | |
339 | |
340 TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) { | |
341 ProcessLinkHeader(GURL("https://example.com/foobar/"), | |
342 "<bar.js>; rel=serviceworker; scope=\"./foo%2Fbar\""); | |
343 | |
344 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
345 ASSERT_EQ(0u, registrations.size()); | |
346 } | |
347 | |
348 TEST_F(LinkHeaderServiceWorkerTest, | |
349 InstallServiceWorker_ScriptUrlEncodedSlash) { | |
350 ProcessLinkHeader(GURL("https://example.com/foobar/"), | |
351 "<foo%2Fbar.js>; rel=serviceworker"); | |
352 | |
353 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
354 ASSERT_EQ(0u, registrations.size()); | |
355 } | |
356 | |
357 TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) { | |
358 ProcessLinkHeader( | |
359 GURL("https://example.com/foobar/"), | |
360 "<https://example.com/bar.js>; rel=serviceworker; scope=foo"); | |
361 | |
362 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
363 ASSERT_EQ(1u, registrations.size()); | |
364 EXPECT_EQ(GURL("https://example.com/foobar/foo"), registrations[0].pattern); | |
365 EXPECT_EQ(GURL("https://example.com/bar.js"), | |
366 registrations[0].active_version.script_url); | |
367 } | |
368 | |
369 TEST_F(LinkHeaderServiceWorkerTest, | |
370 InstallServiceWorker_ScriptDifferentOrigin) { | |
371 ProcessLinkHeader( | |
372 GURL("https://example.com/foobar/"), | |
373 "<https://google.com/bar.js>; rel=serviceworker; scope=foo"); | |
374 | |
375 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
376 ASSERT_EQ(0u, registrations.size()); | |
377 } | |
378 | |
379 TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) { | |
380 ProcessLinkHeader(GURL("https://example.com/foobar/"), | |
381 "<bar.js>; rel=serviceworker; scope=foo, <baz.js>; " | |
382 "rel=serviceworker; scope=scope"); | |
383 | |
384 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
385 ASSERT_EQ(2u, registrations.size()); | |
386 EXPECT_EQ(GURL("https://example.com/foobar/foo"), registrations[0].pattern); | |
387 EXPECT_EQ(GURL("https://example.com/foobar/bar.js"), | |
388 registrations[0].active_version.script_url); | |
389 EXPECT_EQ(GURL("https://example.com/foobar/scope"), registrations[1].pattern); | |
390 EXPECT_EQ(GURL("https://example.com/foobar/baz.js"), | |
391 registrations[1].active_version.script_url); | |
392 } | |
393 | |
394 TEST_F(LinkHeaderServiceWorkerTest, | |
395 InstallServiceWorker_ValidAndInvalidValues) { | |
396 ProcessLinkHeader( | |
397 GURL("https://example.com/foobar/"), | |
398 "<https://google.com/bar.js>; rel=serviceworker; scope=foo, <baz.js>; " | |
399 "rel=serviceworker; scope=scope"); | |
400 | |
401 std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations(); | |
402 ASSERT_EQ(1u, registrations.size()); | |
403 EXPECT_EQ(GURL("https://example.com/foobar/scope"), registrations[0].pattern); | |
404 EXPECT_EQ(GURL("https://example.com/foobar/baz.js"), | |
405 registrations[0].active_version.script_url); | |
406 } | |
407 | |
408 } // namespace | 225 } // namespace |
409 | 226 |
410 } // namespace content | 227 } // namespace link_header_util |
OLD | NEW |