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
{
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(); }
123 scoped_refptr
<ServiceWorkerRegistration
> RunRegisterJob(
125 const GURL
& script_url
,
126 ServiceWorkerStatusCode expected_status
= SERVICE_WORKER_OK
);
127 void RunUnregisterJob(
129 ServiceWorkerStatusCode expected_status
= SERVICE_WORKER_OK
);
130 scoped_refptr
<ServiceWorkerRegistration
> FindRegistrationForPattern(
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(
142 const GURL
& script_url
,
143 ServiceWorkerStatusCode expected_status
) {
144 scoped_refptr
<ServiceWorkerRegistration
> registration
;
146 job_coordinator()->Register(
147 pattern
, script_url
, NULL
,
148 SaveRegistration(expected_status
, &called
, ®istration
));
149 EXPECT_FALSE(called
);
150 base::RunLoop().RunUntilIdle();
155 void ServiceWorkerJobTest::RunUnregisterJob(
157 ServiceWorkerStatusCode expected_status
) {
159 job_coordinator()->Unregister(pattern
,
160 SaveUnregistration(expected_status
, &called
));
161 EXPECT_FALSE(called
);
162 base::RunLoop().RunUntilIdle();
166 scoped_refptr
<ServiceWorkerRegistration
>
167 ServiceWorkerJobTest::FindRegistrationForPattern(
169 ServiceWorkerStatusCode expected_status
) {
171 scoped_refptr
<ServiceWorkerRegistration
> registration
;
172 storage()->FindRegistrationForPattern(
174 SaveFoundRegistration(expected_status
, &called
, ®istration
));
176 EXPECT_FALSE(called
);
177 base::RunLoop().RunUntilIdle();
182 scoped_ptr
<ServiceWorkerProviderHost
> ServiceWorkerJobTest::CreateControllee() {
183 return scoped_ptr
<ServiceWorkerProviderHost
>(
184 new ServiceWorkerProviderHost(33 /* dummy render_process id */,
185 MSG_ROUTING_NONE
/* render_frame_id */,
186 1 /* dummy provider_id */,
187 SERVICE_WORKER_PROVIDER_FOR_CONTROLLEE
,
188 helper_
->context()->AsWeakPtr(),
192 TEST_F(ServiceWorkerJobTest
, SameDocumentSameRegistration
) {
193 scoped_refptr
<ServiceWorkerRegistration
> original_registration
=
194 RunRegisterJob(GURL("http://www.example.com/"),
195 GURL("http://www.example.com/service_worker.js"));
197 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
198 storage()->FindRegistrationForDocument(
199 GURL("http://www.example.com/"),
200 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration1
));
201 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
202 storage()->FindRegistrationForDocument(
203 GURL("http://www.example.com/"),
204 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration2
));
205 base::RunLoop().RunUntilIdle();
207 ASSERT_TRUE(registration1
.get());
208 ASSERT_EQ(registration1
, original_registration
);
209 ASSERT_EQ(registration1
, registration2
);
212 TEST_F(ServiceWorkerJobTest
, SameMatchSameRegistration
) {
214 scoped_refptr
<ServiceWorkerRegistration
> original_registration
=
215 RunRegisterJob(GURL("http://www.example.com/"),
216 GURL("http://www.example.com/service_worker.js"));
217 ASSERT_NE(static_cast<ServiceWorkerRegistration
*>(NULL
),
218 original_registration
.get());
220 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
221 storage()->FindRegistrationForDocument(
222 GURL("http://www.example.com/one"),
223 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration1
));
224 base::RunLoop().RunUntilIdle();
227 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
228 storage()->FindRegistrationForDocument(
229 GURL("http://www.example.com/two"),
230 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration2
));
231 base::RunLoop().RunUntilIdle();
233 ASSERT_EQ(registration1
, original_registration
);
234 ASSERT_EQ(registration1
, registration2
);
237 TEST_F(ServiceWorkerJobTest
, DifferentMatchDifferentRegistration
) {
239 scoped_refptr
<ServiceWorkerRegistration
> original_registration1
;
240 job_coordinator()->Register(
241 GURL("http://www.example.com/one/"),
242 GURL("http://www.example.com/service_worker.js"),
244 SaveRegistration(SERVICE_WORKER_OK
, &called1
, &original_registration1
));
247 scoped_refptr
<ServiceWorkerRegistration
> original_registration2
;
248 job_coordinator()->Register(
249 GURL("http://www.example.com/two/"),
250 GURL("http://www.example.com/service_worker.js"),
252 SaveRegistration(SERVICE_WORKER_OK
, &called2
, &original_registration2
));
254 EXPECT_FALSE(called1
);
255 EXPECT_FALSE(called2
);
256 base::RunLoop().RunUntilIdle();
257 EXPECT_TRUE(called2
);
258 EXPECT_TRUE(called1
);
260 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
261 storage()->FindRegistrationForDocument(
262 GURL("http://www.example.com/one/"),
263 SaveFoundRegistration(SERVICE_WORKER_OK
, &called1
, ®istration1
));
264 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
265 storage()->FindRegistrationForDocument(
266 GURL("http://www.example.com/two/"),
267 SaveFoundRegistration(SERVICE_WORKER_OK
, &called2
, ®istration2
));
269 base::RunLoop().RunUntilIdle();
270 EXPECT_TRUE(called2
);
271 EXPECT_TRUE(called1
);
272 ASSERT_NE(registration1
, registration2
);
275 // Make sure basic registration is working.
276 TEST_F(ServiceWorkerJobTest
, Register
) {
277 scoped_refptr
<ServiceWorkerRegistration
> registration
=
278 RunRegisterJob(GURL("http://www.example.com/"),
279 GURL("http://www.example.com/service_worker.js"));
281 ASSERT_NE(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
284 // Make sure registrations are cleaned up when they are unregistered.
285 TEST_F(ServiceWorkerJobTest
, Unregister
) {
286 GURL
pattern("http://www.example.com/");
288 scoped_refptr
<ServiceWorkerRegistration
> registration
=
289 RunRegisterJob(pattern
, GURL("http://www.example.com/service_worker.js"));
291 RunUnregisterJob(pattern
);
293 ASSERT_TRUE(registration
->HasOneRef());
295 registration
= FindRegistrationForPattern(pattern
,
296 SERVICE_WORKER_ERROR_NOT_FOUND
);
298 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
301 TEST_F(ServiceWorkerJobTest
, Unregister_NothingRegistered
) {
302 GURL
pattern("http://www.example.com/");
304 RunUnregisterJob(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
307 // Make sure registering a new script creates a new version and shares an
308 // existing registration.
309 TEST_F(ServiceWorkerJobTest
, RegisterNewScript
) {
310 GURL
pattern("http://www.example.com/");
312 scoped_refptr
<ServiceWorkerRegistration
> old_registration
=
313 RunRegisterJob(pattern
, GURL("http://www.example.com/service_worker.js"));
315 scoped_refptr
<ServiceWorkerRegistration
> old_registration_by_pattern
=
316 FindRegistrationForPattern(pattern
);
318 ASSERT_EQ(old_registration
, old_registration_by_pattern
);
319 old_registration_by_pattern
= NULL
;
321 scoped_refptr
<ServiceWorkerRegistration
> new_registration
=
322 RunRegisterJob(pattern
,
323 GURL("http://www.example.com/service_worker_new.js"));
325 ASSERT_EQ(old_registration
, new_registration
);
327 scoped_refptr
<ServiceWorkerRegistration
> new_registration_by_pattern
=
328 FindRegistrationForPattern(pattern
);
330 ASSERT_EQ(new_registration
, new_registration_by_pattern
);
333 // Make sure that when registering a duplicate pattern+script_url
334 // combination, that the same registration is used.
335 TEST_F(ServiceWorkerJobTest
, RegisterDuplicateScript
) {
336 GURL
pattern("http://www.example.com/");
337 GURL
script_url("http://www.example.com/service_worker.js");
339 scoped_refptr
<ServiceWorkerRegistration
> old_registration
=
340 RunRegisterJob(pattern
, script_url
);
342 scoped_refptr
<ServiceWorkerRegistration
> old_registration_by_pattern
=
343 FindRegistrationForPattern(pattern
);
345 ASSERT_TRUE(old_registration_by_pattern
.get());
347 scoped_refptr
<ServiceWorkerRegistration
> new_registration
=
348 RunRegisterJob(pattern
, script_url
);
350 ASSERT_EQ(old_registration
, new_registration
);
352 ASSERT_FALSE(old_registration
->HasOneRef());
354 scoped_refptr
<ServiceWorkerRegistration
> new_registration_by_pattern
=
355 FindRegistrationForPattern(pattern
);
357 ASSERT_EQ(new_registration
, old_registration
);
360 class FailToStartWorkerTestHelper
: public EmbeddedWorkerTestHelper
{
362 explicit FailToStartWorkerTestHelper(int mock_render_process_id
)
363 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
) {}
365 void OnStartWorker(int embedded_worker_id
,
366 int64 service_worker_version_id
,
368 const GURL
& script_url
,
369 bool pause_after_download
) override
{
370 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
371 registry()->OnWorkerStopped(worker
->process_id(), embedded_worker_id
);
375 TEST_F(ServiceWorkerJobTest
, Register_FailToStartWorker
) {
376 helper_
.reset(new FailToStartWorkerTestHelper(render_process_id_
));
378 scoped_refptr
<ServiceWorkerRegistration
> registration
=
379 RunRegisterJob(GURL("http://www.example.com/"),
380 GURL("http://www.example.com/service_worker.js"),
381 SERVICE_WORKER_ERROR_START_WORKER_FAILED
);
383 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
386 // Register and then unregister the pattern, in parallel. Job coordinator should
387 // process jobs until the last job.
388 TEST_F(ServiceWorkerJobTest
, ParallelRegUnreg
) {
389 GURL
pattern("http://www.example.com/");
390 GURL
script_url("http://www.example.com/service_worker.js");
392 bool registration_called
= false;
393 scoped_refptr
<ServiceWorkerRegistration
> registration
;
394 job_coordinator()->Register(
398 SaveRegistration(SERVICE_WORKER_OK
, ®istration_called
, ®istration
));
400 bool unregistration_called
= false;
401 job_coordinator()->Unregister(
403 SaveUnregistration(SERVICE_WORKER_OK
, &unregistration_called
));
405 ASSERT_FALSE(registration_called
);
406 ASSERT_FALSE(unregistration_called
);
407 base::RunLoop().RunUntilIdle();
408 ASSERT_TRUE(registration_called
);
409 ASSERT_TRUE(unregistration_called
);
411 registration
= FindRegistrationForPattern(pattern
,
412 SERVICE_WORKER_ERROR_NOT_FOUND
);
414 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
417 // Register conflicting scripts for the same pattern. The most recent
418 // registration should win, and the old registration should have been
420 TEST_F(ServiceWorkerJobTest
, ParallelRegNewScript
) {
421 GURL
pattern("http://www.example.com/");
423 GURL
script_url1("http://www.example.com/service_worker1.js");
424 bool registration1_called
= false;
425 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
426 job_coordinator()->Register(
431 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
433 GURL
script_url2("http://www.example.com/service_worker2.js");
434 bool registration2_called
= false;
435 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
436 job_coordinator()->Register(
441 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
443 ASSERT_FALSE(registration1_called
);
444 ASSERT_FALSE(registration2_called
);
445 base::RunLoop().RunUntilIdle();
446 ASSERT_TRUE(registration1_called
);
447 ASSERT_TRUE(registration2_called
);
449 scoped_refptr
<ServiceWorkerRegistration
> registration
=
450 FindRegistrationForPattern(pattern
);
452 ASSERT_EQ(registration2
, registration
);
455 // Register the exact same pattern + script. Requests should be
456 // coalesced such that both callers get the exact same registration
458 TEST_F(ServiceWorkerJobTest
, ParallelRegSameScript
) {
459 GURL
pattern("http://www.example.com/");
461 GURL
script_url("http://www.example.com/service_worker1.js");
462 bool registration1_called
= false;
463 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
464 job_coordinator()->Register(
469 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
471 bool registration2_called
= false;
472 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
473 job_coordinator()->Register(
478 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
480 ASSERT_FALSE(registration1_called
);
481 ASSERT_FALSE(registration2_called
);
482 base::RunLoop().RunUntilIdle();
483 ASSERT_TRUE(registration1_called
);
484 ASSERT_TRUE(registration2_called
);
486 ASSERT_EQ(registration1
, registration2
);
488 scoped_refptr
<ServiceWorkerRegistration
> registration
=
489 FindRegistrationForPattern(pattern
);
491 ASSERT_EQ(registration
, registration1
);
494 // Call simulataneous unregister calls.
495 TEST_F(ServiceWorkerJobTest
, ParallelUnreg
) {
496 GURL
pattern("http://www.example.com/");
498 GURL
script_url("http://www.example.com/service_worker.js");
499 bool unregistration1_called
= false;
500 job_coordinator()->Unregister(
502 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
503 &unregistration1_called
));
505 bool unregistration2_called
= false;
506 job_coordinator()->Unregister(
508 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
509 &unregistration2_called
));
511 ASSERT_FALSE(unregistration1_called
);
512 ASSERT_FALSE(unregistration2_called
);
513 base::RunLoop().RunUntilIdle();
514 ASSERT_TRUE(unregistration1_called
);
515 ASSERT_TRUE(unregistration2_called
);
517 // There isn't really a way to test that they are being coalesced,
518 // but we can make sure they can exist simultaneously without
520 scoped_refptr
<ServiceWorkerRegistration
> registration
=
521 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
523 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
526 TEST_F(ServiceWorkerJobTest
, AbortAll_Register
) {
527 GURL
pattern1("http://www1.example.com/");
528 GURL
pattern2("http://www2.example.com/");
529 GURL
script_url1("http://www1.example.com/service_worker.js");
530 GURL
script_url2("http://www2.example.com/service_worker.js");
532 bool registration_called1
= false;
533 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
534 job_coordinator()->Register(
538 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
539 ®istration_called1
, ®istration1
));
541 bool registration_called2
= false;
542 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
543 job_coordinator()->Register(
547 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
548 ®istration_called2
, ®istration2
));
550 ASSERT_FALSE(registration_called1
);
551 ASSERT_FALSE(registration_called2
);
552 job_coordinator()->AbortAll();
554 base::RunLoop().RunUntilIdle();
555 ASSERT_TRUE(registration_called1
);
556 ASSERT_TRUE(registration_called2
);
558 bool find_called1
= false;
559 storage()->FindRegistrationForPattern(
561 SaveFoundRegistration(
562 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called1
, ®istration1
));
564 bool find_called2
= false;
565 storage()->FindRegistrationForPattern(
567 SaveFoundRegistration(
568 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called2
, ®istration2
));
570 base::RunLoop().RunUntilIdle();
571 ASSERT_TRUE(find_called1
);
572 ASSERT_TRUE(find_called2
);
573 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration1
);
574 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration2
);
577 TEST_F(ServiceWorkerJobTest
, AbortAll_Unregister
) {
578 GURL
pattern1("http://www1.example.com/");
579 GURL
pattern2("http://www2.example.com/");
581 bool unregistration_called1
= false;
582 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
583 job_coordinator()->Unregister(
585 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
586 &unregistration_called1
));
588 bool unregistration_called2
= false;
589 job_coordinator()->Unregister(
591 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
592 &unregistration_called2
));
594 ASSERT_FALSE(unregistration_called1
);
595 ASSERT_FALSE(unregistration_called2
);
596 job_coordinator()->AbortAll();
598 base::RunLoop().RunUntilIdle();
599 ASSERT_TRUE(unregistration_called1
);
600 ASSERT_TRUE(unregistration_called2
);
603 TEST_F(ServiceWorkerJobTest
, AbortAll_RegUnreg
) {
604 GURL
pattern("http://www.example.com/");
605 GURL
script_url("http://www.example.com/service_worker.js");
607 bool registration_called
= false;
608 scoped_refptr
<ServiceWorkerRegistration
> registration
;
609 job_coordinator()->Register(
613 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
614 ®istration_called
, ®istration
));
616 bool unregistration_called
= false;
617 job_coordinator()->Unregister(
619 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
620 &unregistration_called
));
622 ASSERT_FALSE(registration_called
);
623 ASSERT_FALSE(unregistration_called
);
624 job_coordinator()->AbortAll();
626 base::RunLoop().RunUntilIdle();
627 ASSERT_TRUE(registration_called
);
628 ASSERT_TRUE(unregistration_called
);
630 registration
= FindRegistrationForPattern(pattern
,
631 SERVICE_WORKER_ERROR_NOT_FOUND
);
633 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
636 // Tests that the waiting worker enters the 'redundant' state upon
638 TEST_F(ServiceWorkerJobTest
, UnregisterWaitingSetsRedundant
) {
639 GURL
script_url("http://www.example.com/service_worker.js");
640 scoped_refptr
<ServiceWorkerRegistration
> registration
=
641 RunRegisterJob(GURL("http://www.example.com/"), script_url
);
642 ASSERT_TRUE(registration
.get());
644 // Manually create the waiting worker since there is no way to become a
645 // waiting worker until Update is implemented.
646 scoped_refptr
<ServiceWorkerVersion
> version
= new ServiceWorkerVersion(
647 registration
.get(), script_url
, 1L, helper_
->context()->AsWeakPtr());
648 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
649 version
->StartWorker(CreateReceiverOnCurrentThread(&status
));
650 base::RunLoop().RunUntilIdle();
651 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
653 version
->SetStatus(ServiceWorkerVersion::INSTALLED
);
654 registration
->SetWaitingVersion(version
.get());
655 EXPECT_EQ(ServiceWorkerVersion::RUNNING
,
656 version
->running_status());
657 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, version
->status());
659 RunUnregisterJob(GURL("http://www.example.com/"));
661 // The version should be stopped since there is no controllee after
663 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
664 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
667 // Tests that the active worker enters the 'redundant' state upon
669 TEST_F(ServiceWorkerJobTest
, UnregisterActiveSetsRedundant
) {
670 scoped_refptr
<ServiceWorkerRegistration
> registration
=
671 RunRegisterJob(GURL("http://www.example.com/"),
672 GURL("http://www.example.com/service_worker.js"));
673 ASSERT_TRUE(registration
.get());
675 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
676 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
677 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
679 RunUnregisterJob(GURL("http://www.example.com/"));
681 // The version should be stopped since there is no controllee after
683 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
684 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
687 // Tests that the active worker enters the 'redundant' state upon
689 TEST_F(ServiceWorkerJobTest
,
690 UnregisterActiveSetsRedundant_WaitForNoControllee
) {
691 scoped_refptr
<ServiceWorkerRegistration
> registration
=
692 RunRegisterJob(GURL("http://www.example.com/"),
693 GURL("http://www.example.com/service_worker.js"));
694 ASSERT_TRUE(registration
.get());
696 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
697 registration
->active_version()->AddControllee(host
.get());
699 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
700 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
701 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
703 RunUnregisterJob(GURL("http://www.example.com/"));
705 // The version should be running since there is still a controllee.
706 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
707 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
709 registration
->active_version()->RemoveControllee(host
.get());
710 base::RunLoop().RunUntilIdle();
712 // The version should be stopped since there is no controllee.
713 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
714 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
717 namespace { // Helpers for the update job tests.
719 const GURL
kNoChangeOrigin("http://nochange/");
720 const GURL
kNewVersionOrigin("http://newversion/");
721 const std::string
kScope("scope/");
722 const std::string
kScript("script.js");
724 void RunNestedUntilIdle() {
725 base::MessageLoop::ScopedNestableTaskAllower
allow(
726 base::MessageLoop::current());
727 base::MessageLoop::current()->RunUntilIdle();
730 void OnIOComplete(int* rv_out
, int rv
) {
735 ServiceWorkerStorage
* storage
, int64 id
,
736 const std::string
& headers
,
737 IOBuffer
* body
, int length
) {
738 scoped_ptr
<ServiceWorkerResponseWriter
> writer
=
739 storage
->CreateResponseWriter(id
);
741 scoped_ptr
<net::HttpResponseInfo
> info(new net::HttpResponseInfo
);
742 info
->request_time
= base::Time::Now();
743 info
->response_time
= base::Time::Now();
744 info
->was_cached
= false;
745 info
->headers
= new net::HttpResponseHeaders(headers
);
746 scoped_refptr
<HttpResponseInfoIOBuffer
> info_buffer
=
747 new HttpResponseInfoIOBuffer(info
.release());
750 writer
->WriteInfo(info_buffer
.get(), base::Bind(&OnIOComplete
, &rv
));
751 RunNestedUntilIdle();
755 writer
->WriteData(body
, length
,
756 base::Bind(&OnIOComplete
, &rv
));
757 RunNestedUntilIdle();
758 EXPECT_EQ(length
, rv
);
761 void WriteStringResponse(
762 ServiceWorkerStorage
* storage
, int64 id
,
763 const std::string
& body
) {
764 scoped_refptr
<IOBuffer
> body_buffer(new WrappedIOBuffer(body
.data()));
765 const char kHttpHeaders
[] = "HTTP/1.0 200 HONKYDORY\0\0";
766 std::string
headers(kHttpHeaders
, arraysize(kHttpHeaders
));
767 WriteResponse(storage
, id
, headers
, body_buffer
.get(), body
.length());
770 class UpdateJobTestHelper
771 : public EmbeddedWorkerTestHelper
,
772 public ServiceWorkerRegistration::Listener
,
773 public ServiceWorkerVersion::Listener
{
775 struct AttributeChangeLogEntry
{
776 int64 registration_id
;
777 ChangedVersionAttributesMask mask
;
778 ServiceWorkerRegistrationInfo info
;
781 struct StateChangeLogEntry
{
783 ServiceWorkerVersion::Status status
;
786 UpdateJobTestHelper(int mock_render_process_id
)
787 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
),
788 update_found_(false) {}
789 ~UpdateJobTestHelper() override
{
790 if (registration_
.get())
791 registration_
->RemoveListener(this);
794 ServiceWorkerStorage
* storage() { return context()->storage(); }
795 ServiceWorkerJobCoordinator
* job_coordinator() {
796 return context()->job_coordinator();
799 scoped_refptr
<ServiceWorkerRegistration
> SetupInitialRegistration(
800 const GURL
& test_origin
) {
801 scoped_refptr
<ServiceWorkerRegistration
> registration
;
803 job_coordinator()->Register(
804 test_origin
.Resolve(kScope
),
805 test_origin
.Resolve(kScript
),
807 SaveRegistration(SERVICE_WORKER_OK
, &called
, ®istration
));
808 base::RunLoop().RunUntilIdle();
810 EXPECT_TRUE(registration
.get());
811 EXPECT_TRUE(registration
->active_version());
812 EXPECT_FALSE(registration
->installing_version());
813 EXPECT_FALSE(registration
->waiting_version());
814 registration_
= registration
;
818 // EmbeddedWorkerTestHelper overrides
819 void OnStartWorker(int embedded_worker_id
,
823 bool pause_after_download
) override
{
824 const std::string kMockScriptBody
= "mock_script";
825 const uint64 kMockScriptSize
= 19284;
826 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
827 ASSERT_TRUE(version
);
828 version
->AddListener(this);
830 if (!pause_after_download
) {
831 // Spoof caching the script for the initial version.
832 int64 resource_id
= storage()->NewResourceId();
833 version
->script_cache_map()->NotifyStartedCaching(script
, resource_id
);
834 WriteStringResponse(storage(), resource_id
, kMockScriptBody
);
835 version
->script_cache_map()->NotifyFinishedCaching(
836 script
, kMockScriptSize
, net::URLRequestStatus(), std::string());
838 // Spoof caching the script for the new version.
839 int64 resource_id
= storage()->NewResourceId();
840 version
->script_cache_map()->NotifyStartedCaching(script
, resource_id
);
841 if (script
.GetOrigin() == kNoChangeOrigin
)
842 WriteStringResponse(storage(), resource_id
, kMockScriptBody
);
844 WriteStringResponse(storage(), resource_id
, "mock_different_script");
845 version
->script_cache_map()->NotifyFinishedCaching(
846 script
, kMockScriptSize
, net::URLRequestStatus(), std::string());
848 EmbeddedWorkerTestHelper::OnStartWorker(
849 embedded_worker_id
, version_id
, scope
, script
, pause_after_download
);
852 // ServiceWorkerRegistration::Listener overrides
853 void OnVersionAttributesChanged(
854 ServiceWorkerRegistration
* registration
,
855 ChangedVersionAttributesMask changed_mask
,
856 const ServiceWorkerRegistrationInfo
& info
) override
{
857 AttributeChangeLogEntry entry
;
858 entry
.registration_id
= registration
->id();
859 entry
.mask
= changed_mask
;
861 attribute_change_log_
.push_back(entry
);
864 void OnRegistrationFailed(ServiceWorkerRegistration
* registration
) override
{
868 void OnUpdateFound(ServiceWorkerRegistration
* registration
) override
{
869 ASSERT_FALSE(update_found_
);
870 update_found_
= true;
873 // ServiceWorkerVersion::Listener overrides
874 void OnVersionStateChanged(ServiceWorkerVersion
* version
) override
{
875 StateChangeLogEntry entry
;
876 entry
.version_id
= version
->version_id();
877 entry
.status
= version
->status();
878 state_change_log_
.push_back(entry
);
881 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
883 std::vector
<AttributeChangeLogEntry
> attribute_change_log_
;
884 std::vector
<StateChangeLogEntry
> state_change_log_
;
890 TEST_F(ServiceWorkerJobTest
, Update_NoChange
) {
891 UpdateJobTestHelper
* update_helper
=
892 new UpdateJobTestHelper(render_process_id_
);
893 helper_
.reset(update_helper
);
894 scoped_refptr
<ServiceWorkerRegistration
> registration
=
895 update_helper
->SetupInitialRegistration(kNoChangeOrigin
);
896 ASSERT_TRUE(registration
.get());
897 ASSERT_EQ(4u, update_helper
->state_change_log_
.size());
898 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
899 update_helper
->state_change_log_
[0].status
);
900 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
901 update_helper
->state_change_log_
[1].status
);
902 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
903 update_helper
->state_change_log_
[2].status
);
904 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
905 update_helper
->state_change_log_
[3].status
);
906 update_helper
->state_change_log_
.clear();
908 // Run the update job.
909 registration
->AddListener(update_helper
);
910 scoped_refptr
<ServiceWorkerVersion
> first_version
=
911 registration
->active_version();
912 first_version
->StartUpdate();
913 base::RunLoop().RunUntilIdle();
916 ASSERT_TRUE(registration
->active_version());
917 EXPECT_EQ(first_version
.get(), registration
->active_version());
918 EXPECT_FALSE(registration
->installing_version());
919 EXPECT_FALSE(registration
->waiting_version());
920 EXPECT_TRUE(update_helper
->attribute_change_log_
.empty());
921 ASSERT_EQ(1u, update_helper
->state_change_log_
.size());
922 EXPECT_NE(registration
->active_version()->version_id(),
923 update_helper
->state_change_log_
[0].version_id
);
924 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
925 update_helper
->state_change_log_
[0].status
);
926 EXPECT_FALSE(update_helper
->update_found_
);
929 TEST_F(ServiceWorkerJobTest
, Update_NewVersion
) {
930 UpdateJobTestHelper
* update_helper
=
931 new UpdateJobTestHelper(render_process_id_
);
932 helper_
.reset(update_helper
);
933 scoped_refptr
<ServiceWorkerRegistration
> registration
=
934 update_helper
->SetupInitialRegistration(kNewVersionOrigin
);
935 ASSERT_TRUE(registration
.get());
936 update_helper
->state_change_log_
.clear();
938 // Run the update job.
939 registration
->AddListener(update_helper
);
940 scoped_refptr
<ServiceWorkerVersion
> first_version
=
941 registration
->active_version();
942 first_version
->StartUpdate();
943 base::RunLoop().RunUntilIdle();
946 ASSERT_TRUE(registration
->active_version());
947 EXPECT_NE(first_version
.get(), registration
->active_version());
948 EXPECT_FALSE(registration
->installing_version());
949 EXPECT_FALSE(registration
->waiting_version());
950 ASSERT_EQ(3u, update_helper
->attribute_change_log_
.size());
952 UpdateJobTestHelper::AttributeChangeLogEntry entry
;
953 entry
= update_helper
->attribute_change_log_
[0];
954 EXPECT_TRUE(entry
.mask
.installing_changed());
955 EXPECT_FALSE(entry
.mask
.waiting_changed());
956 EXPECT_FALSE(entry
.mask
.active_changed());
957 EXPECT_NE(entry
.info
.installing_version
.version_id
,
958 kInvalidServiceWorkerVersionId
);
959 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
960 kInvalidServiceWorkerVersionId
);
961 EXPECT_NE(entry
.info
.active_version
.version_id
,
962 kInvalidServiceWorkerVersionId
);
964 entry
= update_helper
->attribute_change_log_
[1];
965 EXPECT_TRUE(entry
.mask
.installing_changed());
966 EXPECT_TRUE(entry
.mask
.waiting_changed());
967 EXPECT_FALSE(entry
.mask
.active_changed());
968 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
969 kInvalidServiceWorkerVersionId
);
970 EXPECT_NE(entry
.info
.waiting_version
.version_id
,
971 kInvalidServiceWorkerVersionId
);
972 EXPECT_NE(entry
.info
.active_version
.version_id
,
973 kInvalidServiceWorkerVersionId
);
975 entry
= update_helper
->attribute_change_log_
[2];
976 EXPECT_FALSE(entry
.mask
.installing_changed());
977 EXPECT_TRUE(entry
.mask
.waiting_changed());
978 EXPECT_TRUE(entry
.mask
.active_changed());
979 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
980 kInvalidServiceWorkerVersionId
);
981 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
982 kInvalidServiceWorkerVersionId
);
983 EXPECT_NE(entry
.info
.active_version
.version_id
,
984 kInvalidServiceWorkerVersionId
);
986 // expected version state transitions:
987 // new.installing, new.installed,
989 // new.activating, new.activated
990 ASSERT_EQ(5u, update_helper
->state_change_log_
.size());
992 EXPECT_EQ(registration
->active_version()->version_id(),
993 update_helper
->state_change_log_
[0].version_id
);
994 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
995 update_helper
->state_change_log_
[0].status
);
997 EXPECT_EQ(registration
->active_version()->version_id(),
998 update_helper
->state_change_log_
[1].version_id
);
999 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
1000 update_helper
->state_change_log_
[1].status
);
1002 EXPECT_EQ(first_version
->version_id(),
1003 update_helper
->state_change_log_
[2].version_id
);
1004 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
1005 update_helper
->state_change_log_
[2].status
);
1007 EXPECT_EQ(registration
->active_version()->version_id(),
1008 update_helper
->state_change_log_
[3].version_id
);
1009 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
1010 update_helper
->state_change_log_
[3].status
);
1012 EXPECT_EQ(registration
->active_version()->version_id(),
1013 update_helper
->state_change_log_
[4].version_id
);
1014 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
1015 update_helper
->state_change_log_
[4].status
);
1017 EXPECT_TRUE(update_helper
->update_found_
);
1020 TEST_F(ServiceWorkerJobTest
, Update_NewestVersionChanged
) {
1021 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1022 RunRegisterJob(GURL("http://www.example.com/one/"),
1023 GURL("http://www.example.com/service_worker.js"));
1025 ServiceWorkerVersion
* active_version
= registration
->active_version();
1027 // Queue an Update, it should abort when it starts and sees the new version.
1028 job_coordinator()->Update(registration
.get());
1030 // Add a waiting version with new script.
1031 scoped_refptr
<ServiceWorkerVersion
> version
=
1032 new ServiceWorkerVersion(registration
.get(),
1033 GURL("http://www.example.com/new_worker.js"),
1034 2L /* dummy version id */,
1035 helper_
->context()->AsWeakPtr());
1036 registration
->SetWaitingVersion(version
.get());
1038 base::RunLoop().RunUntilIdle();
1040 // Verify the registration was not modified by the Update.
1041 EXPECT_EQ(active_version
, registration
->active_version());
1042 EXPECT_EQ(version
.get(), registration
->waiting_version());
1043 EXPECT_EQ(NULL
, registration
->installing_version());
1046 TEST_F(ServiceWorkerJobTest
, Update_UninstallingRegistration
) {
1048 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1049 RunRegisterJob(GURL("http://www.example.com/one/"),
1050 GURL("http://www.example.com/service_worker.js"));
1052 // Add a controllee and queue an unregister to force the uninstalling state.
1053 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1054 ServiceWorkerVersion
* active_version
= registration
->active_version();
1055 active_version
->AddControllee(host
.get());
1056 job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
1057 SaveUnregistration(SERVICE_WORKER_OK
, &called
));
1059 // Update should abort after it starts and sees uninstalling.
1060 job_coordinator()->Update(registration
.get());
1062 EXPECT_FALSE(called
);
1063 base::RunLoop().RunUntilIdle();
1064 EXPECT_TRUE(called
);
1066 // Verify the registration was not modified by the Update.
1067 EXPECT_TRUE(registration
->is_uninstalling());
1068 EXPECT_EQ(active_version
, registration
->active_version());
1069 EXPECT_EQ(NULL
, registration
->waiting_version());
1070 EXPECT_EQ(NULL
, registration
->installing_version());
1073 TEST_F(ServiceWorkerJobTest
, RegisterWhileUninstalling
) {
1074 GURL
pattern("http://www.example.com/one/");
1075 GURL
script1("http://www.example.com/service_worker.js");
1076 GURL
script2("http://www.example.com/service_worker.js?new");
1078 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1079 RunRegisterJob(pattern
, script1
);
1081 // Add a controllee and queue an unregister to force the uninstalling state.
1082 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1083 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1084 registration
->active_version();
1085 old_version
->AddControllee(host
.get());
1086 RunUnregisterJob(pattern
);
1088 // Register another script.
1089 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1091 EXPECT_FALSE(registration
->is_uninstalling());
1092 EXPECT_EQ(old_version
, registration
->active_version());
1094 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1095 registration
->waiting_version();
1097 // Verify the new version is installed but not activated yet.
1098 EXPECT_EQ(NULL
, registration
->installing_version());
1099 EXPECT_TRUE(new_version
);
1100 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1101 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1103 old_version
->RemoveControllee(host
.get());
1104 base::RunLoop().RunUntilIdle();
1106 EXPECT_FALSE(registration
->is_uninstalling());
1107 EXPECT_FALSE(registration
->is_uninstalled());
1109 // Verify the new version is activated.
1110 EXPECT_EQ(NULL
, registration
->installing_version());
1111 EXPECT_EQ(NULL
, registration
->waiting_version());
1112 EXPECT_EQ(new_version
, registration
->active_version());
1113 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1114 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1117 TEST_F(ServiceWorkerJobTest
, RegisterAndUnregisterWhileUninstalling
) {
1118 GURL
pattern("http://www.example.com/one/");
1119 GURL
script1("http://www.example.com/service_worker.js");
1120 GURL
script2("http://www.example.com/service_worker.js?new");
1122 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1123 RunRegisterJob(pattern
, script1
);
1125 // Add a controllee and queue an unregister to force the uninstalling state.
1126 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1127 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1128 registration
->active_version();
1129 old_version
->AddControllee(host
.get());
1130 RunUnregisterJob(pattern
);
1132 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1134 EXPECT_EQ(registration
, FindRegistrationForPattern(pattern
));
1135 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1136 registration
->waiting_version();
1137 ASSERT_TRUE(new_version
);
1139 // Unregister the registration (but it's still live).
1140 RunUnregisterJob(pattern
);
1141 // Now it's not found in the storage.
1142 RunUnregisterJob(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1144 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1145 EXPECT_TRUE(registration
->is_uninstalling());
1146 EXPECT_EQ(old_version
, registration
->active_version());
1148 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, old_version
->running_status());
1149 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, old_version
->status());
1150 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1151 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1153 old_version
->RemoveControllee(host
.get());
1154 base::RunLoop().RunUntilIdle();
1156 EXPECT_FALSE(registration
->is_uninstalling());
1157 EXPECT_TRUE(registration
->is_uninstalled());
1159 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1160 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1161 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, new_version
->running_status());
1162 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, new_version
->status());
1165 TEST_F(ServiceWorkerJobTest
, RegisterSameScriptMultipleTimesWhileUninstalling
) {
1166 GURL
pattern("http://www.example.com/one/");
1167 GURL
script1("http://www.example.com/service_worker.js");
1168 GURL
script2("http://www.example.com/service_worker.js?new");
1170 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1171 RunRegisterJob(pattern
, script1
);
1173 // Add a controllee and queue an unregister to force the uninstalling state.
1174 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1175 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1176 registration
->active_version();
1177 old_version
->AddControllee(host
.get());
1178 RunUnregisterJob(pattern
);
1180 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1182 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1183 registration
->waiting_version();
1184 ASSERT_TRUE(new_version
);
1186 RunUnregisterJob(pattern
);
1188 EXPECT_TRUE(registration
->is_uninstalling());
1190 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1192 EXPECT_FALSE(registration
->is_uninstalling());
1193 EXPECT_EQ(new_version
, registration
->waiting_version());
1195 old_version
->RemoveControllee(host
.get());
1196 base::RunLoop().RunUntilIdle();
1198 EXPECT_FALSE(registration
->is_uninstalling());
1199 EXPECT_FALSE(registration
->is_uninstalled());
1201 // Verify the new version is activated.
1202 EXPECT_EQ(NULL
, registration
->installing_version());
1203 EXPECT_EQ(NULL
, registration
->waiting_version());
1204 EXPECT_EQ(new_version
, registration
->active_version());
1205 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1206 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1209 TEST_F(ServiceWorkerJobTest
, RegisterMultipleTimesWhileUninstalling
) {
1210 GURL
pattern("http://www.example.com/one/");
1211 GURL
script1("http://www.example.com/service_worker.js?first");
1212 GURL
script2("http://www.example.com/service_worker.js?second");
1213 GURL
script3("http://www.example.com/service_worker.js?third");
1215 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1216 RunRegisterJob(pattern
, script1
);
1218 // Add a controllee and queue an unregister to force the uninstalling state.
1219 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1220 scoped_refptr
<ServiceWorkerVersion
> first_version
=
1221 registration
->active_version();
1222 first_version
->AddControllee(host
.get());
1223 RunUnregisterJob(pattern
);
1225 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1227 scoped_refptr
<ServiceWorkerVersion
> second_version
=
1228 registration
->waiting_version();
1229 ASSERT_TRUE(second_version
);
1231 RunUnregisterJob(pattern
);
1233 EXPECT_TRUE(registration
->is_uninstalling());
1235 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script3
));
1237 scoped_refptr
<ServiceWorkerVersion
> third_version
=
1238 registration
->waiting_version();
1239 ASSERT_TRUE(third_version
);
1241 EXPECT_FALSE(registration
->is_uninstalling());
1242 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, second_version
->status());
1244 first_version
->RemoveControllee(host
.get());
1245 base::RunLoop().RunUntilIdle();
1247 EXPECT_FALSE(registration
->is_uninstalling());
1248 EXPECT_FALSE(registration
->is_uninstalled());
1250 // Verify the new version is activated.
1251 EXPECT_EQ(NULL
, registration
->installing_version());
1252 EXPECT_EQ(NULL
, registration
->waiting_version());
1253 EXPECT_EQ(third_version
, registration
->active_version());
1254 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, third_version
->running_status());
1255 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, third_version
->status());
1258 class EventCallbackHelper
: public EmbeddedWorkerTestHelper
{
1260 explicit EventCallbackHelper(int mock_render_process_id
)
1261 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
),
1262 install_event_result_(blink::WebServiceWorkerEventResultCompleted
),
1263 activate_event_result_(blink::WebServiceWorkerEventResultCompleted
) {}
1265 void OnInstallEvent(int embedded_worker_id
,
1266 int request_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