Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_job_unittest.cc
blob2c936f2daed1bd27ccea9bbff5661574f428bed7
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
3 // found in the LICENSE file.
5 #include "base/files/scoped_temp_dir.h"
6 #include "base/logging.h"
7 #include "base/run_loop.h"
8 #include "content/browser/browser_thread_impl.h"
9 #include "content/browser/service_worker/embedded_worker_registry.h"
10 #include "content/browser/service_worker/embedded_worker_test_helper.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_disk_cache.h"
13 #include "content/browser/service_worker/service_worker_job_coordinator.h"
14 #include "content/browser/service_worker/service_worker_registration.h"
15 #include "content/browser/service_worker/service_worker_registration_status.h"
16 #include "content/browser/service_worker/service_worker_test_utils.h"
17 #include "content/common/service_worker/service_worker_messages.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "ipc/ipc_test_sink.h"
20 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/test_completion_callback.h"
23 #include "net/http/http_response_headers.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using net::IOBuffer;
27 using net::TestCompletionCallback;
28 using net::WrappedIOBuffer;
30 // Unit tests for testing all job registration tasks.
31 namespace content {
33 namespace {
35 int kMockRenderProcessId = 88;
37 void SaveRegistrationCallback(
38 ServiceWorkerStatusCode expected_status,
39 bool* called,
40 scoped_refptr<ServiceWorkerRegistration>* registration_out,
41 ServiceWorkerStatusCode status,
42 const std::string& status_message,
43 ServiceWorkerRegistration* registration) {
44 EXPECT_EQ(expected_status, status);
45 *called = true;
46 *registration_out = registration;
49 void SaveFoundRegistrationCallback(
50 ServiceWorkerStatusCode expected_status,
51 bool* called,
52 scoped_refptr<ServiceWorkerRegistration>* registration,
53 ServiceWorkerStatusCode status,
54 const scoped_refptr<ServiceWorkerRegistration>& result) {
55 EXPECT_EQ(expected_status, status);
56 *called = true;
57 *registration = result;
60 // 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 // it ensures that the resulting status matches the expectation.
63 // 'called' is useful for making sure a sychronous callback is or
64 // isn't called.
65 ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration(
66 ServiceWorkerStatusCode expected_status,
67 bool* called,
68 scoped_refptr<ServiceWorkerRegistration>* registration) {
69 *called = false;
70 return base::Bind(
71 &SaveRegistrationCallback, expected_status, called, registration);
74 ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration(
75 ServiceWorkerStatusCode expected_status,
76 bool* called,
77 scoped_refptr<ServiceWorkerRegistration>* registration) {
78 *called = false;
79 return base::Bind(&SaveFoundRegistrationCallback,
80 expected_status,
81 called,
82 registration);
85 void SaveUnregistrationCallback(ServiceWorkerStatusCode expected_status,
86 bool* called,
87 int64 registration_id,
88 ServiceWorkerStatusCode status) {
89 EXPECT_EQ(expected_status, status);
90 *called = true;
93 ServiceWorkerUnregisterJob::UnregistrationCallback SaveUnregistration(
94 ServiceWorkerStatusCode expected_status,
95 bool* called) {
96 *called = false;
97 return base::Bind(&SaveUnregistrationCallback, expected_status, called);
100 } // namespace
102 class ServiceWorkerJobTest : public testing::Test {
103 public:
104 ServiceWorkerJobTest()
105 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
106 render_process_id_(kMockRenderProcessId) {}
108 void SetUp() override {
109 helper_.reset(
110 new EmbeddedWorkerTestHelper(base::FilePath(), render_process_id_));
113 void TearDown() override { helper_.reset(); }
115 ServiceWorkerContextCore* context() const { return helper_->context(); }
117 ServiceWorkerJobCoordinator* job_coordinator() const {
118 return context()->job_coordinator();
120 ServiceWorkerStorage* storage() const { return context()->storage(); }
122 protected:
123 scoped_refptr<ServiceWorkerRegistration> RunRegisterJob(
124 const GURL& pattern,
125 const GURL& script_url,
126 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
127 void RunUnregisterJob(
128 const GURL& pattern,
129 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
130 scoped_refptr<ServiceWorkerRegistration> FindRegistrationForPattern(
131 const GURL& pattern,
132 ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
133 scoped_ptr<ServiceWorkerProviderHost> CreateControllee();
135 TestBrowserThreadBundle browser_thread_bundle_;
136 scoped_ptr<EmbeddedWorkerTestHelper> helper_;
137 int render_process_id_;
140 scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob(
141 const GURL& pattern,
142 const GURL& script_url,
143 ServiceWorkerStatusCode expected_status) {
144 scoped_refptr<ServiceWorkerRegistration> registration;
145 bool called;
146 job_coordinator()->Register(
147 pattern, script_url, NULL,
148 SaveRegistration(expected_status, &called, &registration));
149 EXPECT_FALSE(called);
150 base::RunLoop().RunUntilIdle();
151 EXPECT_TRUE(called);
152 return registration;
155 void ServiceWorkerJobTest::RunUnregisterJob(
156 const GURL& pattern,
157 ServiceWorkerStatusCode expected_status) {
158 bool called;
159 job_coordinator()->Unregister(pattern,
160 SaveUnregistration(expected_status, &called));
161 EXPECT_FALSE(called);
162 base::RunLoop().RunUntilIdle();
163 EXPECT_TRUE(called);
166 scoped_refptr<ServiceWorkerRegistration>
167 ServiceWorkerJobTest::FindRegistrationForPattern(
168 const GURL& pattern,
169 ServiceWorkerStatusCode expected_status) {
170 bool called;
171 scoped_refptr<ServiceWorkerRegistration> registration;
172 storage()->FindRegistrationForPattern(
173 pattern,
174 SaveFoundRegistration(expected_status, &called, &registration));
176 EXPECT_FALSE(called);
177 base::RunLoop().RunUntilIdle();
178 EXPECT_TRUE(called);
179 return registration;
182 scoped_ptr<ServiceWorkerProviderHost> ServiceWorkerJobTest::CreateControllee() {
183 return scoped_ptr<ServiceWorkerProviderHost>(new ServiceWorkerProviderHost(
184 33 /* dummy render_process id */, MSG_ROUTING_NONE /* render_frame_id */,
185 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
186 helper_->context()->AsWeakPtr(), NULL));
189 TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
190 scoped_refptr<ServiceWorkerRegistration> original_registration =
191 RunRegisterJob(GURL("http://www.example.com/"),
192 GURL("http://www.example.com/service_worker.js"));
193 bool called;
194 scoped_refptr<ServiceWorkerRegistration> registration1;
195 storage()->FindRegistrationForDocument(
196 GURL("http://www.example.com/"),
197 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
198 scoped_refptr<ServiceWorkerRegistration> registration2;
199 storage()->FindRegistrationForDocument(
200 GURL("http://www.example.com/"),
201 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
202 base::RunLoop().RunUntilIdle();
203 EXPECT_TRUE(called);
204 ASSERT_TRUE(registration1.get());
205 ASSERT_EQ(registration1, original_registration);
206 ASSERT_EQ(registration1, registration2);
209 TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
210 bool called;
211 scoped_refptr<ServiceWorkerRegistration> original_registration =
212 RunRegisterJob(GURL("http://www.example.com/"),
213 GURL("http://www.example.com/service_worker.js"));
214 ASSERT_NE(static_cast<ServiceWorkerRegistration*>(NULL),
215 original_registration.get());
217 scoped_refptr<ServiceWorkerRegistration> registration1;
218 storage()->FindRegistrationForDocument(
219 GURL("http://www.example.com/one"),
220 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
221 base::RunLoop().RunUntilIdle();
222 EXPECT_TRUE(called);
224 scoped_refptr<ServiceWorkerRegistration> registration2;
225 storage()->FindRegistrationForDocument(
226 GURL("http://www.example.com/two"),
227 SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
228 base::RunLoop().RunUntilIdle();
229 EXPECT_TRUE(called);
230 ASSERT_EQ(registration1, original_registration);
231 ASSERT_EQ(registration1, registration2);
234 TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
235 bool called1;
236 scoped_refptr<ServiceWorkerRegistration> original_registration1;
237 job_coordinator()->Register(
238 GURL("http://www.example.com/one/"),
239 GURL("http://www.example.com/service_worker.js"),
240 NULL,
241 SaveRegistration(SERVICE_WORKER_OK, &called1, &original_registration1));
243 bool called2;
244 scoped_refptr<ServiceWorkerRegistration> original_registration2;
245 job_coordinator()->Register(
246 GURL("http://www.example.com/two/"),
247 GURL("http://www.example.com/service_worker.js"),
248 NULL,
249 SaveRegistration(SERVICE_WORKER_OK, &called2, &original_registration2));
251 EXPECT_FALSE(called1);
252 EXPECT_FALSE(called2);
253 base::RunLoop().RunUntilIdle();
254 EXPECT_TRUE(called2);
255 EXPECT_TRUE(called1);
257 scoped_refptr<ServiceWorkerRegistration> registration1;
258 storage()->FindRegistrationForDocument(
259 GURL("http://www.example.com/one/"),
260 SaveFoundRegistration(SERVICE_WORKER_OK, &called1, &registration1));
261 scoped_refptr<ServiceWorkerRegistration> registration2;
262 storage()->FindRegistrationForDocument(
263 GURL("http://www.example.com/two/"),
264 SaveFoundRegistration(SERVICE_WORKER_OK, &called2, &registration2));
266 base::RunLoop().RunUntilIdle();
267 EXPECT_TRUE(called2);
268 EXPECT_TRUE(called1);
269 ASSERT_NE(registration1, registration2);
272 // Make sure basic registration is working.
273 TEST_F(ServiceWorkerJobTest, Register) {
274 scoped_refptr<ServiceWorkerRegistration> registration =
275 RunRegisterJob(GURL("http://www.example.com/"),
276 GURL("http://www.example.com/service_worker.js"));
278 ASSERT_NE(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
281 // Make sure registrations are cleaned up when they are unregistered.
282 TEST_F(ServiceWorkerJobTest, Unregister) {
283 GURL pattern("http://www.example.com/");
285 scoped_refptr<ServiceWorkerRegistration> registration =
286 RunRegisterJob(pattern, GURL("http://www.example.com/service_worker.js"));
288 RunUnregisterJob(pattern);
290 ASSERT_TRUE(registration->HasOneRef());
292 registration = FindRegistrationForPattern(pattern,
293 SERVICE_WORKER_ERROR_NOT_FOUND);
295 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
298 TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
299 GURL pattern("http://www.example.com/");
301 RunUnregisterJob(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
304 // Make sure registering a new script creates a new version and shares an
305 // existing registration.
306 TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
307 GURL pattern("http://www.example.com/");
309 scoped_refptr<ServiceWorkerRegistration> old_registration =
310 RunRegisterJob(pattern, GURL("http://www.example.com/service_worker.js"));
312 scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern =
313 FindRegistrationForPattern(pattern);
315 ASSERT_EQ(old_registration, old_registration_by_pattern);
316 old_registration_by_pattern = NULL;
318 scoped_refptr<ServiceWorkerRegistration> new_registration =
319 RunRegisterJob(pattern,
320 GURL("http://www.example.com/service_worker_new.js"));
322 ASSERT_EQ(old_registration, new_registration);
324 scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern =
325 FindRegistrationForPattern(pattern);
327 ASSERT_EQ(new_registration, new_registration_by_pattern);
330 // Make sure that when registering a duplicate pattern+script_url
331 // combination, that the same registration is used.
332 TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
333 GURL pattern("http://www.example.com/");
334 GURL script_url("http://www.example.com/service_worker.js");
336 scoped_refptr<ServiceWorkerRegistration> old_registration =
337 RunRegisterJob(pattern, script_url);
339 scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern =
340 FindRegistrationForPattern(pattern);
342 ASSERT_TRUE(old_registration_by_pattern.get());
344 scoped_refptr<ServiceWorkerRegistration> new_registration =
345 RunRegisterJob(pattern, script_url);
347 ASSERT_EQ(old_registration, new_registration);
349 ASSERT_FALSE(old_registration->HasOneRef());
351 scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern =
352 FindRegistrationForPattern(pattern);
354 ASSERT_EQ(new_registration, old_registration);
357 class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
358 public:
359 explicit FailToStartWorkerTestHelper(int mock_render_process_id)
360 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id) {}
362 void OnStartWorker(int embedded_worker_id,
363 int64 service_worker_version_id,
364 const GURL& scope,
365 const GURL& script_url,
366 bool pause_after_download) override {
367 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
368 registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
372 TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
373 helper_.reset(new FailToStartWorkerTestHelper(render_process_id_));
375 scoped_refptr<ServiceWorkerRegistration> registration =
376 RunRegisterJob(GURL("http://www.example.com/"),
377 GURL("http://www.example.com/service_worker.js"),
378 SERVICE_WORKER_ERROR_START_WORKER_FAILED);
380 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
383 // Register and then unregister the pattern, in parallel. Job coordinator should
384 // process jobs until the last job.
385 TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
386 GURL pattern("http://www.example.com/");
387 GURL script_url("http://www.example.com/service_worker.js");
389 bool registration_called = false;
390 scoped_refptr<ServiceWorkerRegistration> registration;
391 job_coordinator()->Register(
392 pattern,
393 script_url,
394 NULL,
395 SaveRegistration(SERVICE_WORKER_OK, &registration_called, &registration));
397 bool unregistration_called = false;
398 job_coordinator()->Unregister(
399 pattern,
400 SaveUnregistration(SERVICE_WORKER_OK, &unregistration_called));
402 ASSERT_FALSE(registration_called);
403 ASSERT_FALSE(unregistration_called);
404 base::RunLoop().RunUntilIdle();
405 ASSERT_TRUE(registration_called);
406 ASSERT_TRUE(unregistration_called);
408 registration = FindRegistrationForPattern(pattern,
409 SERVICE_WORKER_ERROR_NOT_FOUND);
411 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
414 // Register conflicting scripts for the same pattern. The most recent
415 // registration should win, and the old registration should have been
416 // shutdown.
417 TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
418 GURL pattern("http://www.example.com/");
420 GURL script_url1("http://www.example.com/service_worker1.js");
421 bool registration1_called = false;
422 scoped_refptr<ServiceWorkerRegistration> registration1;
423 job_coordinator()->Register(
424 pattern,
425 script_url1,
426 NULL,
427 SaveRegistration(
428 SERVICE_WORKER_OK, &registration1_called, &registration1));
430 GURL script_url2("http://www.example.com/service_worker2.js");
431 bool registration2_called = false;
432 scoped_refptr<ServiceWorkerRegistration> registration2;
433 job_coordinator()->Register(
434 pattern,
435 script_url2,
436 NULL,
437 SaveRegistration(
438 SERVICE_WORKER_OK, &registration2_called, &registration2));
440 ASSERT_FALSE(registration1_called);
441 ASSERT_FALSE(registration2_called);
442 base::RunLoop().RunUntilIdle();
443 ASSERT_TRUE(registration1_called);
444 ASSERT_TRUE(registration2_called);
446 scoped_refptr<ServiceWorkerRegistration> registration =
447 FindRegistrationForPattern(pattern);
449 ASSERT_EQ(registration2, registration);
452 // Register the exact same pattern + script. Requests should be
453 // coalesced such that both callers get the exact same registration
454 // object.
455 TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
456 GURL pattern("http://www.example.com/");
458 GURL script_url("http://www.example.com/service_worker1.js");
459 bool registration1_called = false;
460 scoped_refptr<ServiceWorkerRegistration> registration1;
461 job_coordinator()->Register(
462 pattern,
463 script_url,
464 NULL,
465 SaveRegistration(
466 SERVICE_WORKER_OK, &registration1_called, &registration1));
468 bool registration2_called = false;
469 scoped_refptr<ServiceWorkerRegistration> registration2;
470 job_coordinator()->Register(
471 pattern,
472 script_url,
473 NULL,
474 SaveRegistration(
475 SERVICE_WORKER_OK, &registration2_called, &registration2));
477 ASSERT_FALSE(registration1_called);
478 ASSERT_FALSE(registration2_called);
479 base::RunLoop().RunUntilIdle();
480 ASSERT_TRUE(registration1_called);
481 ASSERT_TRUE(registration2_called);
483 ASSERT_EQ(registration1, registration2);
485 scoped_refptr<ServiceWorkerRegistration> registration =
486 FindRegistrationForPattern(pattern);
488 ASSERT_EQ(registration, registration1);
491 // Call simulataneous unregister calls.
492 TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
493 GURL pattern("http://www.example.com/");
495 GURL script_url("http://www.example.com/service_worker.js");
496 bool unregistration1_called = false;
497 job_coordinator()->Unregister(
498 pattern,
499 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
500 &unregistration1_called));
502 bool unregistration2_called = false;
503 job_coordinator()->Unregister(
504 pattern,
505 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
506 &unregistration2_called));
508 ASSERT_FALSE(unregistration1_called);
509 ASSERT_FALSE(unregistration2_called);
510 base::RunLoop().RunUntilIdle();
511 ASSERT_TRUE(unregistration1_called);
512 ASSERT_TRUE(unregistration2_called);
514 // There isn't really a way to test that they are being coalesced,
515 // but we can make sure they can exist simultaneously without
516 // crashing.
517 scoped_refptr<ServiceWorkerRegistration> registration =
518 FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
520 ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
523 TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
524 GURL pattern1("http://www1.example.com/");
525 GURL pattern2("http://www2.example.com/");
526 GURL script_url1("http://www1.example.com/service_worker.js");
527 GURL script_url2("http://www2.example.com/service_worker.js");
529 bool registration_called1 = false;
530 scoped_refptr<ServiceWorkerRegistration> registration1;
531 job_coordinator()->Register(
532 pattern1,
533 script_url1,
534 NULL,
535 SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
536 &registration_called1, &registration1));
538 bool registration_called2 = false;
539 scoped_refptr<ServiceWorkerRegistration> registration2;
540 job_coordinator()->Register(
541 pattern2,
542 script_url2,
543 NULL,
544 SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
545 &registration_called2, &registration2));
547 ASSERT_FALSE(registration_called1);
548 ASSERT_FALSE(registration_called2);
549 job_coordinator()->AbortAll();
551 base::RunLoop().RunUntilIdle();
552 ASSERT_TRUE(registration_called1);
553 ASSERT_TRUE(registration_called2);
555 bool find_called1 = false;
556 storage()->FindRegistrationForPattern(
557 pattern1,
558 SaveFoundRegistration(
559 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called1, &registration1));
561 bool find_called2 = false;
562 storage()->FindRegistrationForPattern(
563 pattern2,
564 SaveFoundRegistration(
565 SERVICE_WORKER_ERROR_NOT_FOUND, &find_called2, &registration2));
567 base::RunLoop().RunUntilIdle();
568 ASSERT_TRUE(find_called1);
569 ASSERT_TRUE(find_called2);
570 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration1);
571 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration2);
574 TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
575 GURL pattern1("http://www1.example.com/");
576 GURL pattern2("http://www2.example.com/");
578 bool unregistration_called1 = false;
579 scoped_refptr<ServiceWorkerRegistration> registration1;
580 job_coordinator()->Unregister(
581 pattern1,
582 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
583 &unregistration_called1));
585 bool unregistration_called2 = false;
586 job_coordinator()->Unregister(
587 pattern2,
588 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
589 &unregistration_called2));
591 ASSERT_FALSE(unregistration_called1);
592 ASSERT_FALSE(unregistration_called2);
593 job_coordinator()->AbortAll();
595 base::RunLoop().RunUntilIdle();
596 ASSERT_TRUE(unregistration_called1);
597 ASSERT_TRUE(unregistration_called2);
600 TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
601 GURL pattern("http://www.example.com/");
602 GURL script_url("http://www.example.com/service_worker.js");
604 bool registration_called = false;
605 scoped_refptr<ServiceWorkerRegistration> registration;
606 job_coordinator()->Register(
607 pattern,
608 script_url,
609 NULL,
610 SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
611 &registration_called, &registration));
613 bool unregistration_called = false;
614 job_coordinator()->Unregister(
615 pattern,
616 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
617 &unregistration_called));
619 ASSERT_FALSE(registration_called);
620 ASSERT_FALSE(unregistration_called);
621 job_coordinator()->AbortAll();
623 base::RunLoop().RunUntilIdle();
624 ASSERT_TRUE(registration_called);
625 ASSERT_TRUE(unregistration_called);
627 registration = FindRegistrationForPattern(pattern,
628 SERVICE_WORKER_ERROR_NOT_FOUND);
630 EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
633 // Tests that the waiting worker enters the 'redundant' state upon
634 // unregistration.
635 TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
636 GURL script_url("http://www.example.com/service_worker.js");
637 scoped_refptr<ServiceWorkerRegistration> registration =
638 RunRegisterJob(GURL("http://www.example.com/"), script_url);
639 ASSERT_TRUE(registration.get());
641 // Manually create the waiting worker since there is no way to become a
642 // waiting worker until Update is implemented.
643 scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
644 registration.get(), script_url, 1L, helper_->context()->AsWeakPtr());
645 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
646 version->StartWorker(CreateReceiverOnCurrentThread(&status));
647 base::RunLoop().RunUntilIdle();
648 ASSERT_EQ(SERVICE_WORKER_OK, status);
650 version->SetStatus(ServiceWorkerVersion::INSTALLED);
651 registration->SetWaitingVersion(version.get());
652 EXPECT_EQ(ServiceWorkerVersion::RUNNING,
653 version->running_status());
654 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
656 RunUnregisterJob(GURL("http://www.example.com/"));
658 // The version should be stopped since there is no controllee after
659 // unregistration.
660 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
661 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
664 // Tests that the active worker enters the 'redundant' state upon
665 // unregistration.
666 TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
667 scoped_refptr<ServiceWorkerRegistration> registration =
668 RunRegisterJob(GURL("http://www.example.com/"),
669 GURL("http://www.example.com/service_worker.js"));
670 ASSERT_TRUE(registration.get());
672 scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
673 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
674 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
676 RunUnregisterJob(GURL("http://www.example.com/"));
678 // The version should be stopped since there is no controllee after
679 // unregistration.
680 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
681 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
684 // Tests that the active worker enters the 'redundant' state upon
685 // unregistration.
686 TEST_F(ServiceWorkerJobTest,
687 UnregisterActiveSetsRedundant_WaitForNoControllee) {
688 scoped_refptr<ServiceWorkerRegistration> registration =
689 RunRegisterJob(GURL("http://www.example.com/"),
690 GURL("http://www.example.com/service_worker.js"));
691 ASSERT_TRUE(registration.get());
693 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
694 registration->active_version()->AddControllee(host.get());
696 scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
697 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
698 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
700 RunUnregisterJob(GURL("http://www.example.com/"));
702 // The version should be running since there is still a controllee.
703 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
704 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
706 registration->active_version()->RemoveControllee(host.get());
707 base::RunLoop().RunUntilIdle();
709 // The version should be stopped since there is no controllee.
710 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
711 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
714 namespace { // Helpers for the update job tests.
716 const GURL kNoChangeOrigin("http://nochange/");
717 const GURL kNewVersionOrigin("http://newversion/");
718 const std::string kScope("scope/");
719 const std::string kScript("script.js");
721 void RunNestedUntilIdle() {
722 base::MessageLoop::ScopedNestableTaskAllower allow(
723 base::MessageLoop::current());
724 base::MessageLoop::current()->RunUntilIdle();
727 void OnIOComplete(int* rv_out, int rv) {
728 *rv_out = rv;
731 void WriteResponse(
732 ServiceWorkerStorage* storage, int64 id,
733 const std::string& headers,
734 IOBuffer* body, int length) {
735 scoped_ptr<ServiceWorkerResponseWriter> writer =
736 storage->CreateResponseWriter(id);
738 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
739 info->request_time = base::Time::Now();
740 info->response_time = base::Time::Now();
741 info->was_cached = false;
742 info->headers = new net::HttpResponseHeaders(headers);
743 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
744 new HttpResponseInfoIOBuffer(info.release());
746 int rv = -1234;
747 writer->WriteInfo(info_buffer.get(), base::Bind(&OnIOComplete, &rv));
748 RunNestedUntilIdle();
749 EXPECT_LT(0, rv);
751 rv = -1234;
752 writer->WriteData(body, length,
753 base::Bind(&OnIOComplete, &rv));
754 RunNestedUntilIdle();
755 EXPECT_EQ(length, rv);
758 void WriteStringResponse(
759 ServiceWorkerStorage* storage, int64 id,
760 const std::string& body) {
761 scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
762 const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
763 std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
764 WriteResponse(storage, id, headers, body_buffer.get(), body.length());
767 class UpdateJobTestHelper
768 : public EmbeddedWorkerTestHelper,
769 public ServiceWorkerRegistration::Listener,
770 public ServiceWorkerVersion::Listener {
771 public:
772 struct AttributeChangeLogEntry {
773 int64 registration_id;
774 ChangedVersionAttributesMask mask;
775 ServiceWorkerRegistrationInfo info;
778 struct StateChangeLogEntry {
779 int64 version_id;
780 ServiceWorkerVersion::Status status;
783 UpdateJobTestHelper(int mock_render_process_id)
784 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id),
785 update_found_(false) {}
786 ~UpdateJobTestHelper() override {
787 if (registration_.get())
788 registration_->RemoveListener(this);
791 ServiceWorkerStorage* storage() { return context()->storage(); }
792 ServiceWorkerJobCoordinator* job_coordinator() {
793 return context()->job_coordinator();
796 scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration(
797 const GURL& test_origin) {
798 scoped_refptr<ServiceWorkerRegistration> registration;
799 bool called = false;
800 job_coordinator()->Register(
801 test_origin.Resolve(kScope),
802 test_origin.Resolve(kScript),
803 NULL,
804 SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
805 base::RunLoop().RunUntilIdle();
806 EXPECT_TRUE(called);
807 EXPECT_TRUE(registration.get());
808 EXPECT_TRUE(registration->active_version());
809 EXPECT_FALSE(registration->installing_version());
810 EXPECT_FALSE(registration->waiting_version());
811 registration_ = registration;
812 return registration;
815 // EmbeddedWorkerTestHelper overrides
816 void OnStartWorker(int embedded_worker_id,
817 int64 version_id,
818 const GURL& scope,
819 const GURL& script,
820 bool pause_after_download) override {
821 const std::string kMockScriptBody = "mock_script";
822 const uint64 kMockScriptSize = 19284;
823 ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
824 ASSERT_TRUE(version);
825 version->AddListener(this);
827 if (!pause_after_download) {
828 // Spoof caching the script for the initial version.
829 int64 resource_id = storage()->NewResourceId();
830 version->script_cache_map()->NotifyStartedCaching(script, resource_id);
831 WriteStringResponse(storage(), resource_id, kMockScriptBody);
832 version->script_cache_map()->NotifyFinishedCaching(
833 script, kMockScriptSize, net::URLRequestStatus(), std::string());
834 } else {
835 // Spoof caching the script for the new version.
836 int64 resource_id = storage()->NewResourceId();
837 version->script_cache_map()->NotifyStartedCaching(script, resource_id);
838 if (script.GetOrigin() == kNoChangeOrigin)
839 WriteStringResponse(storage(), resource_id, kMockScriptBody);
840 else
841 WriteStringResponse(storage(), resource_id, "mock_different_script");
842 version->script_cache_map()->NotifyFinishedCaching(
843 script, kMockScriptSize, net::URLRequestStatus(), std::string());
845 EmbeddedWorkerTestHelper::OnStartWorker(
846 embedded_worker_id, version_id, scope, script, pause_after_download);
849 // ServiceWorkerRegistration::Listener overrides
850 void OnVersionAttributesChanged(
851 ServiceWorkerRegistration* registration,
852 ChangedVersionAttributesMask changed_mask,
853 const ServiceWorkerRegistrationInfo& info) override {
854 AttributeChangeLogEntry entry;
855 entry.registration_id = registration->id();
856 entry.mask = changed_mask;
857 entry.info = info;
858 attribute_change_log_.push_back(entry);
861 void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
862 NOTREACHED();
865 void OnUpdateFound(ServiceWorkerRegistration* registration) override {
866 ASSERT_FALSE(update_found_);
867 update_found_ = true;
870 // ServiceWorkerVersion::Listener overrides
871 void OnVersionStateChanged(ServiceWorkerVersion* version) override {
872 StateChangeLogEntry entry;
873 entry.version_id = version->version_id();
874 entry.status = version->status();
875 state_change_log_.push_back(entry);
878 scoped_refptr<ServiceWorkerRegistration> registration_;
880 std::vector<AttributeChangeLogEntry> attribute_change_log_;
881 std::vector<StateChangeLogEntry> state_change_log_;
882 bool update_found_;
885 } // namespace
887 TEST_F(ServiceWorkerJobTest, Update_NoChange) {
888 UpdateJobTestHelper* update_helper =
889 new UpdateJobTestHelper(render_process_id_);
890 helper_.reset(update_helper);
891 scoped_refptr<ServiceWorkerRegistration> registration =
892 update_helper->SetupInitialRegistration(kNoChangeOrigin);
893 ASSERT_TRUE(registration.get());
894 ASSERT_EQ(4u, update_helper->state_change_log_.size());
895 EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
896 update_helper->state_change_log_[0].status);
897 EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
898 update_helper->state_change_log_[1].status);
899 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
900 update_helper->state_change_log_[2].status);
901 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
902 update_helper->state_change_log_[3].status);
903 update_helper->state_change_log_.clear();
905 // Run the update job.
906 registration->AddListener(update_helper);
907 scoped_refptr<ServiceWorkerVersion> first_version =
908 registration->active_version();
909 first_version->StartUpdate();
910 base::RunLoop().RunUntilIdle();
912 // Verify results.
913 ASSERT_TRUE(registration->active_version());
914 EXPECT_EQ(first_version.get(), registration->active_version());
915 EXPECT_FALSE(registration->installing_version());
916 EXPECT_FALSE(registration->waiting_version());
917 EXPECT_TRUE(update_helper->attribute_change_log_.empty());
918 ASSERT_EQ(1u, update_helper->state_change_log_.size());
919 EXPECT_NE(registration->active_version()->version_id(),
920 update_helper->state_change_log_[0].version_id);
921 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
922 update_helper->state_change_log_[0].status);
923 EXPECT_FALSE(update_helper->update_found_);
926 TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
927 UpdateJobTestHelper* update_helper =
928 new UpdateJobTestHelper(render_process_id_);
929 helper_.reset(update_helper);
930 scoped_refptr<ServiceWorkerRegistration> registration =
931 update_helper->SetupInitialRegistration(kNewVersionOrigin);
932 ASSERT_TRUE(registration.get());
933 update_helper->state_change_log_.clear();
935 // Run the update job.
936 registration->AddListener(update_helper);
937 scoped_refptr<ServiceWorkerVersion> first_version =
938 registration->active_version();
939 first_version->StartUpdate();
940 base::RunLoop().RunUntilIdle();
942 // Verify results.
943 ASSERT_TRUE(registration->active_version());
944 EXPECT_NE(first_version.get(), registration->active_version());
945 EXPECT_FALSE(registration->installing_version());
946 EXPECT_FALSE(registration->waiting_version());
947 ASSERT_EQ(3u, update_helper->attribute_change_log_.size());
949 UpdateJobTestHelper::AttributeChangeLogEntry entry;
950 entry = update_helper->attribute_change_log_[0];
951 EXPECT_TRUE(entry.mask.installing_changed());
952 EXPECT_FALSE(entry.mask.waiting_changed());
953 EXPECT_FALSE(entry.mask.active_changed());
954 EXPECT_NE(entry.info.installing_version.version_id,
955 kInvalidServiceWorkerVersionId);
956 EXPECT_EQ(entry.info.waiting_version.version_id,
957 kInvalidServiceWorkerVersionId);
958 EXPECT_NE(entry.info.active_version.version_id,
959 kInvalidServiceWorkerVersionId);
961 entry = update_helper->attribute_change_log_[1];
962 EXPECT_TRUE(entry.mask.installing_changed());
963 EXPECT_TRUE(entry.mask.waiting_changed());
964 EXPECT_FALSE(entry.mask.active_changed());
965 EXPECT_EQ(entry.info.installing_version.version_id,
966 kInvalidServiceWorkerVersionId);
967 EXPECT_NE(entry.info.waiting_version.version_id,
968 kInvalidServiceWorkerVersionId);
969 EXPECT_NE(entry.info.active_version.version_id,
970 kInvalidServiceWorkerVersionId);
972 entry = update_helper->attribute_change_log_[2];
973 EXPECT_FALSE(entry.mask.installing_changed());
974 EXPECT_TRUE(entry.mask.waiting_changed());
975 EXPECT_TRUE(entry.mask.active_changed());
976 EXPECT_EQ(entry.info.installing_version.version_id,
977 kInvalidServiceWorkerVersionId);
978 EXPECT_EQ(entry.info.waiting_version.version_id,
979 kInvalidServiceWorkerVersionId);
980 EXPECT_NE(entry.info.active_version.version_id,
981 kInvalidServiceWorkerVersionId);
983 // expected version state transitions:
984 // new.installing, new.installed,
985 // old.redundant,
986 // new.activating, new.activated
987 ASSERT_EQ(5u, update_helper->state_change_log_.size());
989 EXPECT_EQ(registration->active_version()->version_id(),
990 update_helper->state_change_log_[0].version_id);
991 EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
992 update_helper->state_change_log_[0].status);
994 EXPECT_EQ(registration->active_version()->version_id(),
995 update_helper->state_change_log_[1].version_id);
996 EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
997 update_helper->state_change_log_[1].status);
999 EXPECT_EQ(first_version->version_id(),
1000 update_helper->state_change_log_[2].version_id);
1001 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
1002 update_helper->state_change_log_[2].status);
1004 EXPECT_EQ(registration->active_version()->version_id(),
1005 update_helper->state_change_log_[3].version_id);
1006 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
1007 update_helper->state_change_log_[3].status);
1009 EXPECT_EQ(registration->active_version()->version_id(),
1010 update_helper->state_change_log_[4].version_id);
1011 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1012 update_helper->state_change_log_[4].status);
1014 EXPECT_TRUE(update_helper->update_found_);
1017 TEST_F(ServiceWorkerJobTest, Update_NewestVersionChanged) {
1018 scoped_refptr<ServiceWorkerRegistration> registration =
1019 RunRegisterJob(GURL("http://www.example.com/one/"),
1020 GURL("http://www.example.com/service_worker.js"));
1022 ServiceWorkerVersion* active_version = registration->active_version();
1024 // Queue an Update, it should abort when it starts and sees the new version.
1025 job_coordinator()->Update(registration.get(), false);
1027 // Add a waiting version with new script.
1028 scoped_refptr<ServiceWorkerVersion> version =
1029 new ServiceWorkerVersion(registration.get(),
1030 GURL("http://www.example.com/new_worker.js"),
1031 2L /* dummy version id */,
1032 helper_->context()->AsWeakPtr());
1033 registration->SetWaitingVersion(version.get());
1035 base::RunLoop().RunUntilIdle();
1037 // Verify the registration was not modified by the Update.
1038 EXPECT_EQ(active_version, registration->active_version());
1039 EXPECT_EQ(version.get(), registration->waiting_version());
1040 EXPECT_EQ(NULL, registration->installing_version());
1043 TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
1044 bool called;
1045 scoped_refptr<ServiceWorkerRegistration> registration =
1046 RunRegisterJob(GURL("http://www.example.com/one/"),
1047 GURL("http://www.example.com/service_worker.js"));
1049 // Add a controllee and queue an unregister to force the uninstalling state.
1050 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1051 ServiceWorkerVersion* active_version = registration->active_version();
1052 active_version->AddControllee(host.get());
1053 job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
1054 SaveUnregistration(SERVICE_WORKER_OK, &called));
1056 // Update should abort after it starts and sees uninstalling.
1057 job_coordinator()->Update(registration.get(), false);
1059 EXPECT_FALSE(called);
1060 base::RunLoop().RunUntilIdle();
1061 EXPECT_TRUE(called);
1063 // Verify the registration was not modified by the Update.
1064 EXPECT_TRUE(registration->is_uninstalling());
1065 EXPECT_EQ(active_version, registration->active_version());
1066 EXPECT_EQ(NULL, registration->waiting_version());
1067 EXPECT_EQ(NULL, registration->installing_version());
1070 TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
1071 GURL pattern("http://www.example.com/one/");
1072 GURL script1("http://www.example.com/service_worker.js");
1073 GURL script2("http://www.example.com/service_worker.js?new");
1075 scoped_refptr<ServiceWorkerRegistration> registration =
1076 RunRegisterJob(pattern, script1);
1078 // Add a controllee and queue an unregister to force the uninstalling state.
1079 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1080 scoped_refptr<ServiceWorkerVersion> old_version =
1081 registration->active_version();
1082 old_version->AddControllee(host.get());
1083 RunUnregisterJob(pattern);
1085 // Register another script.
1086 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1088 EXPECT_FALSE(registration->is_uninstalling());
1089 EXPECT_EQ(old_version, registration->active_version());
1091 scoped_refptr<ServiceWorkerVersion> new_version =
1092 registration->waiting_version();
1094 // Verify the new version is installed but not activated yet.
1095 EXPECT_EQ(NULL, registration->installing_version());
1096 EXPECT_TRUE(new_version);
1097 EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
1098 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
1100 old_version->RemoveControllee(host.get());
1101 base::RunLoop().RunUntilIdle();
1103 EXPECT_FALSE(registration->is_uninstalling());
1104 EXPECT_FALSE(registration->is_uninstalled());
1106 // Verify the new version is activated.
1107 EXPECT_EQ(NULL, registration->installing_version());
1108 EXPECT_EQ(NULL, registration->waiting_version());
1109 EXPECT_EQ(new_version, registration->active_version());
1110 EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
1111 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
1114 TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
1115 GURL pattern("http://www.example.com/one/");
1116 GURL script1("http://www.example.com/service_worker.js");
1117 GURL script2("http://www.example.com/service_worker.js?new");
1119 scoped_refptr<ServiceWorkerRegistration> registration =
1120 RunRegisterJob(pattern, script1);
1122 // Add a controllee and queue an unregister to force the uninstalling state.
1123 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1124 scoped_refptr<ServiceWorkerVersion> old_version =
1125 registration->active_version();
1126 old_version->AddControllee(host.get());
1127 RunUnregisterJob(pattern);
1129 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1131 EXPECT_EQ(registration, FindRegistrationForPattern(pattern));
1132 scoped_refptr<ServiceWorkerVersion> new_version =
1133 registration->waiting_version();
1134 ASSERT_TRUE(new_version);
1136 // Unregister the registration (but it's still live).
1137 RunUnregisterJob(pattern);
1138 // Now it's not found in the storage.
1139 RunUnregisterJob(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
1141 FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
1142 EXPECT_TRUE(registration->is_uninstalling());
1143 EXPECT_EQ(old_version, registration->active_version());
1145 EXPECT_EQ(ServiceWorkerVersion::RUNNING, old_version->running_status());
1146 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, old_version->status());
1147 EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
1148 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
1150 old_version->RemoveControllee(host.get());
1151 base::RunLoop().RunUntilIdle();
1153 EXPECT_FALSE(registration->is_uninstalling());
1154 EXPECT_TRUE(registration->is_uninstalled());
1156 EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
1157 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
1158 EXPECT_EQ(ServiceWorkerVersion::STOPPED, new_version->running_status());
1159 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, new_version->status());
1162 TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
1163 GURL pattern("http://www.example.com/one/");
1164 GURL script1("http://www.example.com/service_worker.js");
1165 GURL script2("http://www.example.com/service_worker.js?new");
1167 scoped_refptr<ServiceWorkerRegistration> registration =
1168 RunRegisterJob(pattern, script1);
1170 // Add a controllee and queue an unregister to force the uninstalling state.
1171 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1172 scoped_refptr<ServiceWorkerVersion> old_version =
1173 registration->active_version();
1174 old_version->AddControllee(host.get());
1175 RunUnregisterJob(pattern);
1177 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1179 scoped_refptr<ServiceWorkerVersion> new_version =
1180 registration->waiting_version();
1181 ASSERT_TRUE(new_version);
1183 RunUnregisterJob(pattern);
1185 EXPECT_TRUE(registration->is_uninstalling());
1187 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1189 EXPECT_FALSE(registration->is_uninstalling());
1190 EXPECT_EQ(new_version, registration->waiting_version());
1192 old_version->RemoveControllee(host.get());
1193 base::RunLoop().RunUntilIdle();
1195 EXPECT_FALSE(registration->is_uninstalling());
1196 EXPECT_FALSE(registration->is_uninstalled());
1198 // Verify the new version is activated.
1199 EXPECT_EQ(NULL, registration->installing_version());
1200 EXPECT_EQ(NULL, registration->waiting_version());
1201 EXPECT_EQ(new_version, registration->active_version());
1202 EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
1203 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
1206 TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
1207 GURL pattern("http://www.example.com/one/");
1208 GURL script1("http://www.example.com/service_worker.js?first");
1209 GURL script2("http://www.example.com/service_worker.js?second");
1210 GURL script3("http://www.example.com/service_worker.js?third");
1212 scoped_refptr<ServiceWorkerRegistration> registration =
1213 RunRegisterJob(pattern, script1);
1215 // Add a controllee and queue an unregister to force the uninstalling state.
1216 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1217 scoped_refptr<ServiceWorkerVersion> first_version =
1218 registration->active_version();
1219 first_version->AddControllee(host.get());
1220 RunUnregisterJob(pattern);
1222 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1224 scoped_refptr<ServiceWorkerVersion> second_version =
1225 registration->waiting_version();
1226 ASSERT_TRUE(second_version);
1228 RunUnregisterJob(pattern);
1230 EXPECT_TRUE(registration->is_uninstalling());
1232 EXPECT_EQ(registration, RunRegisterJob(pattern, script3));
1234 scoped_refptr<ServiceWorkerVersion> third_version =
1235 registration->waiting_version();
1236 ASSERT_TRUE(third_version);
1238 EXPECT_FALSE(registration->is_uninstalling());
1239 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, second_version->status());
1241 first_version->RemoveControllee(host.get());
1242 base::RunLoop().RunUntilIdle();
1244 EXPECT_FALSE(registration->is_uninstalling());
1245 EXPECT_FALSE(registration->is_uninstalled());
1247 // Verify the new version is activated.
1248 EXPECT_EQ(NULL, registration->installing_version());
1249 EXPECT_EQ(NULL, registration->waiting_version());
1250 EXPECT_EQ(third_version, registration->active_version());
1251 EXPECT_EQ(ServiceWorkerVersion::RUNNING, third_version->running_status());
1252 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, third_version->status());
1255 class EventCallbackHelper : public EmbeddedWorkerTestHelper {
1256 public:
1257 explicit EventCallbackHelper(int mock_render_process_id)
1258 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id),
1259 install_event_result_(blink::WebServiceWorkerEventResultCompleted),
1260 activate_event_result_(blink::WebServiceWorkerEventResultCompleted) {}
1262 void OnInstallEvent(int embedded_worker_id,
1263 int request_id) override {
1264 if (!install_callback_.is_null())
1265 install_callback_.Run();
1266 SimulateSend(
1267 new ServiceWorkerHostMsg_InstallEventFinished(
1268 embedded_worker_id, request_id, install_event_result_));
1270 void OnActivateEvent(int embedded_worker_id, int request_id) override {
1271 SimulateSend(
1272 new ServiceWorkerHostMsg_ActivateEventFinished(
1273 embedded_worker_id, request_id, activate_event_result_));
1276 void set_install_callback(const base::Closure& callback) {
1277 install_callback_ = callback;
1279 void set_install_event_result(blink::WebServiceWorkerEventResult result) {
1280 install_event_result_ = result;
1282 void set_activate_event_result(blink::WebServiceWorkerEventResult result) {
1283 activate_event_result_ = result;
1285 private:
1286 base::Closure install_callback_;
1287 blink::WebServiceWorkerEventResult install_event_result_;
1288 blink::WebServiceWorkerEventResult activate_event_result_;
1291 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
1292 EventCallbackHelper* helper = new EventCallbackHelper(render_process_id_);
1293 helper_.reset(helper);
1295 GURL pattern("http://www.example.com/one/");
1296 GURL script1("http://www.example.com/service_worker.js");
1297 GURL script2("http://www.example.com/service_worker.js?new");
1299 scoped_refptr<ServiceWorkerRegistration> registration =
1300 RunRegisterJob(pattern, script1);
1302 // Add a controllee and queue an unregister to force the uninstalling state.
1303 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1304 scoped_refptr<ServiceWorkerVersion> old_version =
1305 registration->active_version();
1306 old_version->AddControllee(host.get());
1307 RunUnregisterJob(pattern);
1309 // Register another script. While installing, old_version loses controllee.
1310 helper->set_install_callback(
1311 base::Bind(&ServiceWorkerVersion::RemoveControllee,
1312 old_version, host.get()));
1313 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1315 EXPECT_FALSE(registration->is_uninstalling());
1316 EXPECT_FALSE(registration->is_uninstalled());
1318 // Verify the new version is activated.
1319 scoped_refptr<ServiceWorkerVersion> new_version =
1320 registration->active_version();
1321 EXPECT_NE(old_version, new_version);
1322 EXPECT_EQ(NULL, registration->installing_version());
1323 EXPECT_EQ(NULL, registration->waiting_version());
1324 EXPECT_EQ(new_version, registration->active_version());
1325 EXPECT_EQ(ServiceWorkerVersion::RUNNING, new_version->running_status());
1326 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
1328 EXPECT_EQ(registration, FindRegistrationForPattern(pattern));
1331 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
1332 EventCallbackHelper* helper = new EventCallbackHelper(render_process_id_);
1333 helper_.reset(helper);
1335 GURL pattern("http://www.example.com/one/");
1336 GURL script1("http://www.example.com/service_worker.js");
1337 GURL script2("http://www.example.com/service_worker.js?new");
1339 scoped_refptr<ServiceWorkerRegistration> registration =
1340 RunRegisterJob(pattern, script1);
1342 // Add a controllee and queue an unregister to force the uninstalling state.
1343 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1344 scoped_refptr<ServiceWorkerVersion> old_version =
1345 registration->active_version();
1346 old_version->AddControllee(host.get());
1347 RunUnregisterJob(pattern);
1349 // Register another script that fails to install. While installing,
1350 // old_version loses controllee.
1351 helper->set_install_callback(
1352 base::Bind(&ServiceWorkerVersion::RemoveControllee,
1353 old_version, host.get()));
1354 helper->set_install_event_result(blink::WebServiceWorkerEventResultRejected);
1355 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1357 // Verify the registration was uninstalled.
1358 EXPECT_FALSE(registration->is_uninstalling());
1359 EXPECT_TRUE(registration->is_uninstalled());
1361 EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
1362 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
1364 FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
1367 TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
1368 EventCallbackHelper* helper = new EventCallbackHelper(render_process_id_);
1369 helper_.reset(helper);
1371 GURL pattern("http://www.example.com/one/");
1372 GURL script1("http://www.example.com/service_worker.js");
1373 GURL script2("http://www.example.com/service_worker.js?new");
1375 scoped_refptr<ServiceWorkerRegistration> registration =
1376 RunRegisterJob(pattern, script1);
1378 // Add a controllee and queue an unregister to force the uninstalling state.
1379 scoped_ptr<ServiceWorkerProviderHost> host = CreateControllee();
1380 scoped_refptr<ServiceWorkerVersion> old_version =
1381 registration->active_version();
1382 old_version->AddControllee(host.get());
1383 RunUnregisterJob(pattern);
1385 // Register another script that fails to activate. While installing,
1386 // old_version loses controllee.
1387 helper->set_install_callback(
1388 base::Bind(&ServiceWorkerVersion::RemoveControllee,
1389 old_version, host.get()));
1390 helper->set_activate_event_result(blink::WebServiceWorkerEventResultRejected);
1391 EXPECT_EQ(registration, RunRegisterJob(pattern, script2));
1393 // Verify the registration was uninstalled.
1394 EXPECT_FALSE(registration->is_uninstalling());
1395 EXPECT_TRUE(registration->is_uninstalled());
1397 EXPECT_EQ(ServiceWorkerVersion::STOPPED, old_version->running_status());
1398 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
1400 FindRegistrationForPattern(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
1403 } // namespace content