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"
27 using net::TestCompletionCallback
;
28 using net::WrappedIOBuffer
;
30 // Unit tests for testing all job registration tasks.
35 int kMockRenderProcessId
= 88;
37 void SaveRegistrationCallback(
38 ServiceWorkerStatusCode expected_status
,
40 scoped_refptr
<ServiceWorkerRegistration
>* registration_out
,
41 ServiceWorkerStatusCode status
,
42 const std::string
& status_message
,
43 ServiceWorkerRegistration
* registration
) {
44 EXPECT_EQ(expected_status
, status
);
46 *registration_out
= registration
;
49 void SaveFoundRegistrationCallback(
50 ServiceWorkerStatusCode expected_status
,
52 scoped_refptr
<ServiceWorkerRegistration
>* registration
,
53 ServiceWorkerStatusCode status
,
54 const scoped_refptr
<ServiceWorkerRegistration
>& result
) {
55 EXPECT_EQ(expected_status
, status
);
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
65 ServiceWorkerRegisterJob::RegistrationCallback
SaveRegistration(
66 ServiceWorkerStatusCode expected_status
,
68 scoped_refptr
<ServiceWorkerRegistration
>* registration
) {
71 &SaveRegistrationCallback
, expected_status
, called
, registration
);
74 ServiceWorkerStorage::FindRegistrationCallback
SaveFoundRegistration(
75 ServiceWorkerStatusCode expected_status
,
77 scoped_refptr
<ServiceWorkerRegistration
>* registration
) {
79 return base::Bind(&SaveFoundRegistrationCallback
,
85 void SaveUnregistrationCallback(ServiceWorkerStatusCode expected_status
,
87 int64 registration_id
,
88 ServiceWorkerStatusCode status
) {
89 EXPECT_EQ(expected_status
, status
);
93 ServiceWorkerUnregisterJob::UnregistrationCallback
SaveUnregistration(
94 ServiceWorkerStatusCode expected_status
,
97 return base::Bind(&SaveUnregistrationCallback
, expected_status
, called
);
102 class ServiceWorkerJobTest
: public testing::Test
{
104 ServiceWorkerJobTest()
105 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP
),
106 render_process_id_(kMockRenderProcessId
) {}
108 void SetUp() override
{
109 helper_
.reset(new EmbeddedWorkerTestHelper(render_process_id_
));
112 void TearDown() override
{ helper_
.reset(); }
114 ServiceWorkerContextCore
* context() const { return helper_
->context(); }
116 ServiceWorkerJobCoordinator
* job_coordinator() const {
117 return context()->job_coordinator();
119 ServiceWorkerStorage
* storage() const { return context()->storage(); }
122 scoped_refptr
<ServiceWorkerRegistration
> RunRegisterJob(
124 const GURL
& script_url
,
125 ServiceWorkerStatusCode expected_status
= SERVICE_WORKER_OK
);
126 void RunUnregisterJob(
128 ServiceWorkerStatusCode expected_status
= SERVICE_WORKER_OK
);
129 scoped_refptr
<ServiceWorkerRegistration
> FindRegistrationForPattern(
131 ServiceWorkerStatusCode expected_status
= SERVICE_WORKER_OK
);
132 scoped_ptr
<ServiceWorkerProviderHost
> CreateControllee();
134 TestBrowserThreadBundle browser_thread_bundle_
;
135 scoped_ptr
<EmbeddedWorkerTestHelper
> helper_
;
136 int render_process_id_
;
139 scoped_refptr
<ServiceWorkerRegistration
> ServiceWorkerJobTest::RunRegisterJob(
141 const GURL
& script_url
,
142 ServiceWorkerStatusCode expected_status
) {
143 scoped_refptr
<ServiceWorkerRegistration
> registration
;
145 job_coordinator()->Register(
146 pattern
, script_url
, NULL
,
147 SaveRegistration(expected_status
, &called
, ®istration
));
148 EXPECT_FALSE(called
);
149 base::RunLoop().RunUntilIdle();
154 void ServiceWorkerJobTest::RunUnregisterJob(
156 ServiceWorkerStatusCode expected_status
) {
158 job_coordinator()->Unregister(pattern
,
159 SaveUnregistration(expected_status
, &called
));
160 EXPECT_FALSE(called
);
161 base::RunLoop().RunUntilIdle();
165 scoped_refptr
<ServiceWorkerRegistration
>
166 ServiceWorkerJobTest::FindRegistrationForPattern(
168 ServiceWorkerStatusCode expected_status
) {
170 scoped_refptr
<ServiceWorkerRegistration
> registration
;
171 storage()->FindRegistrationForPattern(
173 SaveFoundRegistration(expected_status
, &called
, ®istration
));
175 EXPECT_FALSE(called
);
176 base::RunLoop().RunUntilIdle();
181 scoped_ptr
<ServiceWorkerProviderHost
> ServiceWorkerJobTest::CreateControllee() {
182 return scoped_ptr
<ServiceWorkerProviderHost
>(
183 new ServiceWorkerProviderHost(33 /* dummy render_process id */,
184 MSG_ROUTING_NONE
/* render_frame_id */,
185 1 /* dummy provider_id */,
186 SERVICE_WORKER_PROVIDER_FOR_CONTROLLEE
,
187 helper_
->context()->AsWeakPtr(),
191 TEST_F(ServiceWorkerJobTest
, SameDocumentSameRegistration
) {
192 scoped_refptr
<ServiceWorkerRegistration
> original_registration
=
193 RunRegisterJob(GURL("http://www.example.com/"),
194 GURL("http://www.example.com/service_worker.js"));
196 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
197 storage()->FindRegistrationForDocument(
198 GURL("http://www.example.com/"),
199 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration1
));
200 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
201 storage()->FindRegistrationForDocument(
202 GURL("http://www.example.com/"),
203 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration2
));
204 base::RunLoop().RunUntilIdle();
206 ASSERT_TRUE(registration1
.get());
207 ASSERT_EQ(registration1
, original_registration
);
208 ASSERT_EQ(registration1
, registration2
);
211 TEST_F(ServiceWorkerJobTest
, SameMatchSameRegistration
) {
213 scoped_refptr
<ServiceWorkerRegistration
> original_registration
=
214 RunRegisterJob(GURL("http://www.example.com/"),
215 GURL("http://www.example.com/service_worker.js"));
216 ASSERT_NE(static_cast<ServiceWorkerRegistration
*>(NULL
),
217 original_registration
.get());
219 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
220 storage()->FindRegistrationForDocument(
221 GURL("http://www.example.com/one"),
222 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration1
));
223 base::RunLoop().RunUntilIdle();
226 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
227 storage()->FindRegistrationForDocument(
228 GURL("http://www.example.com/two"),
229 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration2
));
230 base::RunLoop().RunUntilIdle();
232 ASSERT_EQ(registration1
, original_registration
);
233 ASSERT_EQ(registration1
, registration2
);
236 TEST_F(ServiceWorkerJobTest
, DifferentMatchDifferentRegistration
) {
238 scoped_refptr
<ServiceWorkerRegistration
> original_registration1
;
239 job_coordinator()->Register(
240 GURL("http://www.example.com/one/"),
241 GURL("http://www.example.com/service_worker.js"),
243 SaveRegistration(SERVICE_WORKER_OK
, &called1
, &original_registration1
));
246 scoped_refptr
<ServiceWorkerRegistration
> original_registration2
;
247 job_coordinator()->Register(
248 GURL("http://www.example.com/two/"),
249 GURL("http://www.example.com/service_worker.js"),
251 SaveRegistration(SERVICE_WORKER_OK
, &called2
, &original_registration2
));
253 EXPECT_FALSE(called1
);
254 EXPECT_FALSE(called2
);
255 base::RunLoop().RunUntilIdle();
256 EXPECT_TRUE(called2
);
257 EXPECT_TRUE(called1
);
259 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
260 storage()->FindRegistrationForDocument(
261 GURL("http://www.example.com/one/"),
262 SaveFoundRegistration(SERVICE_WORKER_OK
, &called1
, ®istration1
));
263 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
264 storage()->FindRegistrationForDocument(
265 GURL("http://www.example.com/two/"),
266 SaveFoundRegistration(SERVICE_WORKER_OK
, &called2
, ®istration2
));
268 base::RunLoop().RunUntilIdle();
269 EXPECT_TRUE(called2
);
270 EXPECT_TRUE(called1
);
271 ASSERT_NE(registration1
, registration2
);
274 // Make sure basic registration is working.
275 TEST_F(ServiceWorkerJobTest
, Register
) {
276 scoped_refptr
<ServiceWorkerRegistration
> registration
=
277 RunRegisterJob(GURL("http://www.example.com/"),
278 GURL("http://www.example.com/service_worker.js"));
280 ASSERT_NE(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
283 // Make sure registrations are cleaned up when they are unregistered.
284 TEST_F(ServiceWorkerJobTest
, Unregister
) {
285 GURL
pattern("http://www.example.com/");
287 scoped_refptr
<ServiceWorkerRegistration
> registration
=
288 RunRegisterJob(pattern
, GURL("http://www.example.com/service_worker.js"));
290 RunUnregisterJob(pattern
);
292 ASSERT_TRUE(registration
->HasOneRef());
294 registration
= FindRegistrationForPattern(pattern
,
295 SERVICE_WORKER_ERROR_NOT_FOUND
);
297 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
300 TEST_F(ServiceWorkerJobTest
, Unregister_NothingRegistered
) {
301 GURL
pattern("http://www.example.com/");
303 RunUnregisterJob(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
306 // Make sure registering a new script creates a new version and shares an
307 // existing registration.
308 TEST_F(ServiceWorkerJobTest
, RegisterNewScript
) {
309 GURL
pattern("http://www.example.com/");
311 scoped_refptr
<ServiceWorkerRegistration
> old_registration
=
312 RunRegisterJob(pattern
, GURL("http://www.example.com/service_worker.js"));
314 scoped_refptr
<ServiceWorkerRegistration
> old_registration_by_pattern
=
315 FindRegistrationForPattern(pattern
);
317 ASSERT_EQ(old_registration
, old_registration_by_pattern
);
318 old_registration_by_pattern
= NULL
;
320 scoped_refptr
<ServiceWorkerRegistration
> new_registration
=
321 RunRegisterJob(pattern
,
322 GURL("http://www.example.com/service_worker_new.js"));
324 ASSERT_EQ(old_registration
, new_registration
);
326 scoped_refptr
<ServiceWorkerRegistration
> new_registration_by_pattern
=
327 FindRegistrationForPattern(pattern
);
329 ASSERT_EQ(new_registration
, new_registration_by_pattern
);
332 // Make sure that when registering a duplicate pattern+script_url
333 // combination, that the same registration is used.
334 TEST_F(ServiceWorkerJobTest
, RegisterDuplicateScript
) {
335 GURL
pattern("http://www.example.com/");
336 GURL
script_url("http://www.example.com/service_worker.js");
338 scoped_refptr
<ServiceWorkerRegistration
> old_registration
=
339 RunRegisterJob(pattern
, script_url
);
341 scoped_refptr
<ServiceWorkerRegistration
> old_registration_by_pattern
=
342 FindRegistrationForPattern(pattern
);
344 ASSERT_TRUE(old_registration_by_pattern
.get());
346 scoped_refptr
<ServiceWorkerRegistration
> new_registration
=
347 RunRegisterJob(pattern
, script_url
);
349 ASSERT_EQ(old_registration
, new_registration
);
351 ASSERT_FALSE(old_registration
->HasOneRef());
353 scoped_refptr
<ServiceWorkerRegistration
> new_registration_by_pattern
=
354 FindRegistrationForPattern(pattern
);
356 ASSERT_EQ(new_registration
, old_registration
);
359 class FailToStartWorkerTestHelper
: public EmbeddedWorkerTestHelper
{
361 explicit FailToStartWorkerTestHelper(int mock_render_process_id
)
362 : EmbeddedWorkerTestHelper(mock_render_process_id
) {}
364 void OnStartWorker(int embedded_worker_id
,
365 int64 service_worker_version_id
,
367 const GURL
& script_url
,
368 bool pause_after_download
) override
{
369 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
370 registry()->OnWorkerStopped(worker
->process_id(), embedded_worker_id
);
374 TEST_F(ServiceWorkerJobTest
, Register_FailToStartWorker
) {
375 helper_
.reset(new FailToStartWorkerTestHelper(render_process_id_
));
377 scoped_refptr
<ServiceWorkerRegistration
> registration
=
378 RunRegisterJob(GURL("http://www.example.com/"),
379 GURL("http://www.example.com/service_worker.js"),
380 SERVICE_WORKER_ERROR_START_WORKER_FAILED
);
382 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
385 // Register and then unregister the pattern, in parallel. Job coordinator should
386 // process jobs until the last job.
387 TEST_F(ServiceWorkerJobTest
, ParallelRegUnreg
) {
388 GURL
pattern("http://www.example.com/");
389 GURL
script_url("http://www.example.com/service_worker.js");
391 bool registration_called
= false;
392 scoped_refptr
<ServiceWorkerRegistration
> registration
;
393 job_coordinator()->Register(
397 SaveRegistration(SERVICE_WORKER_OK
, ®istration_called
, ®istration
));
399 bool unregistration_called
= false;
400 job_coordinator()->Unregister(
402 SaveUnregistration(SERVICE_WORKER_OK
, &unregistration_called
));
404 ASSERT_FALSE(registration_called
);
405 ASSERT_FALSE(unregistration_called
);
406 base::RunLoop().RunUntilIdle();
407 ASSERT_TRUE(registration_called
);
408 ASSERT_TRUE(unregistration_called
);
410 registration
= FindRegistrationForPattern(pattern
,
411 SERVICE_WORKER_ERROR_NOT_FOUND
);
413 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
416 // Register conflicting scripts for the same pattern. The most recent
417 // registration should win, and the old registration should have been
419 TEST_F(ServiceWorkerJobTest
, ParallelRegNewScript
) {
420 GURL
pattern("http://www.example.com/");
422 GURL
script_url1("http://www.example.com/service_worker1.js");
423 bool registration1_called
= false;
424 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
425 job_coordinator()->Register(
430 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
432 GURL
script_url2("http://www.example.com/service_worker2.js");
433 bool registration2_called
= false;
434 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
435 job_coordinator()->Register(
440 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
442 ASSERT_FALSE(registration1_called
);
443 ASSERT_FALSE(registration2_called
);
444 base::RunLoop().RunUntilIdle();
445 ASSERT_TRUE(registration1_called
);
446 ASSERT_TRUE(registration2_called
);
448 scoped_refptr
<ServiceWorkerRegistration
> registration
=
449 FindRegistrationForPattern(pattern
);
451 ASSERT_EQ(registration2
, registration
);
454 // Register the exact same pattern + script. Requests should be
455 // coalesced such that both callers get the exact same registration
457 TEST_F(ServiceWorkerJobTest
, ParallelRegSameScript
) {
458 GURL
pattern("http://www.example.com/");
460 GURL
script_url("http://www.example.com/service_worker1.js");
461 bool registration1_called
= false;
462 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
463 job_coordinator()->Register(
468 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
470 bool registration2_called
= false;
471 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
472 job_coordinator()->Register(
477 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
479 ASSERT_FALSE(registration1_called
);
480 ASSERT_FALSE(registration2_called
);
481 base::RunLoop().RunUntilIdle();
482 ASSERT_TRUE(registration1_called
);
483 ASSERT_TRUE(registration2_called
);
485 ASSERT_EQ(registration1
, registration2
);
487 scoped_refptr
<ServiceWorkerRegistration
> registration
=
488 FindRegistrationForPattern(pattern
);
490 ASSERT_EQ(registration
, registration1
);
493 // Call simulataneous unregister calls.
494 TEST_F(ServiceWorkerJobTest
, ParallelUnreg
) {
495 GURL
pattern("http://www.example.com/");
497 GURL
script_url("http://www.example.com/service_worker.js");
498 bool unregistration1_called
= false;
499 job_coordinator()->Unregister(
501 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
502 &unregistration1_called
));
504 bool unregistration2_called
= false;
505 job_coordinator()->Unregister(
507 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
508 &unregistration2_called
));
510 ASSERT_FALSE(unregistration1_called
);
511 ASSERT_FALSE(unregistration2_called
);
512 base::RunLoop().RunUntilIdle();
513 ASSERT_TRUE(unregistration1_called
);
514 ASSERT_TRUE(unregistration2_called
);
516 // There isn't really a way to test that they are being coalesced,
517 // but we can make sure they can exist simultaneously without
519 scoped_refptr
<ServiceWorkerRegistration
> registration
=
520 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
522 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
525 TEST_F(ServiceWorkerJobTest
, AbortAll_Register
) {
526 GURL
pattern1("http://www1.example.com/");
527 GURL
pattern2("http://www2.example.com/");
528 GURL
script_url1("http://www1.example.com/service_worker.js");
529 GURL
script_url2("http://www2.example.com/service_worker.js");
531 bool registration_called1
= false;
532 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
533 job_coordinator()->Register(
537 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
538 ®istration_called1
, ®istration1
));
540 bool registration_called2
= false;
541 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
542 job_coordinator()->Register(
546 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
547 ®istration_called2
, ®istration2
));
549 ASSERT_FALSE(registration_called1
);
550 ASSERT_FALSE(registration_called2
);
551 job_coordinator()->AbortAll();
553 base::RunLoop().RunUntilIdle();
554 ASSERT_TRUE(registration_called1
);
555 ASSERT_TRUE(registration_called2
);
557 bool find_called1
= false;
558 storage()->FindRegistrationForPattern(
560 SaveFoundRegistration(
561 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called1
, ®istration1
));
563 bool find_called2
= false;
564 storage()->FindRegistrationForPattern(
566 SaveFoundRegistration(
567 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called2
, ®istration2
));
569 base::RunLoop().RunUntilIdle();
570 ASSERT_TRUE(find_called1
);
571 ASSERT_TRUE(find_called2
);
572 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration1
);
573 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration2
);
576 TEST_F(ServiceWorkerJobTest
, AbortAll_Unregister
) {
577 GURL
pattern1("http://www1.example.com/");
578 GURL
pattern2("http://www2.example.com/");
580 bool unregistration_called1
= false;
581 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
582 job_coordinator()->Unregister(
584 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
585 &unregistration_called1
));
587 bool unregistration_called2
= false;
588 job_coordinator()->Unregister(
590 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
591 &unregistration_called2
));
593 ASSERT_FALSE(unregistration_called1
);
594 ASSERT_FALSE(unregistration_called2
);
595 job_coordinator()->AbortAll();
597 base::RunLoop().RunUntilIdle();
598 ASSERT_TRUE(unregistration_called1
);
599 ASSERT_TRUE(unregistration_called2
);
602 TEST_F(ServiceWorkerJobTest
, AbortAll_RegUnreg
) {
603 GURL
pattern("http://www.example.com/");
604 GURL
script_url("http://www.example.com/service_worker.js");
606 bool registration_called
= false;
607 scoped_refptr
<ServiceWorkerRegistration
> registration
;
608 job_coordinator()->Register(
612 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
613 ®istration_called
, ®istration
));
615 bool unregistration_called
= false;
616 job_coordinator()->Unregister(
618 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
619 &unregistration_called
));
621 ASSERT_FALSE(registration_called
);
622 ASSERT_FALSE(unregistration_called
);
623 job_coordinator()->AbortAll();
625 base::RunLoop().RunUntilIdle();
626 ASSERT_TRUE(registration_called
);
627 ASSERT_TRUE(unregistration_called
);
629 registration
= FindRegistrationForPattern(pattern
,
630 SERVICE_WORKER_ERROR_NOT_FOUND
);
632 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
635 // Tests that the waiting worker enters the 'redundant' state upon
637 TEST_F(ServiceWorkerJobTest
, UnregisterWaitingSetsRedundant
) {
638 GURL
script_url("http://www.example.com/service_worker.js");
639 scoped_refptr
<ServiceWorkerRegistration
> registration
=
640 RunRegisterJob(GURL("http://www.example.com/"), script_url
);
641 ASSERT_TRUE(registration
.get());
643 // Manually create the waiting worker since there is no way to become a
644 // waiting worker until Update is implemented.
645 scoped_refptr
<ServiceWorkerVersion
> version
= new ServiceWorkerVersion(
646 registration
.get(), script_url
, 1L, helper_
->context()->AsWeakPtr());
647 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
648 version
->StartWorker(CreateReceiverOnCurrentThread(&status
));
649 base::RunLoop().RunUntilIdle();
650 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
652 version
->SetStatus(ServiceWorkerVersion::INSTALLED
);
653 registration
->SetWaitingVersion(version
.get());
654 EXPECT_EQ(ServiceWorkerVersion::RUNNING
,
655 version
->running_status());
656 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, version
->status());
658 RunUnregisterJob(GURL("http://www.example.com/"));
660 // The version should be stopped since there is no controllee after
662 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
663 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
666 // Tests that the active worker enters the 'redundant' state upon
668 TEST_F(ServiceWorkerJobTest
, UnregisterActiveSetsRedundant
) {
669 scoped_refptr
<ServiceWorkerRegistration
> registration
=
670 RunRegisterJob(GURL("http://www.example.com/"),
671 GURL("http://www.example.com/service_worker.js"));
672 ASSERT_TRUE(registration
.get());
674 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
675 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
676 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
678 RunUnregisterJob(GURL("http://www.example.com/"));
680 // The version should be stopped since there is no controllee after
682 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
683 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
686 // Tests that the active worker enters the 'redundant' state upon
688 TEST_F(ServiceWorkerJobTest
,
689 UnregisterActiveSetsRedundant_WaitForNoControllee
) {
690 scoped_refptr
<ServiceWorkerRegistration
> registration
=
691 RunRegisterJob(GURL("http://www.example.com/"),
692 GURL("http://www.example.com/service_worker.js"));
693 ASSERT_TRUE(registration
.get());
695 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
696 registration
->active_version()->AddControllee(host
.get());
698 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
699 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
700 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
702 RunUnregisterJob(GURL("http://www.example.com/"));
704 // The version should be running since there is still a controllee.
705 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
706 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
708 registration
->active_version()->RemoveControllee(host
.get());
709 base::RunLoop().RunUntilIdle();
711 // The version should be stopped since there is no controllee.
712 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
713 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
716 namespace { // Helpers for the update job tests.
718 const GURL
kNoChangeOrigin("http://nochange/");
719 const GURL
kNewVersionOrigin("http://newversion/");
720 const std::string
kScope("scope/");
721 const std::string
kScript("script.js");
723 void RunNestedUntilIdle() {
724 base::MessageLoop::ScopedNestableTaskAllower
allow(
725 base::MessageLoop::current());
726 base::MessageLoop::current()->RunUntilIdle();
729 void OnIOComplete(int* rv_out
, int rv
) {
734 ServiceWorkerStorage
* storage
, int64 id
,
735 const std::string
& headers
,
736 IOBuffer
* body
, int length
) {
737 scoped_ptr
<ServiceWorkerResponseWriter
> writer
=
738 storage
->CreateResponseWriter(id
);
740 scoped_ptr
<net::HttpResponseInfo
> info(new net::HttpResponseInfo
);
741 info
->request_time
= base::Time::Now();
742 info
->response_time
= base::Time::Now();
743 info
->was_cached
= false;
744 info
->headers
= new net::HttpResponseHeaders(headers
);
745 scoped_refptr
<HttpResponseInfoIOBuffer
> info_buffer
=
746 new HttpResponseInfoIOBuffer(info
.release());
749 writer
->WriteInfo(info_buffer
.get(), base::Bind(&OnIOComplete
, &rv
));
750 RunNestedUntilIdle();
754 writer
->WriteData(body
, length
,
755 base::Bind(&OnIOComplete
, &rv
));
756 RunNestedUntilIdle();
757 EXPECT_EQ(length
, rv
);
760 void WriteStringResponse(
761 ServiceWorkerStorage
* storage
, int64 id
,
762 const std::string
& body
) {
763 scoped_refptr
<IOBuffer
> body_buffer(new WrappedIOBuffer(body
.data()));
764 const char kHttpHeaders
[] = "HTTP/1.0 200 HONKYDORY\0\0";
765 std::string
headers(kHttpHeaders
, arraysize(kHttpHeaders
));
766 WriteResponse(storage
, id
, headers
, body_buffer
.get(), body
.length());
769 class UpdateJobTestHelper
770 : public EmbeddedWorkerTestHelper
,
771 public ServiceWorkerRegistration::Listener
,
772 public ServiceWorkerVersion::Listener
{
774 struct AttributeChangeLogEntry
{
775 int64 registration_id
;
776 ChangedVersionAttributesMask mask
;
777 ServiceWorkerRegistrationInfo info
;
780 struct StateChangeLogEntry
{
782 ServiceWorkerVersion::Status status
;
785 UpdateJobTestHelper(int mock_render_process_id
)
786 : EmbeddedWorkerTestHelper(mock_render_process_id
),
787 update_found_(false) {}
788 ~UpdateJobTestHelper() override
{
789 if (registration_
.get())
790 registration_
->RemoveListener(this);
793 ServiceWorkerStorage
* storage() { return context()->storage(); }
794 ServiceWorkerJobCoordinator
* job_coordinator() {
795 return context()->job_coordinator();
798 scoped_refptr
<ServiceWorkerRegistration
> SetupInitialRegistration(
799 const GURL
& test_origin
) {
800 scoped_refptr
<ServiceWorkerRegistration
> registration
;
802 job_coordinator()->Register(
803 test_origin
.Resolve(kScope
),
804 test_origin
.Resolve(kScript
),
806 SaveRegistration(SERVICE_WORKER_OK
, &called
, ®istration
));
807 base::RunLoop().RunUntilIdle();
809 EXPECT_TRUE(registration
.get());
810 EXPECT_TRUE(registration
->active_version());
811 EXPECT_FALSE(registration
->installing_version());
812 EXPECT_FALSE(registration
->waiting_version());
813 registration_
= registration
;
817 // EmbeddedWorkerTestHelper overrides
818 void OnStartWorker(int embedded_worker_id
,
822 bool pause_after_download
) override
{
823 const std::string kMockScriptBody
= "mock_script";
824 const uint64 kMockScriptSize
= 19284;
825 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
826 ASSERT_TRUE(version
);
827 version
->AddListener(this);
829 if (!pause_after_download
) {
830 // Spoof caching the script for the initial version.
831 int64 resource_id
= storage()->NewResourceId();
832 version
->script_cache_map()->NotifyStartedCaching(script
, resource_id
);
833 WriteStringResponse(storage(), resource_id
, kMockScriptBody
);
834 version
->script_cache_map()->NotifyFinishedCaching(
835 script
, kMockScriptSize
, net::URLRequestStatus(), std::string());
837 // Spoof caching the script for the new version.
838 int64 resource_id
= storage()->NewResourceId();
839 version
->script_cache_map()->NotifyStartedCaching(script
, resource_id
);
840 if (script
.GetOrigin() == kNoChangeOrigin
)
841 WriteStringResponse(storage(), resource_id
, kMockScriptBody
);
843 WriteStringResponse(storage(), resource_id
, "mock_different_script");
844 version
->script_cache_map()->NotifyFinishedCaching(
845 script
, kMockScriptSize
, net::URLRequestStatus(), std::string());
847 EmbeddedWorkerTestHelper::OnStartWorker(
848 embedded_worker_id
, version_id
, scope
, script
, pause_after_download
);
851 // ServiceWorkerRegistration::Listener overrides
852 void OnVersionAttributesChanged(
853 ServiceWorkerRegistration
* registration
,
854 ChangedVersionAttributesMask changed_mask
,
855 const ServiceWorkerRegistrationInfo
& info
) override
{
856 AttributeChangeLogEntry entry
;
857 entry
.registration_id
= registration
->id();
858 entry
.mask
= changed_mask
;
860 attribute_change_log_
.push_back(entry
);
863 void OnRegistrationFailed(ServiceWorkerRegistration
* registration
) override
{
867 void OnUpdateFound(ServiceWorkerRegistration
* registration
) override
{
868 ASSERT_FALSE(update_found_
);
869 update_found_
= true;
872 // ServiceWorkerVersion::Listener overrides
873 void OnVersionStateChanged(ServiceWorkerVersion
* version
) override
{
874 StateChangeLogEntry entry
;
875 entry
.version_id
= version
->version_id();
876 entry
.status
= version
->status();
877 state_change_log_
.push_back(entry
);
880 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
882 std::vector
<AttributeChangeLogEntry
> attribute_change_log_
;
883 std::vector
<StateChangeLogEntry
> state_change_log_
;
889 TEST_F(ServiceWorkerJobTest
, Update_NoChange
) {
890 UpdateJobTestHelper
* update_helper
=
891 new UpdateJobTestHelper(render_process_id_
);
892 helper_
.reset(update_helper
);
893 scoped_refptr
<ServiceWorkerRegistration
> registration
=
894 update_helper
->SetupInitialRegistration(kNoChangeOrigin
);
895 ASSERT_TRUE(registration
.get());
896 ASSERT_EQ(4u, update_helper
->state_change_log_
.size());
897 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
898 update_helper
->state_change_log_
[0].status
);
899 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
900 update_helper
->state_change_log_
[1].status
);
901 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
902 update_helper
->state_change_log_
[2].status
);
903 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
904 update_helper
->state_change_log_
[3].status
);
905 update_helper
->state_change_log_
.clear();
907 // Run the update job.
908 registration
->AddListener(update_helper
);
909 scoped_refptr
<ServiceWorkerVersion
> first_version
=
910 registration
->active_version();
911 first_version
->StartUpdate();
912 base::RunLoop().RunUntilIdle();
915 ASSERT_TRUE(registration
->active_version());
916 EXPECT_EQ(first_version
.get(), registration
->active_version());
917 EXPECT_FALSE(registration
->installing_version());
918 EXPECT_FALSE(registration
->waiting_version());
919 EXPECT_TRUE(update_helper
->attribute_change_log_
.empty());
920 ASSERT_EQ(1u, update_helper
->state_change_log_
.size());
921 EXPECT_NE(registration
->active_version()->version_id(),
922 update_helper
->state_change_log_
[0].version_id
);
923 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
924 update_helper
->state_change_log_
[0].status
);
925 EXPECT_FALSE(update_helper
->update_found_
);
928 TEST_F(ServiceWorkerJobTest
, Update_NewVersion
) {
929 UpdateJobTestHelper
* update_helper
=
930 new UpdateJobTestHelper(render_process_id_
);
931 helper_
.reset(update_helper
);
932 scoped_refptr
<ServiceWorkerRegistration
> registration
=
933 update_helper
->SetupInitialRegistration(kNewVersionOrigin
);
934 ASSERT_TRUE(registration
.get());
935 update_helper
->state_change_log_
.clear();
937 // Run the update job.
938 registration
->AddListener(update_helper
);
939 scoped_refptr
<ServiceWorkerVersion
> first_version
=
940 registration
->active_version();
941 first_version
->StartUpdate();
942 base::RunLoop().RunUntilIdle();
945 ASSERT_TRUE(registration
->active_version());
946 EXPECT_NE(first_version
.get(), registration
->active_version());
947 EXPECT_FALSE(registration
->installing_version());
948 EXPECT_FALSE(registration
->waiting_version());
949 ASSERT_EQ(3u, update_helper
->attribute_change_log_
.size());
951 UpdateJobTestHelper::AttributeChangeLogEntry entry
;
952 entry
= update_helper
->attribute_change_log_
[0];
953 EXPECT_TRUE(entry
.mask
.installing_changed());
954 EXPECT_FALSE(entry
.mask
.waiting_changed());
955 EXPECT_FALSE(entry
.mask
.active_changed());
956 EXPECT_NE(entry
.info
.installing_version
.version_id
,
957 kInvalidServiceWorkerVersionId
);
958 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
959 kInvalidServiceWorkerVersionId
);
960 EXPECT_NE(entry
.info
.active_version
.version_id
,
961 kInvalidServiceWorkerVersionId
);
963 entry
= update_helper
->attribute_change_log_
[1];
964 EXPECT_TRUE(entry
.mask
.installing_changed());
965 EXPECT_TRUE(entry
.mask
.waiting_changed());
966 EXPECT_FALSE(entry
.mask
.active_changed());
967 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
968 kInvalidServiceWorkerVersionId
);
969 EXPECT_NE(entry
.info
.waiting_version
.version_id
,
970 kInvalidServiceWorkerVersionId
);
971 EXPECT_NE(entry
.info
.active_version
.version_id
,
972 kInvalidServiceWorkerVersionId
);
974 entry
= update_helper
->attribute_change_log_
[2];
975 EXPECT_FALSE(entry
.mask
.installing_changed());
976 EXPECT_TRUE(entry
.mask
.waiting_changed());
977 EXPECT_TRUE(entry
.mask
.active_changed());
978 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
979 kInvalidServiceWorkerVersionId
);
980 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
981 kInvalidServiceWorkerVersionId
);
982 EXPECT_NE(entry
.info
.active_version
.version_id
,
983 kInvalidServiceWorkerVersionId
);
985 // expected version state transitions:
986 // new.installing, new.installed,
988 // new.activating, new.activated
989 ASSERT_EQ(5u, update_helper
->state_change_log_
.size());
991 EXPECT_EQ(registration
->active_version()->version_id(),
992 update_helper
->state_change_log_
[0].version_id
);
993 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
994 update_helper
->state_change_log_
[0].status
);
996 EXPECT_EQ(registration
->active_version()->version_id(),
997 update_helper
->state_change_log_
[1].version_id
);
998 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
999 update_helper
->state_change_log_
[1].status
);
1001 EXPECT_EQ(first_version
->version_id(),
1002 update_helper
->state_change_log_
[2].version_id
);
1003 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
1004 update_helper
->state_change_log_
[2].status
);
1006 EXPECT_EQ(registration
->active_version()->version_id(),
1007 update_helper
->state_change_log_
[3].version_id
);
1008 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
1009 update_helper
->state_change_log_
[3].status
);
1011 EXPECT_EQ(registration
->active_version()->version_id(),
1012 update_helper
->state_change_log_
[4].version_id
);
1013 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
1014 update_helper
->state_change_log_
[4].status
);
1016 EXPECT_TRUE(update_helper
->update_found_
);
1019 TEST_F(ServiceWorkerJobTest
, Update_NewestVersionChanged
) {
1020 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1021 RunRegisterJob(GURL("http://www.example.com/one/"),
1022 GURL("http://www.example.com/service_worker.js"));
1024 ServiceWorkerVersion
* active_version
= registration
->active_version();
1026 // Queue an Update, it should abort when it starts and sees the new version.
1027 job_coordinator()->Update(registration
.get());
1029 // Add a waiting version with new script.
1030 scoped_refptr
<ServiceWorkerVersion
> version
=
1031 new ServiceWorkerVersion(registration
.get(),
1032 GURL("http://www.example.com/new_worker.js"),
1033 2L /* dummy version id */,
1034 helper_
->context()->AsWeakPtr());
1035 registration
->SetWaitingVersion(version
.get());
1037 base::RunLoop().RunUntilIdle();
1039 // Verify the registration was not modified by the Update.
1040 EXPECT_EQ(active_version
, registration
->active_version());
1041 EXPECT_EQ(version
.get(), registration
->waiting_version());
1042 EXPECT_EQ(NULL
, registration
->installing_version());
1045 TEST_F(ServiceWorkerJobTest
, Update_UninstallingRegistration
) {
1047 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1048 RunRegisterJob(GURL("http://www.example.com/one/"),
1049 GURL("http://www.example.com/service_worker.js"));
1051 // Add a controllee and queue an unregister to force the uninstalling state.
1052 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1053 ServiceWorkerVersion
* active_version
= registration
->active_version();
1054 active_version
->AddControllee(host
.get());
1055 job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
1056 SaveUnregistration(SERVICE_WORKER_OK
, &called
));
1058 // Update should abort after it starts and sees uninstalling.
1059 job_coordinator()->Update(registration
.get());
1061 EXPECT_FALSE(called
);
1062 base::RunLoop().RunUntilIdle();
1063 EXPECT_TRUE(called
);
1065 // Verify the registration was not modified by the Update.
1066 EXPECT_TRUE(registration
->is_uninstalling());
1067 EXPECT_EQ(active_version
, registration
->active_version());
1068 EXPECT_EQ(NULL
, registration
->waiting_version());
1069 EXPECT_EQ(NULL
, registration
->installing_version());
1072 TEST_F(ServiceWorkerJobTest
, RegisterWhileUninstalling
) {
1073 GURL
pattern("http://www.example.com/one/");
1074 GURL
script1("http://www.example.com/service_worker.js");
1075 GURL
script2("http://www.example.com/service_worker.js?new");
1077 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1078 RunRegisterJob(pattern
, script1
);
1080 // Add a controllee and queue an unregister to force the uninstalling state.
1081 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1082 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1083 registration
->active_version();
1084 old_version
->AddControllee(host
.get());
1085 RunUnregisterJob(pattern
);
1087 // Register another script.
1088 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1090 EXPECT_FALSE(registration
->is_uninstalling());
1091 EXPECT_EQ(old_version
, registration
->active_version());
1093 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1094 registration
->waiting_version();
1096 // Verify the new version is installed but not activated yet.
1097 EXPECT_EQ(NULL
, registration
->installing_version());
1098 EXPECT_TRUE(new_version
);
1099 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1100 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1102 old_version
->RemoveControllee(host
.get());
1103 base::RunLoop().RunUntilIdle();
1105 EXPECT_FALSE(registration
->is_uninstalling());
1106 EXPECT_FALSE(registration
->is_uninstalled());
1108 // Verify the new version is activated.
1109 EXPECT_EQ(NULL
, registration
->installing_version());
1110 EXPECT_EQ(NULL
, registration
->waiting_version());
1111 EXPECT_EQ(new_version
, registration
->active_version());
1112 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1113 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1116 TEST_F(ServiceWorkerJobTest
, RegisterAndUnregisterWhileUninstalling
) {
1117 GURL
pattern("http://www.example.com/one/");
1118 GURL
script1("http://www.example.com/service_worker.js");
1119 GURL
script2("http://www.example.com/service_worker.js?new");
1121 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1122 RunRegisterJob(pattern
, script1
);
1124 // Add a controllee and queue an unregister to force the uninstalling state.
1125 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1126 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1127 registration
->active_version();
1128 old_version
->AddControllee(host
.get());
1129 RunUnregisterJob(pattern
);
1131 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1133 EXPECT_EQ(registration
, FindRegistrationForPattern(pattern
));
1134 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1135 registration
->waiting_version();
1136 ASSERT_TRUE(new_version
);
1138 // Unregister the registration (but it's still live).
1139 RunUnregisterJob(pattern
);
1140 // Now it's not found in the storage.
1141 RunUnregisterJob(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1143 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1144 EXPECT_TRUE(registration
->is_uninstalling());
1145 EXPECT_EQ(old_version
, registration
->active_version());
1147 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, old_version
->running_status());
1148 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, old_version
->status());
1149 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1150 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1152 old_version
->RemoveControllee(host
.get());
1153 base::RunLoop().RunUntilIdle();
1155 EXPECT_FALSE(registration
->is_uninstalling());
1156 EXPECT_TRUE(registration
->is_uninstalled());
1158 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1159 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1160 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, new_version
->running_status());
1161 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, new_version
->status());
1164 TEST_F(ServiceWorkerJobTest
, RegisterSameScriptMultipleTimesWhileUninstalling
) {
1165 GURL
pattern("http://www.example.com/one/");
1166 GURL
script1("http://www.example.com/service_worker.js");
1167 GURL
script2("http://www.example.com/service_worker.js?new");
1169 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1170 RunRegisterJob(pattern
, script1
);
1172 // Add a controllee and queue an unregister to force the uninstalling state.
1173 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1174 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1175 registration
->active_version();
1176 old_version
->AddControllee(host
.get());
1177 RunUnregisterJob(pattern
);
1179 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1181 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1182 registration
->waiting_version();
1183 ASSERT_TRUE(new_version
);
1185 RunUnregisterJob(pattern
);
1187 EXPECT_TRUE(registration
->is_uninstalling());
1189 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1191 EXPECT_FALSE(registration
->is_uninstalling());
1192 EXPECT_EQ(new_version
, registration
->waiting_version());
1194 old_version
->RemoveControllee(host
.get());
1195 base::RunLoop().RunUntilIdle();
1197 EXPECT_FALSE(registration
->is_uninstalling());
1198 EXPECT_FALSE(registration
->is_uninstalled());
1200 // Verify the new version is activated.
1201 EXPECT_EQ(NULL
, registration
->installing_version());
1202 EXPECT_EQ(NULL
, registration
->waiting_version());
1203 EXPECT_EQ(new_version
, registration
->active_version());
1204 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1205 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1208 TEST_F(ServiceWorkerJobTest
, RegisterMultipleTimesWhileUninstalling
) {
1209 GURL
pattern("http://www.example.com/one/");
1210 GURL
script1("http://www.example.com/service_worker.js?first");
1211 GURL
script2("http://www.example.com/service_worker.js?second");
1212 GURL
script3("http://www.example.com/service_worker.js?third");
1214 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1215 RunRegisterJob(pattern
, script1
);
1217 // Add a controllee and queue an unregister to force the uninstalling state.
1218 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1219 scoped_refptr
<ServiceWorkerVersion
> first_version
=
1220 registration
->active_version();
1221 first_version
->AddControllee(host
.get());
1222 RunUnregisterJob(pattern
);
1224 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1226 scoped_refptr
<ServiceWorkerVersion
> second_version
=
1227 registration
->waiting_version();
1228 ASSERT_TRUE(second_version
);
1230 RunUnregisterJob(pattern
);
1232 EXPECT_TRUE(registration
->is_uninstalling());
1234 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script3
));
1236 scoped_refptr
<ServiceWorkerVersion
> third_version
=
1237 registration
->waiting_version();
1238 ASSERT_TRUE(third_version
);
1240 EXPECT_FALSE(registration
->is_uninstalling());
1241 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, second_version
->status());
1243 first_version
->RemoveControllee(host
.get());
1244 base::RunLoop().RunUntilIdle();
1246 EXPECT_FALSE(registration
->is_uninstalling());
1247 EXPECT_FALSE(registration
->is_uninstalled());
1249 // Verify the new version is activated.
1250 EXPECT_EQ(NULL
, registration
->installing_version());
1251 EXPECT_EQ(NULL
, registration
->waiting_version());
1252 EXPECT_EQ(third_version
, registration
->active_version());
1253 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, third_version
->running_status());
1254 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, third_version
->status());
1257 class EventCallbackHelper
: public EmbeddedWorkerTestHelper
{
1259 explicit EventCallbackHelper(int mock_render_process_id
)
1260 : EmbeddedWorkerTestHelper(mock_render_process_id
),
1261 install_event_result_(blink::WebServiceWorkerEventResultCompleted
),
1262 activate_event_result_(blink::WebServiceWorkerEventResultCompleted
) {}
1264 void OnInstallEvent(int embedded_worker_id
,
1266 int active_version_id
) override
{
1267 if (!install_callback_
.is_null())
1268 install_callback_
.Run();
1270 new ServiceWorkerHostMsg_InstallEventFinished(
1271 embedded_worker_id
, request_id
, install_event_result_
));
1273 void OnActivateEvent(int embedded_worker_id
, int request_id
) override
{
1275 new ServiceWorkerHostMsg_ActivateEventFinished(
1276 embedded_worker_id
, request_id
, activate_event_result_
));
1279 void set_install_callback(const base::Closure
& callback
) {
1280 install_callback_
= callback
;
1282 void set_install_event_result(blink::WebServiceWorkerEventResult result
) {
1283 install_event_result_
= result
;
1285 void set_activate_event_result(blink::WebServiceWorkerEventResult result
) {
1286 activate_event_result_
= result
;
1289 base::Closure install_callback_
;
1290 blink::WebServiceWorkerEventResult install_event_result_
;
1291 blink::WebServiceWorkerEventResult activate_event_result_
;
1294 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringInstall
) {
1295 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1296 helper_
.reset(helper
);
1298 GURL
pattern("http://www.example.com/one/");
1299 GURL
script1("http://www.example.com/service_worker.js");
1300 GURL
script2("http://www.example.com/service_worker.js?new");
1302 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1303 RunRegisterJob(pattern
, script1
);
1305 // Add a controllee and queue an unregister to force the uninstalling state.
1306 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1307 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1308 registration
->active_version();
1309 old_version
->AddControllee(host
.get());
1310 RunUnregisterJob(pattern
);
1312 // Register another script. While installing, old_version loses controllee.
1313 helper
->set_install_callback(
1314 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1315 old_version
, host
.get()));
1316 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1318 EXPECT_FALSE(registration
->is_uninstalling());
1319 EXPECT_FALSE(registration
->is_uninstalled());
1321 // Verify the new version is activated.
1322 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1323 registration
->active_version();
1324 EXPECT_NE(old_version
, new_version
);
1325 EXPECT_EQ(NULL
, registration
->installing_version());
1326 EXPECT_EQ(NULL
, registration
->waiting_version());
1327 EXPECT_EQ(new_version
, registration
->active_version());
1328 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1329 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1331 EXPECT_EQ(registration
, FindRegistrationForPattern(pattern
));
1334 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringRejectedInstall
) {
1335 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1336 helper_
.reset(helper
);
1338 GURL
pattern("http://www.example.com/one/");
1339 GURL
script1("http://www.example.com/service_worker.js");
1340 GURL
script2("http://www.example.com/service_worker.js?new");
1342 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1343 RunRegisterJob(pattern
, script1
);
1345 // Add a controllee and queue an unregister to force the uninstalling state.
1346 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1347 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1348 registration
->active_version();
1349 old_version
->AddControllee(host
.get());
1350 RunUnregisterJob(pattern
);
1352 // Register another script that fails to install. While installing,
1353 // old_version loses controllee.
1354 helper
->set_install_callback(
1355 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1356 old_version
, host
.get()));
1357 helper
->set_install_event_result(blink::WebServiceWorkerEventResultRejected
);
1358 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1360 // Verify the registration was uninstalled.
1361 EXPECT_FALSE(registration
->is_uninstalling());
1362 EXPECT_TRUE(registration
->is_uninstalled());
1364 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1365 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1367 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1370 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringInstall_RejectActivate
) {
1371 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1372 helper_
.reset(helper
);
1374 GURL
pattern("http://www.example.com/one/");
1375 GURL
script1("http://www.example.com/service_worker.js");
1376 GURL
script2("http://www.example.com/service_worker.js?new");
1378 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1379 RunRegisterJob(pattern
, script1
);
1381 // Add a controllee and queue an unregister to force the uninstalling state.
1382 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1383 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1384 registration
->active_version();
1385 old_version
->AddControllee(host
.get());
1386 RunUnregisterJob(pattern
);
1388 // Register another script that fails to activate. While installing,
1389 // old_version loses controllee.
1390 helper
->set_install_callback(
1391 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1392 old_version
, host
.get()));
1393 helper
->set_activate_event_result(blink::WebServiceWorkerEventResultRejected
);
1394 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1396 // Verify the registration was uninstalled.
1397 EXPECT_FALSE(registration
->is_uninstalling());
1398 EXPECT_TRUE(registration
->is_uninstalled());
1400 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1401 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1403 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1406 } // namespace content