| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "base/files/scoped_temp_dir.h" | 5 #include "base/files/scoped_temp_dir.h" |
| 6 #include "base/logging.h" | 6 #include "base/logging.h" |
| 7 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
| 8 #include "content/browser/browser_thread_impl.h" | 8 #include "content/browser/browser_thread_impl.h" |
| 9 #include "content/browser/service_worker/embedded_worker_registry.h" | 9 #include "content/browser/service_worker/embedded_worker_registry.h" |
| 10 #include "content/browser/service_worker/embedded_worker_test_helper.h" | 10 #include "content/browser/service_worker/embedded_worker_test_helper.h" |
| 11 #include "content/browser/service_worker/service_worker_context_core.h" | 11 #include "content/browser/service_worker/service_worker_context_core.h" |
| 12 #include "content/browser/service_worker/service_worker_disk_cache.h" | 12 #include "content/browser/service_worker/service_worker_disk_cache.h" |
| 13 #include "content/browser/service_worker/service_worker_job_coordinator.h" | 13 #include "content/browser/service_worker/service_worker_job_coordinator.h" |
| 14 #include "content/browser/service_worker/service_worker_registration.h" | 14 #include "content/browser/service_worker/service_worker_registration.h" |
| 15 #include "content/browser/service_worker/service_worker_registration_status.h" | 15 #include "content/browser/service_worker/service_worker_registration_status.h" |
| 16 #include "content/browser/service_worker/service_worker_test_utils.h" | 16 #include "content/browser/service_worker/service_worker_test_utils.h" |
| 17 #include "content/common/service_worker/service_worker_messages.h" | 17 #include "content/common/service_worker/service_worker_messages.h" |
| 18 #include "content/public/test/test_browser_thread_bundle.h" | 18 #include "content/public/test/test_browser_thread_bundle.h" |
| 19 #include "content/public/test/test_utils.h" |
| 19 #include "ipc/ipc_test_sink.h" | 20 #include "ipc/ipc_test_sink.h" |
| 20 #include "net/base/io_buffer.h" | 21 #include "net/base/io_buffer.h" |
| 21 #include "net/base/net_errors.h" | 22 #include "net/base/net_errors.h" |
| 22 #include "net/base/test_completion_callback.h" | 23 #include "net/base/test_completion_callback.h" |
| 23 #include "net/http/http_response_headers.h" | 24 #include "net/http/http_response_headers.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
| 25 | 26 |
| 26 using net::IOBuffer; | 27 using net::IOBuffer; |
| 27 using net::TestCompletionCallback; | 28 using net::TestCompletionCallback; |
| 28 using net::WrappedIOBuffer; | 29 using net::WrappedIOBuffer; |
| 29 | 30 |
| 30 // Unit tests for testing all job registration tasks. | 31 // Unit tests for testing all job registration tasks. |
| 31 namespace content { | 32 namespace content { |
| 32 | 33 |
| 33 namespace { | 34 namespace { |
| 34 | 35 |
| 35 int kMockRenderProcessId = 88; | |
| 36 | |
| 37 void SaveRegistrationCallback( | 36 void SaveRegistrationCallback( |
| 38 ServiceWorkerStatusCode expected_status, | 37 ServiceWorkerStatusCode expected_status, |
| 38 const scoped_refptr<MessageLoopRunner>& runner, |
| 39 bool* called, | 39 bool* called, |
| 40 scoped_refptr<ServiceWorkerRegistration>* registration_out, | 40 scoped_refptr<ServiceWorkerRegistration>* registration_out, |
| 41 ServiceWorkerStatusCode status, | 41 ServiceWorkerStatusCode status, |
| 42 const std::string& status_message, | 42 const std::string& status_message, |
| 43 ServiceWorkerRegistration* registration) { | 43 ServiceWorkerRegistration* registration) { |
| 44 EXPECT_EQ(expected_status, status); | 44 EXPECT_EQ(expected_status, status); |
| 45 *called = true; | 45 *called = true; |
| 46 *registration_out = registration; | 46 *registration_out = registration; |
| 47 runner->Quit(); |
| 47 } | 48 } |
| 48 | 49 |
| 49 void SaveFoundRegistrationCallback( | 50 void SaveFoundRegistrationCallback( |
| 50 ServiceWorkerStatusCode expected_status, | 51 ServiceWorkerStatusCode expected_status, |
| 51 bool* called, | 52 bool* called, |
| 52 scoped_refptr<ServiceWorkerRegistration>* registration, | 53 scoped_refptr<ServiceWorkerRegistration>* registration, |
| 53 ServiceWorkerStatusCode status, | 54 ServiceWorkerStatusCode status, |
| 54 const scoped_refptr<ServiceWorkerRegistration>& result) { | 55 const scoped_refptr<ServiceWorkerRegistration>& result) { |
| 55 EXPECT_EQ(expected_status, status); | 56 EXPECT_EQ(expected_status, status); |
| 56 *called = true; | 57 *called = true; |
| 57 *registration = result; | 58 *registration = result; |
| 58 } | 59 } |
| 59 | 60 |
| 60 // Creates a callback which both keeps track of if it's been called, | 61 // Creates a callback which both keeps track of if it's been called, |
| 61 // as well as the resulting registration. Whent the callback is fired, | 62 // as well as the resulting registration. Whent the callback is fired, |
| 62 // it ensures that the resulting status matches the expectation. | 63 // it ensures that the resulting status matches the expectation. |
| 63 // 'called' is useful for making sure a sychronous callback is or | 64 // 'called' is useful for making sure a sychronous callback is or |
| 64 // isn't called. | 65 // isn't called. |
| 65 ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration( | 66 ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration( |
| 66 ServiceWorkerStatusCode expected_status, | 67 ServiceWorkerStatusCode expected_status, |
| 68 const scoped_refptr<MessageLoopRunner>& runner, |
| 67 bool* called, | 69 bool* called, |
| 68 scoped_refptr<ServiceWorkerRegistration>* registration) { | 70 scoped_refptr<ServiceWorkerRegistration>* registration) { |
| 69 *called = false; | 71 *called = false; |
| 70 return base::Bind( | 72 return base::Bind(&SaveRegistrationCallback, expected_status, runner, called, |
| 71 &SaveRegistrationCallback, expected_status, called, registration); | 73 registration); |
| 72 } | 74 } |
| 73 | 75 |
| 74 ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration( | 76 ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration( |
| 75 ServiceWorkerStatusCode expected_status, | 77 ServiceWorkerStatusCode expected_status, |
| 76 bool* called, | 78 bool* called, |
| 77 scoped_refptr<ServiceWorkerRegistration>* registration) { | 79 scoped_refptr<ServiceWorkerRegistration>* registration) { |
| 78 *called = false; | 80 *called = false; |
| 79 return base::Bind(&SaveFoundRegistrationCallback, | 81 return base::Bind(&SaveFoundRegistrationCallback, |
| 80 expected_status, | 82 expected_status, |
| 81 called, | 83 called, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 95 bool* called) { | 97 bool* called) { |
| 96 *called = false; | 98 *called = false; |
| 97 return base::Bind(&SaveUnregistrationCallback, expected_status, called); | 99 return base::Bind(&SaveUnregistrationCallback, expected_status, called); |
| 98 } | 100 } |
| 99 | 101 |
| 100 } // namespace | 102 } // namespace |
| 101 | 103 |
| 102 class ServiceWorkerJobTest : public testing::Test { | 104 class ServiceWorkerJobTest : public testing::Test { |
| 103 public: | 105 public: |
| 104 ServiceWorkerJobTest() | 106 ServiceWorkerJobTest() |
| 105 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), | 107 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
| 106 render_process_id_(kMockRenderProcessId) {} | |
| 107 | 108 |
| 108 void SetUp() override { | 109 void SetUp() override { |
| 109 helper_.reset( | 110 helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); |
| 110 new EmbeddedWorkerTestHelper(base::FilePath(), render_process_id_)); | |
| 111 } | 111 } |
| 112 | 112 |
| 113 void TearDown() override { helper_.reset(); } | 113 void TearDown() override { helper_.reset(); } |
| 114 | 114 |
| 115 ServiceWorkerContextCore* context() const { return helper_->context(); } | 115 ServiceWorkerContextCore* context() const { return helper_->context(); } |
| 116 | 116 |
| 117 ServiceWorkerJobCoordinator* job_coordinator() const { | 117 ServiceWorkerJobCoordinator* job_coordinator() const { |
| 118 return context()->job_coordinator(); | 118 return context()->job_coordinator(); |
| 119 } | 119 } |
| 120 ServiceWorkerStorage* storage() const { return context()->storage(); } | 120 ServiceWorkerStorage* storage() const { return context()->storage(); } |
| 121 | 121 |
| 122 protected: | 122 protected: |
| 123 scoped_refptr<ServiceWorkerRegistration> RunRegisterJob( | 123 scoped_refptr<ServiceWorkerRegistration> RunRegisterJob( |
| 124 const GURL& pattern, | 124 const GURL& pattern, |
| 125 const GURL& script_url, | 125 const GURL& script_url, |
| 126 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK); | 126 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK); |
| 127 void RunUnregisterJob( | 127 void RunUnregisterJob( |
| 128 const GURL& pattern, | 128 const GURL& pattern, |
| 129 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK); | 129 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK); |
| 130 scoped_refptr<ServiceWorkerRegistration> FindRegistrationForPattern( | 130 scoped_refptr<ServiceWorkerRegistration> FindRegistrationForPattern( |
| 131 const GURL& pattern, | 131 const GURL& pattern, |
| 132 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK); | 132 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK); |
| 133 scoped_ptr<ServiceWorkerProviderHost> CreateControllee(); | 133 scoped_ptr<ServiceWorkerProviderHost> CreateControllee(); |
| 134 | 134 |
| 135 TestBrowserThreadBundle browser_thread_bundle_; | 135 TestBrowserThreadBundle browser_thread_bundle_; |
| 136 scoped_ptr<EmbeddedWorkerTestHelper> helper_; | 136 scoped_ptr<EmbeddedWorkerTestHelper> helper_; |
| 137 int render_process_id_; | |
| 138 }; | 137 }; |
| 139 | 138 |
| 140 scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob( | 139 scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob( |
| 141 const GURL& pattern, | 140 const GURL& pattern, |
| 142 const GURL& script_url, | 141 const GURL& script_url, |
| 143 ServiceWorkerStatusCode expected_status) { | 142 ServiceWorkerStatusCode expected_status) { |
| 144 scoped_refptr<ServiceWorkerRegistration> registration; | 143 scoped_refptr<ServiceWorkerRegistration> registration; |
| 144 scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner); |
| 145 bool called; | 145 bool called; |
| 146 job_coordinator()->Register( | 146 job_coordinator()->Register( |
| 147 pattern, script_url, NULL, | 147 pattern, script_url, NULL, |
| 148 SaveRegistration(expected_status, &called, ®istration)); | 148 SaveRegistration(expected_status, runner, &called, ®istration)); |
| 149 EXPECT_FALSE(called); | 149 EXPECT_FALSE(called); |
| 150 base::RunLoop().RunUntilIdle(); | 150 runner->Run(); |
| 151 EXPECT_TRUE(called); | 151 EXPECT_TRUE(called); |
| 152 return registration; | 152 return registration; |
| 153 } | 153 } |
| 154 | 154 |
| 155 void ServiceWorkerJobTest::RunUnregisterJob( | 155 void ServiceWorkerJobTest::RunUnregisterJob( |
| 156 const GURL& pattern, | 156 const GURL& pattern, |
| 157 ServiceWorkerStatusCode expected_status) { | 157 ServiceWorkerStatusCode expected_status) { |
| 158 bool called; | 158 bool called; |
| 159 job_coordinator()->Unregister(pattern, | 159 job_coordinator()->Unregister(pattern, |
| 160 SaveUnregistration(expected_status, &called)); | 160 SaveUnregistration(expected_status, &called)); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 storage()->FindRegistrationForDocument( | 225 storage()->FindRegistrationForDocument( |
| 226 GURL("http://www.example.com/two"), | 226 GURL("http://www.example.com/two"), |
| 227 SaveFoundRegistration(SERVICE_WORKER_OK, &called, ®istration2)); | 227 SaveFoundRegistration(SERVICE_WORKER_OK, &called, ®istration2)); |
| 228 base::RunLoop().RunUntilIdle(); | 228 base::RunLoop().RunUntilIdle(); |
| 229 EXPECT_TRUE(called); | 229 EXPECT_TRUE(called); |
| 230 ASSERT_EQ(registration1, original_registration); | 230 ASSERT_EQ(registration1, original_registration); |
| 231 ASSERT_EQ(registration1, registration2); | 231 ASSERT_EQ(registration1, registration2); |
| 232 } | 232 } |
| 233 | 233 |
| 234 TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) { | 234 TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) { |
| 235 scoped_refptr<MessageLoopRunner> runner1(new MessageLoopRunner); |
| 235 bool called1; | 236 bool called1; |
| 236 scoped_refptr<ServiceWorkerRegistration> original_registration1; | 237 scoped_refptr<ServiceWorkerRegistration> original_registration1; |
| 237 job_coordinator()->Register( | 238 job_coordinator()->Register( |
| 238 GURL("http://www.example.com/one/"), | 239 GURL("http://www.example.com/one/"), |
| 239 GURL("http://www.example.com/service_worker.js"), | 240 GURL("http://www.example.com/service_worker.js"), NULL, |
| 240 NULL, | 241 SaveRegistration(SERVICE_WORKER_OK, runner1, &called1, |
| 241 SaveRegistration(SERVICE_WORKER_OK, &called1, &original_registration1)); | 242 &original_registration1)); |
| 242 | 243 |
| 244 scoped_refptr<MessageLoopRunner> runner2(new MessageLoopRunner); |
| 243 bool called2; | 245 bool called2; |
| 244 scoped_refptr<ServiceWorkerRegistration> original_registration2; | 246 scoped_refptr<ServiceWorkerRegistration> original_registration2; |
| 245 job_coordinator()->Register( | 247 job_coordinator()->Register( |
| 246 GURL("http://www.example.com/two/"), | 248 GURL("http://www.example.com/two/"), |
| 247 GURL("http://www.example.com/service_worker.js"), | 249 GURL("http://www.example.com/service_worker.js"), NULL, |
| 248 NULL, | 250 SaveRegistration(SERVICE_WORKER_OK, runner2, &called2, |
| 249 SaveRegistration(SERVICE_WORKER_OK, &called2, &original_registration2)); | 251 &original_registration2)); |
| 250 | 252 |
| 251 EXPECT_FALSE(called1); | 253 EXPECT_FALSE(called1); |
| 252 EXPECT_FALSE(called2); | 254 EXPECT_FALSE(called2); |
| 253 base::RunLoop().RunUntilIdle(); | 255 runner1->Run(); |
| 256 runner2->Run(); |
| 254 EXPECT_TRUE(called2); | 257 EXPECT_TRUE(called2); |
| 255 EXPECT_TRUE(called1); | 258 EXPECT_TRUE(called1); |
| 256 | 259 |
| 257 scoped_refptr<ServiceWorkerRegistration> registration1; | 260 scoped_refptr<ServiceWorkerRegistration> registration1; |
| 258 storage()->FindRegistrationForDocument( | 261 storage()->FindRegistrationForDocument( |
| 259 GURL("http://www.example.com/one/"), | 262 GURL("http://www.example.com/one/"), |
| 260 SaveFoundRegistration(SERVICE_WORKER_OK, &called1, ®istration1)); | 263 SaveFoundRegistration(SERVICE_WORKER_OK, &called1, ®istration1)); |
| 261 scoped_refptr<ServiceWorkerRegistration> registration2; | 264 scoped_refptr<ServiceWorkerRegistration> registration2; |
| 262 storage()->FindRegistrationForDocument( | 265 storage()->FindRegistrationForDocument( |
| 263 GURL("http://www.example.com/two/"), | 266 GURL("http://www.example.com/two/"), |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 ASSERT_FALSE(old_registration->HasOneRef()); | 352 ASSERT_FALSE(old_registration->HasOneRef()); |
| 350 | 353 |
| 351 scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern = | 354 scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern = |
| 352 FindRegistrationForPattern(pattern); | 355 FindRegistrationForPattern(pattern); |
| 353 | 356 |
| 354 ASSERT_EQ(new_registration, old_registration); | 357 ASSERT_EQ(new_registration, old_registration); |
| 355 } | 358 } |
| 356 | 359 |
| 357 class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper { | 360 class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper { |
| 358 public: | 361 public: |
| 359 explicit FailToStartWorkerTestHelper(int mock_render_process_id) | 362 explicit FailToStartWorkerTestHelper() |
| 360 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id) {} | 363 : EmbeddedWorkerTestHelper(base::FilePath()) {} |
| 361 | 364 |
| 362 void OnStartWorker(int embedded_worker_id, | 365 void OnStartWorker(int embedded_worker_id, |
| 363 int64 service_worker_version_id, | 366 int64 service_worker_version_id, |
| 364 const GURL& scope, | 367 const GURL& scope, |
| 365 const GURL& script_url) override { | 368 const GURL& script_url) override { |
| 366 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); | 369 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); |
| 367 registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id); | 370 registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id); |
| 368 } | 371 } |
| 369 }; | 372 }; |
| 370 | 373 |
| 371 TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) { | 374 TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) { |
| 372 helper_.reset(new FailToStartWorkerTestHelper(render_process_id_)); | 375 helper_.reset(new FailToStartWorkerTestHelper()); |
| 373 | 376 |
| 374 scoped_refptr<ServiceWorkerRegistration> registration = | 377 scoped_refptr<ServiceWorkerRegistration> registration = |
| 375 RunRegisterJob(GURL("http://www.example.com/"), | 378 RunRegisterJob(GURL("http://www.example.com/"), |
| 376 GURL("http://www.example.com/service_worker.js"), | 379 GURL("http://www.example.com/service_worker.js"), |
| 377 SERVICE_WORKER_ERROR_START_WORKER_FAILED); | 380 SERVICE_WORKER_ERROR_START_WORKER_FAILED); |
| 378 | 381 |
| 379 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration); | 382 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration); |
| 380 } | 383 } |
| 381 | 384 |
| 382 // Register and then unregister the pattern, in parallel. Job coordinator should | 385 // Register and then unregister the pattern, in parallel. Job coordinator should |
| 383 // process jobs until the last job. | 386 // process jobs until the last job. |
| 384 TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) { | 387 TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) { |
| 385 GURL pattern("http://www.example.com/"); | 388 GURL pattern("http://www.example.com/"); |
| 386 GURL script_url("http://www.example.com/service_worker.js"); | 389 GURL script_url("http://www.example.com/service_worker.js"); |
| 387 | 390 |
| 391 scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner); |
| 388 bool registration_called = false; | 392 bool registration_called = false; |
| 389 scoped_refptr<ServiceWorkerRegistration> registration; | 393 scoped_refptr<ServiceWorkerRegistration> registration; |
| 390 job_coordinator()->Register( | 394 job_coordinator()->Register( |
| 391 pattern, | 395 pattern, script_url, NULL, |
| 392 script_url, | 396 SaveRegistration(SERVICE_WORKER_OK, runner, ®istration_called, |
| 393 NULL, | 397 ®istration)); |
| 394 SaveRegistration(SERVICE_WORKER_OK, ®istration_called, ®istration)); | |
| 395 | 398 |
| 396 bool unregistration_called = false; | 399 bool unregistration_called = false; |
| 397 job_coordinator()->Unregister( | 400 job_coordinator()->Unregister( |
| 398 pattern, | 401 pattern, |
| 399 SaveUnregistration(SERVICE_WORKER_OK, &unregistration_called)); | 402 SaveUnregistration(SERVICE_WORKER_OK, &unregistration_called)); |
| 400 | 403 |
| 401 ASSERT_FALSE(registration_called); | 404 ASSERT_FALSE(registration_called); |
| 402 ASSERT_FALSE(unregistration_called); | 405 ASSERT_FALSE(unregistration_called); |
| 406 runner->Run(); |
| 403 base::RunLoop().RunUntilIdle(); | 407 base::RunLoop().RunUntilIdle(); |
| 404 ASSERT_TRUE(registration_called); | 408 ASSERT_TRUE(registration_called); |
| 405 ASSERT_TRUE(unregistration_called); | 409 ASSERT_TRUE(unregistration_called); |
| 406 | 410 |
| 407 registration = FindRegistrationForPattern(pattern, | 411 registration = FindRegistrationForPattern(pattern, |
| 408 SERVICE_WORKER_ERROR_NOT_FOUND); | 412 SERVICE_WORKER_ERROR_NOT_FOUND); |
| 409 | 413 |
| 410 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration); | 414 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration); |
| 411 } | 415 } |
| 412 | 416 |
| 413 // Register conflicting scripts for the same pattern. The most recent | 417 // Register conflicting scripts for the same pattern. The most recent |
| 414 // registration should win, and the old registration should have been | 418 // registration should win, and the old registration should have been |
| 415 // shutdown. | 419 // shutdown. |
| 416 TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) { | 420 TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) { |
| 417 GURL pattern("http://www.example.com/"); | 421 GURL pattern("http://www.example.com/"); |
| 418 | 422 |
| 419 GURL script_url1("http://www.example.com/service_worker1.js"); | 423 GURL script_url1("http://www.example.com/service_worker1.js"); |
| 424 scoped_refptr<MessageLoopRunner> runner1(new MessageLoopRunner); |
| 420 bool registration1_called = false; | 425 bool registration1_called = false; |
| 421 scoped_refptr<ServiceWorkerRegistration> registration1; | 426 scoped_refptr<ServiceWorkerRegistration> registration1; |
| 422 job_coordinator()->Register( | 427 job_coordinator()->Register( |
| 423 pattern, | 428 pattern, script_url1, NULL, |
| 424 script_url1, | 429 SaveRegistration(SERVICE_WORKER_OK, runner1, ®istration1_called, |
| 425 NULL, | 430 ®istration1)); |
| 426 SaveRegistration( | |
| 427 SERVICE_WORKER_OK, ®istration1_called, ®istration1)); | |
| 428 | 431 |
| 429 GURL script_url2("http://www.example.com/service_worker2.js"); | 432 GURL script_url2("http://www.example.com/service_worker2.js"); |
| 433 scoped_refptr<MessageLoopRunner> runner2(new MessageLoopRunner); |
| 430 bool registration2_called = false; | 434 bool registration2_called = false; |
| 431 scoped_refptr<ServiceWorkerRegistration> registration2; | 435 scoped_refptr<ServiceWorkerRegistration> registration2; |
| 432 job_coordinator()->Register( | 436 job_coordinator()->Register( |
| 433 pattern, | 437 pattern, script_url2, NULL, |
| 434 script_url2, | 438 SaveRegistration(SERVICE_WORKER_OK, runner2, ®istration2_called, |
| 435 NULL, | 439 ®istration2)); |
| 436 SaveRegistration( | |
| 437 SERVICE_WORKER_OK, ®istration2_called, ®istration2)); | |
| 438 | 440 |
| 439 ASSERT_FALSE(registration1_called); | 441 ASSERT_FALSE(registration1_called); |
| 440 ASSERT_FALSE(registration2_called); | 442 ASSERT_FALSE(registration2_called); |
| 441 base::RunLoop().RunUntilIdle(); | 443 runner1->Run(); |
| 444 runner2->Run(); |
| 442 ASSERT_TRUE(registration1_called); | 445 ASSERT_TRUE(registration1_called); |
| 443 ASSERT_TRUE(registration2_called); | 446 ASSERT_TRUE(registration2_called); |
| 444 | 447 |
| 445 scoped_refptr<ServiceWorkerRegistration> registration = | 448 scoped_refptr<ServiceWorkerRegistration> registration = |
| 446 FindRegistrationForPattern(pattern); | 449 FindRegistrationForPattern(pattern); |
| 447 | 450 |
| 448 ASSERT_EQ(registration2, registration); | 451 ASSERT_EQ(registration2, registration); |
| 449 } | 452 } |
| 450 | 453 |
| 451 // Register the exact same pattern + script. Requests should be | 454 // Register the exact same pattern + script. Requests should be |
| 452 // coalesced such that both callers get the exact same registration | 455 // coalesced such that both callers get the exact same registration |
| 453 // object. | 456 // object. |
| 454 TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) { | 457 TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) { |
| 455 GURL pattern("http://www.example.com/"); | 458 GURL pattern("http://www.example.com/"); |
| 456 | 459 |
| 457 GURL script_url("http://www.example.com/service_worker1.js"); | 460 GURL script_url("http://www.example.com/service_worker1.js"); |
| 461 scoped_refptr<MessageLoopRunner> runner1(new MessageLoopRunner); |
| 458 bool registration1_called = false; | 462 bool registration1_called = false; |
| 459 scoped_refptr<ServiceWorkerRegistration> registration1; | 463 scoped_refptr<ServiceWorkerRegistration> registration1; |
| 460 job_coordinator()->Register( | 464 job_coordinator()->Register( |
| 461 pattern, | 465 pattern, script_url, NULL, |
| 462 script_url, | 466 SaveRegistration(SERVICE_WORKER_OK, runner1, ®istration1_called, |
| 463 NULL, | 467 ®istration1)); |
| 464 SaveRegistration( | |
| 465 SERVICE_WORKER_OK, ®istration1_called, ®istration1)); | |
| 466 | 468 |
| 469 scoped_refptr<MessageLoopRunner> runner2(new MessageLoopRunner); |
| 467 bool registration2_called = false; | 470 bool registration2_called = false; |
| 468 scoped_refptr<ServiceWorkerRegistration> registration2; | 471 scoped_refptr<ServiceWorkerRegistration> registration2; |
| 469 job_coordinator()->Register( | 472 job_coordinator()->Register( |
| 470 pattern, | 473 pattern, script_url, NULL, |
| 471 script_url, | 474 SaveRegistration(SERVICE_WORKER_OK, runner2, ®istration2_called, |
| 472 NULL, | 475 ®istration2)); |
| 473 SaveRegistration( | |
| 474 SERVICE_WORKER_OK, ®istration2_called, ®istration2)); | |
| 475 | 476 |
| 476 ASSERT_FALSE(registration1_called); | 477 ASSERT_FALSE(registration1_called); |
| 477 ASSERT_FALSE(registration2_called); | 478 ASSERT_FALSE(registration2_called); |
| 478 base::RunLoop().RunUntilIdle(); | 479 runner1->Run(); |
| 480 runner2->Run(); |
| 479 ASSERT_TRUE(registration1_called); | 481 ASSERT_TRUE(registration1_called); |
| 480 ASSERT_TRUE(registration2_called); | 482 ASSERT_TRUE(registration2_called); |
| 481 | 483 |
| 482 ASSERT_EQ(registration1, registration2); | 484 ASSERT_EQ(registration1, registration2); |
| 483 | 485 |
| 484 scoped_refptr<ServiceWorkerRegistration> registration = | 486 scoped_refptr<ServiceWorkerRegistration> registration = |
| 485 FindRegistrationForPattern(pattern); | 487 FindRegistrationForPattern(pattern); |
| 486 | 488 |
| 487 ASSERT_EQ(registration, registration1); | 489 ASSERT_EQ(registration, registration1); |
| 488 } | 490 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 518 | 520 |
| 519 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration); | 521 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration); |
| 520 } | 522 } |
| 521 | 523 |
| 522 TEST_F(ServiceWorkerJobTest, AbortAll_Register) { | 524 TEST_F(ServiceWorkerJobTest, AbortAll_Register) { |
| 523 GURL pattern1("http://www1.example.com/"); | 525 GURL pattern1("http://www1.example.com/"); |
| 524 GURL pattern2("http://www2.example.com/"); | 526 GURL pattern2("http://www2.example.com/"); |
| 525 GURL script_url1("http://www1.example.com/service_worker.js"); | 527 GURL script_url1("http://www1.example.com/service_worker.js"); |
| 526 GURL script_url2("http://www2.example.com/service_worker.js"); | 528 GURL script_url2("http://www2.example.com/service_worker.js"); |
| 527 | 529 |
| 530 scoped_refptr<MessageLoopRunner> runner1(new MessageLoopRunner); |
| 528 bool registration_called1 = false; | 531 bool registration_called1 = false; |
| 529 scoped_refptr<ServiceWorkerRegistration> registration1; | 532 scoped_refptr<ServiceWorkerRegistration> registration1; |
| 530 job_coordinator()->Register( | 533 job_coordinator()->Register( |
| 531 pattern1, | 534 pattern1, script_url1, NULL, |
| 532 script_url1, | 535 SaveRegistration(SERVICE_WORKER_ERROR_ABORT, runner1, |
| 533 NULL, | |
| 534 SaveRegistration(SERVICE_WORKER_ERROR_ABORT, | |
| 535 ®istration_called1, ®istration1)); | 536 ®istration_called1, ®istration1)); |
| 536 | 537 |
| 538 scoped_refptr<MessageLoopRunner> runner2(new MessageLoopRunner); |
| 537 bool registration_called2 = false; | 539 bool registration_called2 = false; |
| 538 scoped_refptr<ServiceWorkerRegistration> registration2; | 540 scoped_refptr<ServiceWorkerRegistration> registration2; |
| 539 job_coordinator()->Register( | 541 job_coordinator()->Register( |
| 540 pattern2, | 542 pattern2, script_url2, NULL, |
| 541 script_url2, | 543 SaveRegistration(SERVICE_WORKER_ERROR_ABORT, runner2, |
| 542 NULL, | |
| 543 SaveRegistration(SERVICE_WORKER_ERROR_ABORT, | |
| 544 ®istration_called2, ®istration2)); | 544 ®istration_called2, ®istration2)); |
| 545 | 545 |
| 546 ASSERT_FALSE(registration_called1); | 546 ASSERT_FALSE(registration_called1); |
| 547 ASSERT_FALSE(registration_called2); | 547 ASSERT_FALSE(registration_called2); |
| 548 job_coordinator()->AbortAll(); | 548 job_coordinator()->AbortAll(); |
| 549 | 549 |
| 550 base::RunLoop().RunUntilIdle(); | 550 runner1->Run(); |
| 551 runner2->Run(); |
| 551 ASSERT_TRUE(registration_called1); | 552 ASSERT_TRUE(registration_called1); |
| 552 ASSERT_TRUE(registration_called2); | 553 ASSERT_TRUE(registration_called2); |
| 553 | 554 |
| 554 bool find_called1 = false; | 555 bool find_called1 = false; |
| 555 storage()->FindRegistrationForPattern( | 556 storage()->FindRegistrationForPattern( |
| 556 pattern1, | 557 pattern1, |
| 557 SaveFoundRegistration( | 558 SaveFoundRegistration( |
| 558 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called1, ®istration1)); | 559 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called1, ®istration1)); |
| 559 | 560 |
| 560 bool find_called2 = false; | 561 bool find_called2 = false; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 | 594 |
| 594 base::RunLoop().RunUntilIdle(); | 595 base::RunLoop().RunUntilIdle(); |
| 595 ASSERT_TRUE(unregistration_called1); | 596 ASSERT_TRUE(unregistration_called1); |
| 596 ASSERT_TRUE(unregistration_called2); | 597 ASSERT_TRUE(unregistration_called2); |
| 597 } | 598 } |
| 598 | 599 |
| 599 TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) { | 600 TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) { |
| 600 GURL pattern("http://www.example.com/"); | 601 GURL pattern("http://www.example.com/"); |
| 601 GURL script_url("http://www.example.com/service_worker.js"); | 602 GURL script_url("http://www.example.com/service_worker.js"); |
| 602 | 603 |
| 604 scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner); |
| 603 bool registration_called = false; | 605 bool registration_called = false; |
| 604 scoped_refptr<ServiceWorkerRegistration> registration; | 606 scoped_refptr<ServiceWorkerRegistration> registration; |
| 605 job_coordinator()->Register( | 607 job_coordinator()->Register( |
| 606 pattern, | 608 pattern, script_url, NULL, |
| 607 script_url, | 609 SaveRegistration(SERVICE_WORKER_ERROR_ABORT, runner, ®istration_called, |
| 608 NULL, | 610 ®istration)); |
| 609 SaveRegistration(SERVICE_WORKER_ERROR_ABORT, | |
| 610 ®istration_called, ®istration)); | |
| 611 | 611 |
| 612 bool unregistration_called = false; | 612 bool unregistration_called = false; |
| 613 job_coordinator()->Unregister( | 613 job_coordinator()->Unregister( |
| 614 pattern, | 614 pattern, |
| 615 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT, | 615 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT, |
| 616 &unregistration_called)); | 616 &unregistration_called)); |
| 617 | 617 |
| 618 ASSERT_FALSE(registration_called); | 618 ASSERT_FALSE(registration_called); |
| 619 ASSERT_FALSE(unregistration_called); | 619 ASSERT_FALSE(unregistration_called); |
| 620 job_coordinator()->AbortAll(); | 620 job_coordinator()->AbortAll(); |
| 621 | 621 |
| 622 runner->Run(); |
| 622 base::RunLoop().RunUntilIdle(); | 623 base::RunLoop().RunUntilIdle(); |
| 623 ASSERT_TRUE(registration_called); | 624 ASSERT_TRUE(registration_called); |
| 624 ASSERT_TRUE(unregistration_called); | 625 ASSERT_TRUE(unregistration_called); |
| 625 | 626 |
| 626 registration = FindRegistrationForPattern(pattern, | 627 registration = FindRegistrationForPattern(pattern, |
| 627 SERVICE_WORKER_ERROR_NOT_FOUND); | 628 SERVICE_WORKER_ERROR_NOT_FOUND); |
| 628 | 629 |
| 629 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration); | 630 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration); |
| 630 } | 631 } |
| 631 | 632 |
| 632 // Tests that the waiting worker enters the 'redundant' state upon | 633 // Tests that the waiting worker enters the 'redundant' state upon |
| 633 // unregistration. | 634 // unregistration. |
| 634 TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) { | 635 TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) { |
| 635 GURL script_url("http://www.example.com/service_worker.js"); | 636 GURL script_url("http://www.example.com/service_worker.js"); |
| 636 scoped_refptr<ServiceWorkerRegistration> registration = | 637 scoped_refptr<ServiceWorkerRegistration> registration = |
| 637 RunRegisterJob(GURL("http://www.example.com/"), script_url); | 638 RunRegisterJob(GURL("http://www.example.com/"), script_url); |
| 638 ASSERT_TRUE(registration.get()); | 639 ASSERT_TRUE(registration.get()); |
| 639 | 640 |
| 640 // Manually create the waiting worker since there is no way to become a | 641 // Manually create the waiting worker since there is no way to become a |
| 641 // waiting worker until Update is implemented. | 642 // waiting worker until Update is implemented. |
| 642 scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion( | 643 scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion( |
| 643 registration.get(), script_url, 1L, helper_->context()->AsWeakPtr()); | 644 registration.get(), script_url, 1L, helper_->context()->AsWeakPtr()); |
| 644 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; | 645 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; |
| 645 version->StartWorker(CreateReceiverOnCurrentThread(&status)); | 646 scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner); |
| 646 base::RunLoop().RunUntilIdle(); | 647 version->StartWorker( |
| 648 CreateReceiverOnCurrentThread(&status, runner->QuitClosure())); |
| 649 runner->Run(); |
| 647 ASSERT_EQ(SERVICE_WORKER_OK, status); | 650 ASSERT_EQ(SERVICE_WORKER_OK, status); |
| 648 | 651 |
| 649 version->SetStatus(ServiceWorkerVersion::INSTALLED); | 652 version->SetStatus(ServiceWorkerVersion::INSTALLED); |
| 650 registration->SetWaitingVersion(version); | 653 registration->SetWaitingVersion(version); |
| 651 EXPECT_EQ(ServiceWorkerVersion::RUNNING, | 654 EXPECT_EQ(ServiceWorkerVersion::RUNNING, |
| 652 version->running_status()); | 655 version->running_status()); |
| 653 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status()); | 656 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status()); |
| 654 | 657 |
| 655 RunUnregisterJob(GURL("http://www.example.com/")); | 658 RunUnregisterJob(GURL("http://www.example.com/")); |
| 656 | 659 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 int64 registration_id; | 775 int64 registration_id; |
| 773 ChangedVersionAttributesMask mask; | 776 ChangedVersionAttributesMask mask; |
| 774 ServiceWorkerRegistrationInfo info; | 777 ServiceWorkerRegistrationInfo info; |
| 775 }; | 778 }; |
| 776 | 779 |
| 777 struct StateChangeLogEntry { | 780 struct StateChangeLogEntry { |
| 778 int64 version_id; | 781 int64 version_id; |
| 779 ServiceWorkerVersion::Status status; | 782 ServiceWorkerVersion::Status status; |
| 780 }; | 783 }; |
| 781 | 784 |
| 782 UpdateJobTestHelper(int mock_render_process_id) | 785 UpdateJobTestHelper() |
| 783 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id), | 786 : EmbeddedWorkerTestHelper(base::FilePath()), update_found_(false) {} |
| 784 update_found_(false) {} | |
| 785 ~UpdateJobTestHelper() override { | 787 ~UpdateJobTestHelper() override { |
| 786 if (registration_.get()) | 788 if (registration_.get()) |
| 787 registration_->RemoveListener(this); | 789 registration_->RemoveListener(this); |
| 788 } | 790 } |
| 789 | 791 |
| 790 ServiceWorkerStorage* storage() { return context()->storage(); } | 792 ServiceWorkerStorage* storage() { return context()->storage(); } |
| 791 ServiceWorkerJobCoordinator* job_coordinator() { | 793 ServiceWorkerJobCoordinator* job_coordinator() { |
| 792 return context()->job_coordinator(); | 794 return context()->job_coordinator(); |
| 793 } | 795 } |
| 794 | 796 |
| 795 scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration( | 797 scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration( |
| 796 const GURL& test_origin) { | 798 const GURL& test_origin) { |
| 797 scoped_refptr<ServiceWorkerRegistration> registration; | 799 scoped_refptr<ServiceWorkerRegistration> registration; |
| 800 scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner); |
| 798 bool called = false; | 801 bool called = false; |
| 799 job_coordinator()->Register( | 802 job_coordinator()->Register( |
| 800 test_origin.Resolve(kScope), | 803 test_origin.Resolve(kScope), test_origin.Resolve(kScript), NULL, |
| 801 test_origin.Resolve(kScript), | 804 SaveRegistration(SERVICE_WORKER_OK, runner, &called, ®istration)); |
| 802 NULL, | 805 runner->Run(); |
| 803 SaveRegistration(SERVICE_WORKER_OK, &called, ®istration)); | |
| 804 base::RunLoop().RunUntilIdle(); | |
| 805 EXPECT_TRUE(called); | 806 EXPECT_TRUE(called); |
| 806 EXPECT_TRUE(registration.get()); | 807 EXPECT_TRUE(registration.get()); |
| 807 EXPECT_TRUE(registration->active_version()); | 808 EXPECT_TRUE(registration->active_version()); |
| 808 EXPECT_FALSE(registration->installing_version()); | 809 EXPECT_FALSE(registration->installing_version()); |
| 809 EXPECT_FALSE(registration->waiting_version()); | 810 EXPECT_FALSE(registration->waiting_version()); |
| 810 registration_ = registration; | 811 registration_ = registration; |
| 811 return registration; | 812 return registration; |
| 812 } | 813 } |
| 813 | 814 |
| 814 // EmbeddedWorkerTestHelper overrides | 815 // EmbeddedWorkerTestHelper overrides |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 attribute_change_log_.push_back(entry); | 865 attribute_change_log_.push_back(entry); |
| 865 } | 866 } |
| 866 | 867 |
| 867 void OnRegistrationFailed(ServiceWorkerRegistration* registration) override { | 868 void OnRegistrationFailed(ServiceWorkerRegistration* registration) override { |
| 868 NOTREACHED(); | 869 NOTREACHED(); |
| 869 } | 870 } |
| 870 | 871 |
| 871 void OnUpdateFound(ServiceWorkerRegistration* registration) override { | 872 void OnUpdateFound(ServiceWorkerRegistration* registration) override { |
| 872 ASSERT_FALSE(update_found_); | 873 ASSERT_FALSE(update_found_); |
| 873 update_found_ = true; | 874 update_found_ = true; |
| 875 if (wait_for_update_runner_) |
| 876 wait_for_update_runner_->Quit(); |
| 874 } | 877 } |
| 875 | 878 |
| 876 // ServiceWorkerVersion::Listener overrides | 879 // ServiceWorkerVersion::Listener overrides |
| 877 void OnVersionStateChanged(ServiceWorkerVersion* version) override { | 880 void OnVersionStateChanged(ServiceWorkerVersion* version) override { |
| 878 StateChangeLogEntry entry; | 881 StateChangeLogEntry entry; |
| 879 entry.version_id = version->version_id(); | 882 entry.version_id = version->version_id(); |
| 880 entry.status = version->status(); | 883 entry.status = version->status(); |
| 881 state_change_log_.push_back(entry); | 884 state_change_log_.push_back(entry); |
| 885 if (wait_for_state_change_runner_) |
| 886 wait_for_state_change_runner_->Quit(); |
| 882 } | 887 } |
| 883 | 888 |
| 884 scoped_refptr<ServiceWorkerRegistration> registration_; | 889 scoped_refptr<ServiceWorkerRegistration> registration_; |
| 885 | 890 |
| 886 std::vector<AttributeChangeLogEntry> attribute_change_log_; | 891 std::vector<AttributeChangeLogEntry> attribute_change_log_; |
| 887 std::vector<StateChangeLogEntry> state_change_log_; | 892 std::vector<StateChangeLogEntry> state_change_log_; |
| 888 bool update_found_; | 893 bool update_found_; |
| 894 scoped_refptr<MessageLoopRunner> wait_for_update_runner_; |
| 895 scoped_refptr<MessageLoopRunner> wait_for_state_change_runner_; |
| 889 }; | 896 }; |
| 890 | 897 |
| 891 // Helper class for update tests that evicts the active version when the update | 898 // Helper class for update tests that evicts the active version when the update |
| 892 // worker is about to be started. | 899 // worker is about to be started. |
| 893 class EvictIncumbentVersionHelper : public UpdateJobTestHelper { | 900 class EvictIncumbentVersionHelper : public UpdateJobTestHelper { |
| 894 public: | 901 public: |
| 895 EvictIncumbentVersionHelper(int mock_render_process_id) | 902 EvictIncumbentVersionHelper() : UpdateJobTestHelper() {} |
| 896 : UpdateJobTestHelper(mock_render_process_id) {} | |
| 897 ~EvictIncumbentVersionHelper() override {} | 903 ~EvictIncumbentVersionHelper() override {} |
| 898 | 904 |
| 899 void OnStartWorker(int embedded_worker_id, | 905 void OnStartWorker(int embedded_worker_id, |
| 900 int64 version_id, | 906 int64 version_id, |
| 901 const GURL& scope, | 907 const GURL& scope, |
| 902 const GURL& script) override { | 908 const GURL& script) override { |
| 903 ServiceWorkerVersion* version = context()->GetLiveVersion(version_id); | 909 ServiceWorkerVersion* version = context()->GetLiveVersion(version_id); |
| 904 ServiceWorkerRegistration* registration = | 910 ServiceWorkerRegistration* registration = |
| 905 context()->GetLiveRegistration(version->registration_id()); | 911 context()->GetLiveRegistration(version->registration_id()); |
| 906 bool is_update = registration->active_version() && | 912 bool is_update = registration->active_version() && |
| (...skipping 11 matching lines...) Expand all Loading... |
| 918 void OnRegistrationFailed(ServiceWorkerRegistration* registration) override { | 924 void OnRegistrationFailed(ServiceWorkerRegistration* registration) override { |
| 919 registration_failed_ = true; | 925 registration_failed_ = true; |
| 920 } | 926 } |
| 921 | 927 |
| 922 bool registration_failed_ = false; | 928 bool registration_failed_ = false; |
| 923 }; | 929 }; |
| 924 | 930 |
| 925 } // namespace | 931 } // namespace |
| 926 | 932 |
| 927 TEST_F(ServiceWorkerJobTest, Update_NoChange) { | 933 TEST_F(ServiceWorkerJobTest, Update_NoChange) { |
| 928 UpdateJobTestHelper* update_helper = | 934 UpdateJobTestHelper* update_helper = new UpdateJobTestHelper(); |
| 929 new UpdateJobTestHelper(render_process_id_); | |
| 930 helper_.reset(update_helper); | 935 helper_.reset(update_helper); |
| 931 scoped_refptr<ServiceWorkerRegistration> registration = | 936 scoped_refptr<ServiceWorkerRegistration> registration = |
| 932 update_helper->SetupInitialRegistration(kNoChangeOrigin); | 937 update_helper->SetupInitialRegistration(kNoChangeOrigin); |
| 933 ASSERT_TRUE(registration.get()); | 938 ASSERT_TRUE(registration.get()); |
| 934 ASSERT_EQ(4u, update_helper->state_change_log_.size()); | 939 ASSERT_EQ(4u, update_helper->state_change_log_.size()); |
| 935 EXPECT_EQ(ServiceWorkerVersion::INSTALLING, | 940 EXPECT_EQ(ServiceWorkerVersion::INSTALLING, |
| 936 update_helper->state_change_log_[0].status); | 941 update_helper->state_change_log_[0].status); |
| 937 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, | 942 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, |
| 938 update_helper->state_change_log_[1].status); | 943 update_helper->state_change_log_[1].status); |
| 939 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, | 944 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, |
| 940 update_helper->state_change_log_[2].status); | 945 update_helper->state_change_log_[2].status); |
| 941 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, | 946 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, |
| 942 update_helper->state_change_log_[3].status); | 947 update_helper->state_change_log_[3].status); |
| 943 update_helper->state_change_log_.clear(); | 948 update_helper->state_change_log_.clear(); |
| 944 | 949 |
| 945 // Run the update job. | 950 // Run the update job. |
| 951 update_helper->wait_for_state_change_runner_ = new MessageLoopRunner; |
| 946 registration->AddListener(update_helper); | 952 registration->AddListener(update_helper); |
| 947 scoped_refptr<ServiceWorkerVersion> first_version = | 953 scoped_refptr<ServiceWorkerVersion> first_version = |
| 948 registration->active_version(); | 954 registration->active_version(); |
| 949 first_version->StartUpdate(); | 955 first_version->StartUpdate(); |
| 956 update_helper->wait_for_state_change_runner_->Run(); |
| 950 base::RunLoop().RunUntilIdle(); | 957 base::RunLoop().RunUntilIdle(); |
| 951 | 958 |
| 952 // Verify results. | 959 // Verify results. |
| 953 ASSERT_TRUE(registration->active_version()); | 960 ASSERT_TRUE(registration->active_version()); |
| 954 EXPECT_EQ(first_version.get(), registration->active_version()); | 961 EXPECT_EQ(first_version.get(), registration->active_version()); |
| 955 EXPECT_FALSE(registration->installing_version()); | 962 EXPECT_FALSE(registration->installing_version()); |
| 956 EXPECT_FALSE(registration->waiting_version()); | 963 EXPECT_FALSE(registration->waiting_version()); |
| 957 EXPECT_TRUE(update_helper->attribute_change_log_.empty()); | 964 EXPECT_TRUE(update_helper->attribute_change_log_.empty()); |
| 958 ASSERT_EQ(1u, update_helper->state_change_log_.size()); | 965 ASSERT_EQ(1u, update_helper->state_change_log_.size()); |
| 959 EXPECT_NE(registration->active_version()->version_id(), | 966 EXPECT_NE(registration->active_version()->version_id(), |
| 960 update_helper->state_change_log_[0].version_id); | 967 update_helper->state_change_log_[0].version_id); |
| 961 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, | 968 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, |
| 962 update_helper->state_change_log_[0].status); | 969 update_helper->state_change_log_[0].status); |
| 963 EXPECT_FALSE(update_helper->update_found_); | 970 EXPECT_FALSE(update_helper->update_found_); |
| 964 } | 971 } |
| 965 | 972 |
| 966 TEST_F(ServiceWorkerJobTest, Update_BumpLastUpdateCheckTime) { | 973 TEST_F(ServiceWorkerJobTest, Update_BumpLastUpdateCheckTime) { |
| 967 const base::Time kToday = base::Time::Now(); | 974 const base::Time kToday = base::Time::Now(); |
| 968 const base::Time kYesterday = | 975 const base::Time kYesterday = |
| 969 kToday - base::TimeDelta::FromDays(1) - base::TimeDelta::FromHours(1); | 976 kToday - base::TimeDelta::FromDays(1) - base::TimeDelta::FromHours(1); |
| 970 UpdateJobTestHelper* update_helper = | 977 UpdateJobTestHelper* update_helper = new UpdateJobTestHelper(); |
| 971 new UpdateJobTestHelper(render_process_id_); | |
| 972 helper_.reset(update_helper); | 978 helper_.reset(update_helper); |
| 973 scoped_refptr<ServiceWorkerRegistration> registration = | 979 scoped_refptr<ServiceWorkerRegistration> registration = |
| 974 update_helper->SetupInitialRegistration(kNoChangeOrigin); | 980 update_helper->SetupInitialRegistration(kNoChangeOrigin); |
| 975 | 981 |
| 976 // Run an update where the last update check was less than 24 hours ago. The | 982 // Run an update where the last update check was less than 24 hours ago. The |
| 977 // check time shouldn't change, as we didn't bypass cache. | 983 // check time shouldn't change, as we didn't bypass cache. |
| 978 registration->set_last_update_check(kToday); | 984 registration->set_last_update_check(kToday); |
| 979 registration->active_version()->StartUpdate(); | 985 registration->active_version()->StartUpdate(); |
| 980 base::RunLoop().RunUntilIdle(); | 986 base::RunLoop().RunUntilIdle(); |
| 981 EXPECT_EQ(kToday, registration->last_update_check()); | 987 EXPECT_EQ(kToday, registration->last_update_check()); |
| 982 | 988 |
| 983 // Run an update where the last update check was over 24 hours ago. The | 989 // Run an update where the last update check was over 24 hours ago. The |
| 984 // check time should change, as the cache was bypassed. | 990 // check time should change, as the cache was bypassed. |
| 985 registration->set_last_update_check(kYesterday); | 991 registration->set_last_update_check(kYesterday); |
| 986 registration->active_version()->StartUpdate(); | 992 registration->active_version()->StartUpdate(); |
| 987 base::RunLoop().RunUntilIdle(); | 993 base::RunLoop().RunUntilIdle(); |
| 988 EXPECT_LT(kYesterday, registration->last_update_check()); | 994 EXPECT_LT(kYesterday, registration->last_update_check()); |
| 989 } | 995 } |
| 990 | 996 |
| 991 TEST_F(ServiceWorkerJobTest, Update_NewVersion) { | 997 TEST_F(ServiceWorkerJobTest, Update_NewVersion) { |
| 992 UpdateJobTestHelper* update_helper = | 998 UpdateJobTestHelper* update_helper = new UpdateJobTestHelper(); |
| 993 new UpdateJobTestHelper(render_process_id_); | |
| 994 helper_.reset(update_helper); | 999 helper_.reset(update_helper); |
| 995 scoped_refptr<ServiceWorkerRegistration> registration = | 1000 scoped_refptr<ServiceWorkerRegistration> registration = |
| 996 update_helper->SetupInitialRegistration(kNewVersionOrigin); | 1001 update_helper->SetupInitialRegistration(kNewVersionOrigin); |
| 997 ASSERT_TRUE(registration.get()); | 1002 ASSERT_TRUE(registration.get()); |
| 998 update_helper->state_change_log_.clear(); | 1003 update_helper->state_change_log_.clear(); |
| 999 | 1004 |
| 1000 // Run the update job. | 1005 // Run the update job. |
| 1006 update_helper->wait_for_update_runner_ = new MessageLoopRunner; |
| 1001 registration->AddListener(update_helper); | 1007 registration->AddListener(update_helper); |
| 1002 scoped_refptr<ServiceWorkerVersion> first_version = | 1008 scoped_refptr<ServiceWorkerVersion> first_version = |
| 1003 registration->active_version(); | 1009 registration->active_version(); |
| 1004 first_version->StartUpdate(); | 1010 first_version->StartUpdate(); |
| 1011 update_helper->wait_for_update_runner_->Run(); |
| 1005 base::RunLoop().RunUntilIdle(); | 1012 base::RunLoop().RunUntilIdle(); |
| 1006 | 1013 |
| 1007 // Verify results. | 1014 // Verify results. |
| 1008 ASSERT_TRUE(registration->active_version()); | 1015 ASSERT_TRUE(registration->active_version()); |
| 1009 EXPECT_NE(first_version.get(), registration->active_version()); | 1016 EXPECT_NE(first_version.get(), registration->active_version()); |
| 1010 EXPECT_FALSE(registration->installing_version()); | 1017 EXPECT_FALSE(registration->installing_version()); |
| 1011 EXPECT_FALSE(registration->waiting_version()); | 1018 EXPECT_FALSE(registration->waiting_version()); |
| 1012 ASSERT_EQ(3u, update_helper->attribute_change_log_.size()); | 1019 ASSERT_EQ(3u, update_helper->attribute_change_log_.size()); |
| 1013 | 1020 |
| 1014 UpdateJobTestHelper::AttributeChangeLogEntry entry; | 1021 UpdateJobTestHelper::AttributeChangeLogEntry entry; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 // Verify the registration was not modified by the Update. | 1109 // Verify the registration was not modified by the Update. |
| 1103 EXPECT_EQ(active_version, registration->active_version()); | 1110 EXPECT_EQ(active_version, registration->active_version()); |
| 1104 EXPECT_EQ(version.get(), registration->waiting_version()); | 1111 EXPECT_EQ(version.get(), registration->waiting_version()); |
| 1105 EXPECT_EQ(NULL, registration->installing_version()); | 1112 EXPECT_EQ(NULL, registration->installing_version()); |
| 1106 } | 1113 } |
| 1107 | 1114 |
| 1108 // Test that update succeeds if the incumbent worker was evicted | 1115 // Test that update succeeds if the incumbent worker was evicted |
| 1109 // during the update job (this can happen on disk cache failure). | 1116 // during the update job (this can happen on disk cache failure). |
| 1110 TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) { | 1117 TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) { |
| 1111 EvictIncumbentVersionHelper* update_helper = | 1118 EvictIncumbentVersionHelper* update_helper = |
| 1112 new EvictIncumbentVersionHelper(render_process_id_); | 1119 new EvictIncumbentVersionHelper(); |
| 1113 helper_.reset(update_helper); | 1120 helper_.reset(update_helper); |
| 1114 scoped_refptr<ServiceWorkerRegistration> registration = | 1121 scoped_refptr<ServiceWorkerRegistration> registration = |
| 1115 update_helper->SetupInitialRegistration(kNewVersionOrigin); | 1122 update_helper->SetupInitialRegistration(kNewVersionOrigin); |
| 1116 ASSERT_TRUE(registration.get()); | 1123 ASSERT_TRUE(registration.get()); |
| 1117 update_helper->state_change_log_.clear(); | 1124 update_helper->state_change_log_.clear(); |
| 1118 | 1125 |
| 1119 // Run the update job. | 1126 // Run the update job. |
| 1127 update_helper->wait_for_update_runner_ = new MessageLoopRunner; |
| 1120 registration->AddListener(update_helper); | 1128 registration->AddListener(update_helper); |
| 1121 scoped_refptr<ServiceWorkerVersion> first_version = | 1129 scoped_refptr<ServiceWorkerVersion> first_version = |
| 1122 registration->active_version(); | 1130 registration->active_version(); |
| 1123 first_version->StartUpdate(); | 1131 first_version->StartUpdate(); |
| 1132 update_helper->wait_for_update_runner_->Run(); |
| 1124 base::RunLoop().RunUntilIdle(); | 1133 base::RunLoop().RunUntilIdle(); |
| 1125 | 1134 |
| 1126 // Verify results. | 1135 // Verify results. |
| 1127 ASSERT_TRUE(registration->active_version()); | 1136 ASSERT_TRUE(registration->active_version()); |
| 1128 EXPECT_NE(first_version.get(), registration->active_version()); | 1137 EXPECT_NE(first_version.get(), registration->active_version()); |
| 1129 EXPECT_FALSE(registration->installing_version()); | 1138 EXPECT_FALSE(registration->installing_version()); |
| 1130 EXPECT_FALSE(registration->waiting_version()); | 1139 EXPECT_FALSE(registration->waiting_version()); |
| 1131 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, first_version->status()); | 1140 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, first_version->status()); |
| 1132 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, | 1141 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, |
| 1133 registration->active_version()->status()); | 1142 registration->active_version()->status()); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 // Verify the new version is activated. | 1353 // Verify the new version is activated. |
| 1345 EXPECT_EQ(NULL, registration->installing_version()); | 1354 EXPECT_EQ(NULL, registration->installing_version()); |
| 1346 EXPECT_EQ(NULL, registration->waiting_version()); | 1355 EXPECT_EQ(NULL, registration->waiting_version()); |
| 1347 EXPECT_EQ(third_version, registration->active_version()); | 1356 EXPECT_EQ(third_version, registration->active_version()); |
| 1348 EXPECT_EQ(ServiceWorkerVersion::RUNNING, third_version->running_status()); | 1357 EXPECT_EQ(ServiceWorkerVersion::RUNNING, third_version->running_status()); |
| 1349 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, third_version->status()); | 1358 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, third_version->status()); |
| 1350 } | 1359 } |
| 1351 | 1360 |
| 1352 class EventCallbackHelper : public EmbeddedWorkerTestHelper { | 1361 class EventCallbackHelper : public EmbeddedWorkerTestHelper { |
| 1353 public: | 1362 public: |
| 1354 explicit EventCallbackHelper(int mock_render_process_id) | 1363 explicit EventCallbackHelper() |
| 1355 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id), | 1364 : EmbeddedWorkerTestHelper(base::FilePath()), |
| 1356 install_event_result_(blink::WebServiceWorkerEventResultCompleted), | 1365 install_event_result_(blink::WebServiceWorkerEventResultCompleted), |
| 1357 activate_event_result_(blink::WebServiceWorkerEventResultCompleted) {} | 1366 activate_event_result_(blink::WebServiceWorkerEventResultCompleted) {} |
| 1358 | 1367 |
| 1359 void OnInstallEvent(int embedded_worker_id, | 1368 void OnInstallEvent(int embedded_worker_id, |
| 1360 int request_id) override { | 1369 int request_id) override { |
| 1361 if (!install_callback_.is_null()) | 1370 if (!install_callback_.is_null()) |
| 1362 install_callback_.Run(); | 1371 install_callback_.Run(); |
| 1363 SimulateSend( | 1372 SimulateSend( |
| 1364 new ServiceWorkerHostMsg_InstallEventFinished( | 1373 new ServiceWorkerHostMsg_InstallEventFinished( |
| 1365 embedded_worker_id, request_id, install_event_result_)); | 1374 embedded_worker_id, request_id, install_event_result_)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1379 void set_activate_event_result(blink::WebServiceWorkerEventResult result) { | 1388 void set_activate_event_result(blink::WebServiceWorkerEventResult result) { |
| 1380 activate_event_result_ = result; | 1389 activate_event_result_ = result; |
| 1381 } | 1390 } |
| 1382 private: | 1391 private: |
| 1383 base::Closure install_callback_; | 1392 base::Closure install_callback_; |
| 1384 blink::WebServiceWorkerEventResult install_event_result_; | 1393 blink::WebServiceWorkerEventResult install_event_result_; |
| 1385 blink::WebServiceWorkerEventResult activate_event_result_; | 1394 blink::WebServiceWorkerEventResult activate_event_result_; |
| 1386 }; | 1395 }; |
| 1387 | 1396 |
| 1388 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) { | 1397 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) { |
| 1389 EventCallbackHelper* helper = new EventCallbackHelper(render_process_id_); | 1398 EventCallbackHelper* helper = new EventCallbackHelper(); |
| 1390 helper_.reset(helper); | 1399 helper_.reset(helper); |
| 1391 | 1400 |
| 1392 GURL pattern("http://www.example.com/one/"); | 1401 GURL pattern("http://www.example.com/one/"); |
| 1393 GURL script1("http://www.example.com/service_worker.js"); | 1402 GURL script1("http://www.example.com/service_worker.js"); |
| 1394 GURL script2("http://www.example.com/service_worker.js?new"); | 1403 GURL script2("http://www.example.com/service_worker.js?new"); |
| 1395 | 1404 |
| 1396 scoped_refptr<ServiceWorkerRegistration> registration = | 1405 scoped_refptr<ServiceWorkerRegistration> registration = |
| 1397 RunRegisterJob(pattern, script1); | 1406 RunRegisterJob(pattern, script1); |
| 1398 | 1407 |
| 1399 // Add a controllee and queue an unregister to force the uninstalling state. | 1408 // Add a controllee and queue an unregister to force the uninstalling state. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1419 EXPECT_EQ(NULL, registration->installing_version()); | 1428 EXPECT_EQ(NULL, registration->installing_version()); |
| 1420 EXPECT_EQ(NULL, registration->waiting_version()); | 1429 EXPECT_EQ(NULL, registration->waiting_version()); |
| 1421 EXPECT_EQ(new_version, registration->active_version()); | 1430 EXPECT_EQ(new_version, registration->active_version()); |
| 1422 EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status()); | 1431 EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status()); |
| 1423 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status()); | 1432 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status()); |
| 1424 | 1433 |
| 1425 EXPECT_EQ(registration, FindRegistrationForPattern(pattern)); | 1434 EXPECT_EQ(registration, FindRegistrationForPattern(pattern)); |
| 1426 } | 1435 } |
| 1427 | 1436 |
| 1428 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) { | 1437 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) { |
| 1429 EventCallbackHelper* helper = new EventCallbackHelper(render_process_id_); | 1438 EventCallbackHelper* helper = new EventCallbackHelper(); |
| 1430 helper_.reset(helper); | 1439 helper_.reset(helper); |
| 1431 | 1440 |
| 1432 GURL pattern("http://www.example.com/one/"); | 1441 GURL pattern("http://www.example.com/one/"); |
| 1433 GURL script1("http://www.example.com/service_worker.js"); | 1442 GURL script1("http://www.example.com/service_worker.js"); |
| 1434 GURL script2("http://www.example.com/service_worker.js?new"); | 1443 GURL script2("http://www.example.com/service_worker.js?new"); |
| 1435 | 1444 |
| 1436 scoped_refptr<ServiceWorkerRegistration> registration = | 1445 scoped_refptr<ServiceWorkerRegistration> registration = |
| 1437 RunRegisterJob(pattern, script1); | 1446 RunRegisterJob(pattern, script1); |
| 1438 | 1447 |
| 1439 // Add a controllee and queue an unregister to force the uninstalling state. | 1448 // Add a controllee and queue an unregister to force the uninstalling state. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1455 EXPECT_FALSE(registration->is_uninstalling()); | 1464 EXPECT_FALSE(registration->is_uninstalling()); |
| 1456 EXPECT_TRUE(registration->is_uninstalled()); | 1465 EXPECT_TRUE(registration->is_uninstalled()); |
| 1457 | 1466 |
| 1458 EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status()); | 1467 EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status()); |
| 1459 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status()); | 1468 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status()); |
| 1460 | 1469 |
| 1461 FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND); | 1470 FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND); |
| 1462 } | 1471 } |
| 1463 | 1472 |
| 1464 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) { | 1473 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) { |
| 1465 EventCallbackHelper* helper = new EventCallbackHelper(render_process_id_); | 1474 EventCallbackHelper* helper = new EventCallbackHelper(); |
| 1466 helper_.reset(helper); | 1475 helper_.reset(helper); |
| 1467 | 1476 |
| 1468 GURL pattern("http://www.example.com/one/"); | 1477 GURL pattern("http://www.example.com/one/"); |
| 1469 GURL script1("http://www.example.com/service_worker.js"); | 1478 GURL script1("http://www.example.com/service_worker.js"); |
| 1470 GURL script2("http://www.example.com/service_worker.js?new"); | 1479 GURL script2("http://www.example.com/service_worker.js?new"); |
| 1471 | 1480 |
| 1472 scoped_refptr<ServiceWorkerRegistration> registration = | 1481 scoped_refptr<ServiceWorkerRegistration> registration = |
| 1473 RunRegisterJob(pattern, script1); | 1482 RunRegisterJob(pattern, script1); |
| 1474 | 1483 |
| 1475 // Add a controllee and queue an unregister to force the uninstalling state. | 1484 // Add a controllee and queue an unregister to force the uninstalling state. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1491 EXPECT_FALSE(registration->is_uninstalling()); | 1500 EXPECT_FALSE(registration->is_uninstalling()); |
| 1492 EXPECT_FALSE(registration->is_uninstalled()); | 1501 EXPECT_FALSE(registration->is_uninstalled()); |
| 1493 | 1502 |
| 1494 EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status()); | 1503 EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status()); |
| 1495 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status()); | 1504 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status()); |
| 1496 | 1505 |
| 1497 FindRegistrationForPattern(pattern, SERVICE_WORKER_OK); | 1506 FindRegistrationForPattern(pattern, SERVICE_WORKER_OK); |
| 1498 } | 1507 } |
| 1499 | 1508 |
| 1500 } // namespace content | 1509 } // namespace content |
| OLD | NEW |