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
>(new ServiceWorkerProviderHost(
184 33 /* dummy render_process id */, MSG_ROUTING_NONE
/* render_frame_id */,
185 1 /* dummy provider_id */, SERVICE_WORKER_PROVIDER_FOR_WINDOW
,
186 helper_
->context()->AsWeakPtr(), NULL
));
189 TEST_F(ServiceWorkerJobTest
, SameDocumentSameRegistration
) {
190 scoped_refptr
<ServiceWorkerRegistration
> original_registration
=
191 RunRegisterJob(GURL("http://www.example.com/"),
192 GURL("http://www.example.com/service_worker.js"));
194 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
195 storage()->FindRegistrationForDocument(
196 GURL("http://www.example.com/"),
197 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration1
));
198 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
199 storage()->FindRegistrationForDocument(
200 GURL("http://www.example.com/"),
201 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration2
));
202 base::RunLoop().RunUntilIdle();
204 ASSERT_TRUE(registration1
.get());
205 ASSERT_EQ(registration1
, original_registration
);
206 ASSERT_EQ(registration1
, registration2
);
209 TEST_F(ServiceWorkerJobTest
, SameMatchSameRegistration
) {
211 scoped_refptr
<ServiceWorkerRegistration
> original_registration
=
212 RunRegisterJob(GURL("http://www.example.com/"),
213 GURL("http://www.example.com/service_worker.js"));
214 ASSERT_NE(static_cast<ServiceWorkerRegistration
*>(NULL
),
215 original_registration
.get());
217 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
218 storage()->FindRegistrationForDocument(
219 GURL("http://www.example.com/one"),
220 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration1
));
221 base::RunLoop().RunUntilIdle();
224 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
225 storage()->FindRegistrationForDocument(
226 GURL("http://www.example.com/two"),
227 SaveFoundRegistration(SERVICE_WORKER_OK
, &called
, ®istration2
));
228 base::RunLoop().RunUntilIdle();
230 ASSERT_EQ(registration1
, original_registration
);
231 ASSERT_EQ(registration1
, registration2
);
234 TEST_F(ServiceWorkerJobTest
, DifferentMatchDifferentRegistration
) {
236 scoped_refptr
<ServiceWorkerRegistration
> original_registration1
;
237 job_coordinator()->Register(
238 GURL("http://www.example.com/one/"),
239 GURL("http://www.example.com/service_worker.js"),
241 SaveRegistration(SERVICE_WORKER_OK
, &called1
, &original_registration1
));
244 scoped_refptr
<ServiceWorkerRegistration
> original_registration2
;
245 job_coordinator()->Register(
246 GURL("http://www.example.com/two/"),
247 GURL("http://www.example.com/service_worker.js"),
249 SaveRegistration(SERVICE_WORKER_OK
, &called2
, &original_registration2
));
251 EXPECT_FALSE(called1
);
252 EXPECT_FALSE(called2
);
253 base::RunLoop().RunUntilIdle();
254 EXPECT_TRUE(called2
);
255 EXPECT_TRUE(called1
);
257 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
258 storage()->FindRegistrationForDocument(
259 GURL("http://www.example.com/one/"),
260 SaveFoundRegistration(SERVICE_WORKER_OK
, &called1
, ®istration1
));
261 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
262 storage()->FindRegistrationForDocument(
263 GURL("http://www.example.com/two/"),
264 SaveFoundRegistration(SERVICE_WORKER_OK
, &called2
, ®istration2
));
266 base::RunLoop().RunUntilIdle();
267 EXPECT_TRUE(called2
);
268 EXPECT_TRUE(called1
);
269 ASSERT_NE(registration1
, registration2
);
272 // Make sure basic registration is working.
273 TEST_F(ServiceWorkerJobTest
, Register
) {
274 scoped_refptr
<ServiceWorkerRegistration
> registration
=
275 RunRegisterJob(GURL("http://www.example.com/"),
276 GURL("http://www.example.com/service_worker.js"));
278 ASSERT_NE(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
281 // Make sure registrations are cleaned up when they are unregistered.
282 TEST_F(ServiceWorkerJobTest
, Unregister
) {
283 GURL
pattern("http://www.example.com/");
285 scoped_refptr
<ServiceWorkerRegistration
> registration
=
286 RunRegisterJob(pattern
, GURL("http://www.example.com/service_worker.js"));
288 RunUnregisterJob(pattern
);
290 ASSERT_TRUE(registration
->HasOneRef());
292 registration
= FindRegistrationForPattern(pattern
,
293 SERVICE_WORKER_ERROR_NOT_FOUND
);
295 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
298 TEST_F(ServiceWorkerJobTest
, Unregister_NothingRegistered
) {
299 GURL
pattern("http://www.example.com/");
301 RunUnregisterJob(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
304 // Make sure registering a new script creates a new version and shares an
305 // existing registration.
306 TEST_F(ServiceWorkerJobTest
, RegisterNewScript
) {
307 GURL
pattern("http://www.example.com/");
309 scoped_refptr
<ServiceWorkerRegistration
> old_registration
=
310 RunRegisterJob(pattern
, GURL("http://www.example.com/service_worker.js"));
312 scoped_refptr
<ServiceWorkerRegistration
> old_registration_by_pattern
=
313 FindRegistrationForPattern(pattern
);
315 ASSERT_EQ(old_registration
, old_registration_by_pattern
);
316 old_registration_by_pattern
= NULL
;
318 scoped_refptr
<ServiceWorkerRegistration
> new_registration
=
319 RunRegisterJob(pattern
,
320 GURL("http://www.example.com/service_worker_new.js"));
322 ASSERT_EQ(old_registration
, new_registration
);
324 scoped_refptr
<ServiceWorkerRegistration
> new_registration_by_pattern
=
325 FindRegistrationForPattern(pattern
);
327 ASSERT_EQ(new_registration
, new_registration_by_pattern
);
330 // Make sure that when registering a duplicate pattern+script_url
331 // combination, that the same registration is used.
332 TEST_F(ServiceWorkerJobTest
, RegisterDuplicateScript
) {
333 GURL
pattern("http://www.example.com/");
334 GURL
script_url("http://www.example.com/service_worker.js");
336 scoped_refptr
<ServiceWorkerRegistration
> old_registration
=
337 RunRegisterJob(pattern
, script_url
);
339 scoped_refptr
<ServiceWorkerRegistration
> old_registration_by_pattern
=
340 FindRegistrationForPattern(pattern
);
342 ASSERT_TRUE(old_registration_by_pattern
.get());
344 scoped_refptr
<ServiceWorkerRegistration
> new_registration
=
345 RunRegisterJob(pattern
, script_url
);
347 ASSERT_EQ(old_registration
, new_registration
);
349 ASSERT_FALSE(old_registration
->HasOneRef());
351 scoped_refptr
<ServiceWorkerRegistration
> new_registration_by_pattern
=
352 FindRegistrationForPattern(pattern
);
354 ASSERT_EQ(new_registration
, old_registration
);
357 class FailToStartWorkerTestHelper
: public EmbeddedWorkerTestHelper
{
359 explicit FailToStartWorkerTestHelper(int mock_render_process_id
)
360 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
) {}
362 void OnStartWorker(int embedded_worker_id
,
363 int64 service_worker_version_id
,
365 const GURL
& script_url
,
366 bool pause_after_download
) override
{
367 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
368 registry()->OnWorkerStopped(worker
->process_id(), embedded_worker_id
);
372 TEST_F(ServiceWorkerJobTest
, Register_FailToStartWorker
) {
373 helper_
.reset(new FailToStartWorkerTestHelper(render_process_id_
));
375 scoped_refptr
<ServiceWorkerRegistration
> registration
=
376 RunRegisterJob(GURL("http://www.example.com/"),
377 GURL("http://www.example.com/service_worker.js"),
378 SERVICE_WORKER_ERROR_START_WORKER_FAILED
);
380 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
383 // Register and then unregister the pattern, in parallel. Job coordinator should
384 // process jobs until the last job.
385 TEST_F(ServiceWorkerJobTest
, ParallelRegUnreg
) {
386 GURL
pattern("http://www.example.com/");
387 GURL
script_url("http://www.example.com/service_worker.js");
389 bool registration_called
= false;
390 scoped_refptr
<ServiceWorkerRegistration
> registration
;
391 job_coordinator()->Register(
395 SaveRegistration(SERVICE_WORKER_OK
, ®istration_called
, ®istration
));
397 bool unregistration_called
= false;
398 job_coordinator()->Unregister(
400 SaveUnregistration(SERVICE_WORKER_OK
, &unregistration_called
));
402 ASSERT_FALSE(registration_called
);
403 ASSERT_FALSE(unregistration_called
);
404 base::RunLoop().RunUntilIdle();
405 ASSERT_TRUE(registration_called
);
406 ASSERT_TRUE(unregistration_called
);
408 registration
= FindRegistrationForPattern(pattern
,
409 SERVICE_WORKER_ERROR_NOT_FOUND
);
411 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
414 // Register conflicting scripts for the same pattern. The most recent
415 // registration should win, and the old registration should have been
417 TEST_F(ServiceWorkerJobTest
, ParallelRegNewScript
) {
418 GURL
pattern("http://www.example.com/");
420 GURL
script_url1("http://www.example.com/service_worker1.js");
421 bool registration1_called
= false;
422 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
423 job_coordinator()->Register(
428 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
430 GURL
script_url2("http://www.example.com/service_worker2.js");
431 bool registration2_called
= false;
432 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
433 job_coordinator()->Register(
438 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
440 ASSERT_FALSE(registration1_called
);
441 ASSERT_FALSE(registration2_called
);
442 base::RunLoop().RunUntilIdle();
443 ASSERT_TRUE(registration1_called
);
444 ASSERT_TRUE(registration2_called
);
446 scoped_refptr
<ServiceWorkerRegistration
> registration
=
447 FindRegistrationForPattern(pattern
);
449 ASSERT_EQ(registration2
, registration
);
452 // Register the exact same pattern + script. Requests should be
453 // coalesced such that both callers get the exact same registration
455 TEST_F(ServiceWorkerJobTest
, ParallelRegSameScript
) {
456 GURL
pattern("http://www.example.com/");
458 GURL
script_url("http://www.example.com/service_worker1.js");
459 bool registration1_called
= false;
460 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
461 job_coordinator()->Register(
466 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
468 bool registration2_called
= false;
469 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
470 job_coordinator()->Register(
475 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
477 ASSERT_FALSE(registration1_called
);
478 ASSERT_FALSE(registration2_called
);
479 base::RunLoop().RunUntilIdle();
480 ASSERT_TRUE(registration1_called
);
481 ASSERT_TRUE(registration2_called
);
483 ASSERT_EQ(registration1
, registration2
);
485 scoped_refptr
<ServiceWorkerRegistration
> registration
=
486 FindRegistrationForPattern(pattern
);
488 ASSERT_EQ(registration
, registration1
);
491 // Call simulataneous unregister calls.
492 TEST_F(ServiceWorkerJobTest
, ParallelUnreg
) {
493 GURL
pattern("http://www.example.com/");
495 GURL
script_url("http://www.example.com/service_worker.js");
496 bool unregistration1_called
= false;
497 job_coordinator()->Unregister(
499 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
500 &unregistration1_called
));
502 bool unregistration2_called
= false;
503 job_coordinator()->Unregister(
505 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
506 &unregistration2_called
));
508 ASSERT_FALSE(unregistration1_called
);
509 ASSERT_FALSE(unregistration2_called
);
510 base::RunLoop().RunUntilIdle();
511 ASSERT_TRUE(unregistration1_called
);
512 ASSERT_TRUE(unregistration2_called
);
514 // There isn't really a way to test that they are being coalesced,
515 // but we can make sure they can exist simultaneously without
517 scoped_refptr
<ServiceWorkerRegistration
> registration
=
518 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
520 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
523 TEST_F(ServiceWorkerJobTest
, AbortAll_Register
) {
524 GURL
pattern1("http://www1.example.com/");
525 GURL
pattern2("http://www2.example.com/");
526 GURL
script_url1("http://www1.example.com/service_worker.js");
527 GURL
script_url2("http://www2.example.com/service_worker.js");
529 bool registration_called1
= false;
530 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
531 job_coordinator()->Register(
535 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
536 ®istration_called1
, ®istration1
));
538 bool registration_called2
= false;
539 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
540 job_coordinator()->Register(
544 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
545 ®istration_called2
, ®istration2
));
547 ASSERT_FALSE(registration_called1
);
548 ASSERT_FALSE(registration_called2
);
549 job_coordinator()->AbortAll();
551 base::RunLoop().RunUntilIdle();
552 ASSERT_TRUE(registration_called1
);
553 ASSERT_TRUE(registration_called2
);
555 bool find_called1
= false;
556 storage()->FindRegistrationForPattern(
558 SaveFoundRegistration(
559 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called1
, ®istration1
));
561 bool find_called2
= false;
562 storage()->FindRegistrationForPattern(
564 SaveFoundRegistration(
565 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called2
, ®istration2
));
567 base::RunLoop().RunUntilIdle();
568 ASSERT_TRUE(find_called1
);
569 ASSERT_TRUE(find_called2
);
570 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration1
);
571 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration2
);
574 TEST_F(ServiceWorkerJobTest
, AbortAll_Unregister
) {
575 GURL
pattern1("http://www1.example.com/");
576 GURL
pattern2("http://www2.example.com/");
578 bool unregistration_called1
= false;
579 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
580 job_coordinator()->Unregister(
582 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
583 &unregistration_called1
));
585 bool unregistration_called2
= false;
586 job_coordinator()->Unregister(
588 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
589 &unregistration_called2
));
591 ASSERT_FALSE(unregistration_called1
);
592 ASSERT_FALSE(unregistration_called2
);
593 job_coordinator()->AbortAll();
595 base::RunLoop().RunUntilIdle();
596 ASSERT_TRUE(unregistration_called1
);
597 ASSERT_TRUE(unregistration_called2
);
600 TEST_F(ServiceWorkerJobTest
, AbortAll_RegUnreg
) {
601 GURL
pattern("http://www.example.com/");
602 GURL
script_url("http://www.example.com/service_worker.js");
604 bool registration_called
= false;
605 scoped_refptr
<ServiceWorkerRegistration
> registration
;
606 job_coordinator()->Register(
610 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
611 ®istration_called
, ®istration
));
613 bool unregistration_called
= false;
614 job_coordinator()->Unregister(
616 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
617 &unregistration_called
));
619 ASSERT_FALSE(registration_called
);
620 ASSERT_FALSE(unregistration_called
);
621 job_coordinator()->AbortAll();
623 base::RunLoop().RunUntilIdle();
624 ASSERT_TRUE(registration_called
);
625 ASSERT_TRUE(unregistration_called
);
627 registration
= FindRegistrationForPattern(pattern
,
628 SERVICE_WORKER_ERROR_NOT_FOUND
);
630 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
633 // Tests that the waiting worker enters the 'redundant' state upon
635 TEST_F(ServiceWorkerJobTest
, UnregisterWaitingSetsRedundant
) {
636 GURL
script_url("http://www.example.com/service_worker.js");
637 scoped_refptr
<ServiceWorkerRegistration
> registration
=
638 RunRegisterJob(GURL("http://www.example.com/"), script_url
);
639 ASSERT_TRUE(registration
.get());
641 // Manually create the waiting worker since there is no way to become a
642 // waiting worker until Update is implemented.
643 scoped_refptr
<ServiceWorkerVersion
> version
= new ServiceWorkerVersion(
644 registration
.get(), script_url
, 1L, helper_
->context()->AsWeakPtr());
645 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
646 version
->StartWorker(CreateReceiverOnCurrentThread(&status
));
647 base::RunLoop().RunUntilIdle();
648 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
650 version
->SetStatus(ServiceWorkerVersion::INSTALLED
);
651 registration
->SetWaitingVersion(version
);
652 EXPECT_EQ(ServiceWorkerVersion::RUNNING
,
653 version
->running_status());
654 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, version
->status());
656 RunUnregisterJob(GURL("http://www.example.com/"));
658 // The version should be stopped since there is no controllee after
660 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
661 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
664 // Tests that the active worker enters the 'redundant' state upon
666 TEST_F(ServiceWorkerJobTest
, UnregisterActiveSetsRedundant
) {
667 scoped_refptr
<ServiceWorkerRegistration
> registration
=
668 RunRegisterJob(GURL("http://www.example.com/"),
669 GURL("http://www.example.com/service_worker.js"));
670 ASSERT_TRUE(registration
.get());
672 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
673 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
674 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
676 RunUnregisterJob(GURL("http://www.example.com/"));
678 // The version should be stopped since there is no controllee after
680 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
681 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
684 // Tests that the active worker enters the 'redundant' state upon
686 TEST_F(ServiceWorkerJobTest
,
687 UnregisterActiveSetsRedundant_WaitForNoControllee
) {
688 scoped_refptr
<ServiceWorkerRegistration
> registration
=
689 RunRegisterJob(GURL("http://www.example.com/"),
690 GURL("http://www.example.com/service_worker.js"));
691 ASSERT_TRUE(registration
.get());
693 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
694 registration
->active_version()->AddControllee(host
.get());
696 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
697 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
698 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
700 RunUnregisterJob(GURL("http://www.example.com/"));
702 // The version should be running since there is still a controllee.
703 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
704 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
706 registration
->active_version()->RemoveControllee(host
.get());
707 base::RunLoop().RunUntilIdle();
709 // The version should be stopped since there is no controllee.
710 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
711 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
714 namespace { // Helpers for the update job tests.
716 const GURL
kNoChangeOrigin("http://nochange/");
717 const GURL
kNewVersionOrigin("http://newversion/");
718 const std::string
kScope("scope/");
719 const std::string
kScript("script.js");
721 void RunNestedUntilIdle() {
722 base::MessageLoop::ScopedNestableTaskAllower
allow(
723 base::MessageLoop::current());
724 base::MessageLoop::current()->RunUntilIdle();
727 void OnIOComplete(int* rv_out
, int rv
) {
732 ServiceWorkerStorage
* storage
, int64 id
,
733 const std::string
& headers
,
734 IOBuffer
* body
, int length
) {
735 scoped_ptr
<ServiceWorkerResponseWriter
> writer
=
736 storage
->CreateResponseWriter(id
);
738 scoped_ptr
<net::HttpResponseInfo
> info(new net::HttpResponseInfo
);
739 info
->request_time
= base::Time::Now();
740 info
->response_time
= base::Time::Now();
741 info
->was_cached
= false;
742 info
->headers
= new net::HttpResponseHeaders(headers
);
743 scoped_refptr
<HttpResponseInfoIOBuffer
> info_buffer
=
744 new HttpResponseInfoIOBuffer(info
.release());
747 writer
->WriteInfo(info_buffer
.get(), base::Bind(&OnIOComplete
, &rv
));
748 RunNestedUntilIdle();
752 writer
->WriteData(body
, length
,
753 base::Bind(&OnIOComplete
, &rv
));
754 RunNestedUntilIdle();
755 EXPECT_EQ(length
, rv
);
758 void WriteStringResponse(
759 ServiceWorkerStorage
* storage
, int64 id
,
760 const std::string
& body
) {
761 scoped_refptr
<IOBuffer
> body_buffer(new WrappedIOBuffer(body
.data()));
762 const char kHttpHeaders
[] = "HTTP/1.0 200 HONKYDORY\0\0";
763 std::string
headers(kHttpHeaders
, arraysize(kHttpHeaders
));
764 WriteResponse(storage
, id
, headers
, body_buffer
.get(), body
.length());
767 class UpdateJobTestHelper
768 : public EmbeddedWorkerTestHelper
,
769 public ServiceWorkerRegistration::Listener
,
770 public ServiceWorkerVersion::Listener
{
772 struct AttributeChangeLogEntry
{
773 int64 registration_id
;
774 ChangedVersionAttributesMask mask
;
775 ServiceWorkerRegistrationInfo info
;
778 struct StateChangeLogEntry
{
780 ServiceWorkerVersion::Status status
;
783 UpdateJobTestHelper(int mock_render_process_id
)
784 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
),
785 update_found_(false) {}
786 ~UpdateJobTestHelper() override
{
787 if (registration_
.get())
788 registration_
->RemoveListener(this);
791 ServiceWorkerStorage
* storage() { return context()->storage(); }
792 ServiceWorkerJobCoordinator
* job_coordinator() {
793 return context()->job_coordinator();
796 scoped_refptr
<ServiceWorkerRegistration
> SetupInitialRegistration(
797 const GURL
& test_origin
) {
798 scoped_refptr
<ServiceWorkerRegistration
> registration
;
800 job_coordinator()->Register(
801 test_origin
.Resolve(kScope
),
802 test_origin
.Resolve(kScript
),
804 SaveRegistration(SERVICE_WORKER_OK
, &called
, ®istration
));
805 base::RunLoop().RunUntilIdle();
807 EXPECT_TRUE(registration
.get());
808 EXPECT_TRUE(registration
->active_version());
809 EXPECT_FALSE(registration
->installing_version());
810 EXPECT_FALSE(registration
->waiting_version());
811 registration_
= registration
;
815 // EmbeddedWorkerTestHelper overrides
816 void OnStartWorker(int embedded_worker_id
,
820 bool pause_after_download
) override
{
821 const std::string kMockScriptBody
= "mock_script";
822 const uint64 kMockScriptSize
= 19284;
823 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
824 ASSERT_TRUE(version
);
825 version
->AddListener(this);
827 if (!pause_after_download
) {
828 // Spoof caching the script for the initial version.
829 int64 resource_id
= storage()->NewResourceId();
830 version
->script_cache_map()->NotifyStartedCaching(script
, resource_id
);
831 WriteStringResponse(storage(), resource_id
, kMockScriptBody
);
832 version
->script_cache_map()->NotifyFinishedCaching(
833 script
, kMockScriptSize
, net::URLRequestStatus(), std::string());
835 // Spoof caching the script for the new version.
836 int64 resource_id
= storage()->NewResourceId();
837 version
->script_cache_map()->NotifyStartedCaching(script
, resource_id
);
838 if (script
.GetOrigin() == kNoChangeOrigin
)
839 WriteStringResponse(storage(), resource_id
, kMockScriptBody
);
841 WriteStringResponse(storage(), resource_id
, "mock_different_script");
842 version
->script_cache_map()->NotifyFinishedCaching(
843 script
, kMockScriptSize
, net::URLRequestStatus(), std::string());
845 EmbeddedWorkerTestHelper::OnStartWorker(
846 embedded_worker_id
, version_id
, scope
, script
, pause_after_download
);
849 // ServiceWorkerRegistration::Listener overrides
850 void OnVersionAttributesChanged(
851 ServiceWorkerRegistration
* registration
,
852 ChangedVersionAttributesMask changed_mask
,
853 const ServiceWorkerRegistrationInfo
& info
) override
{
854 AttributeChangeLogEntry entry
;
855 entry
.registration_id
= registration
->id();
856 entry
.mask
= changed_mask
;
858 attribute_change_log_
.push_back(entry
);
861 void OnRegistrationFailed(ServiceWorkerRegistration
* registration
) override
{
865 void OnUpdateFound(ServiceWorkerRegistration
* registration
) override
{
866 ASSERT_FALSE(update_found_
);
867 update_found_
= true;
870 // ServiceWorkerVersion::Listener overrides
871 void OnVersionStateChanged(ServiceWorkerVersion
* version
) override
{
872 StateChangeLogEntry entry
;
873 entry
.version_id
= version
->version_id();
874 entry
.status
= version
->status();
875 state_change_log_
.push_back(entry
);
878 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
880 std::vector
<AttributeChangeLogEntry
> attribute_change_log_
;
881 std::vector
<StateChangeLogEntry
> state_change_log_
;
885 // Helper class for update tests that evicts the active version when the update
886 // worker is about to be started.
887 class EvictIncumbentVersionHelper
: public UpdateJobTestHelper
{
889 EvictIncumbentVersionHelper(int mock_render_process_id
)
890 : UpdateJobTestHelper(mock_render_process_id
) {}
891 ~EvictIncumbentVersionHelper() override
{}
893 void OnStartWorker(int embedded_worker_id
,
897 bool pause_after_download
) override
{
898 if (pause_after_download
) {
899 // Evict the incumbent worker.
900 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
901 ASSERT_TRUE(version
);
902 ServiceWorkerRegistration
* registration
=
903 context()->GetLiveRegistration(version
->registration_id());
904 ASSERT_TRUE(registration
);
905 ASSERT_TRUE(registration
->active_version());
906 ASSERT_FALSE(registration
->waiting_version());
907 registration
->DeleteVersion(
908 make_scoped_refptr(registration
->active_version()));
910 UpdateJobTestHelper::OnStartWorker(embedded_worker_id
, version_id
, scope
,
911 script
, pause_after_download
);
914 void OnRegistrationFailed(ServiceWorkerRegistration
* registration
) override
{
915 registration_failed_
= true;
918 bool registration_failed_
= false;
923 TEST_F(ServiceWorkerJobTest
, Update_NoChange
) {
924 UpdateJobTestHelper
* update_helper
=
925 new UpdateJobTestHelper(render_process_id_
);
926 helper_
.reset(update_helper
);
927 scoped_refptr
<ServiceWorkerRegistration
> registration
=
928 update_helper
->SetupInitialRegistration(kNoChangeOrigin
);
929 ASSERT_TRUE(registration
.get());
930 ASSERT_EQ(4u, update_helper
->state_change_log_
.size());
931 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
932 update_helper
->state_change_log_
[0].status
);
933 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
934 update_helper
->state_change_log_
[1].status
);
935 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
936 update_helper
->state_change_log_
[2].status
);
937 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
938 update_helper
->state_change_log_
[3].status
);
939 update_helper
->state_change_log_
.clear();
941 // Run the update job.
942 registration
->AddListener(update_helper
);
943 scoped_refptr
<ServiceWorkerVersion
> first_version
=
944 registration
->active_version();
945 first_version
->StartUpdate();
946 base::RunLoop().RunUntilIdle();
949 ASSERT_TRUE(registration
->active_version());
950 EXPECT_EQ(first_version
.get(), registration
->active_version());
951 EXPECT_FALSE(registration
->installing_version());
952 EXPECT_FALSE(registration
->waiting_version());
953 EXPECT_TRUE(update_helper
->attribute_change_log_
.empty());
954 ASSERT_EQ(1u, update_helper
->state_change_log_
.size());
955 EXPECT_NE(registration
->active_version()->version_id(),
956 update_helper
->state_change_log_
[0].version_id
);
957 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
958 update_helper
->state_change_log_
[0].status
);
959 EXPECT_FALSE(update_helper
->update_found_
);
962 TEST_F(ServiceWorkerJobTest
, Update_NewVersion
) {
963 UpdateJobTestHelper
* update_helper
=
964 new UpdateJobTestHelper(render_process_id_
);
965 helper_
.reset(update_helper
);
966 scoped_refptr
<ServiceWorkerRegistration
> registration
=
967 update_helper
->SetupInitialRegistration(kNewVersionOrigin
);
968 ASSERT_TRUE(registration
.get());
969 update_helper
->state_change_log_
.clear();
971 // Run the update job.
972 registration
->AddListener(update_helper
);
973 scoped_refptr
<ServiceWorkerVersion
> first_version
=
974 registration
->active_version();
975 first_version
->StartUpdate();
976 base::RunLoop().RunUntilIdle();
979 ASSERT_TRUE(registration
->active_version());
980 EXPECT_NE(first_version
.get(), registration
->active_version());
981 EXPECT_FALSE(registration
->installing_version());
982 EXPECT_FALSE(registration
->waiting_version());
983 ASSERT_EQ(3u, update_helper
->attribute_change_log_
.size());
985 UpdateJobTestHelper::AttributeChangeLogEntry entry
;
986 entry
= update_helper
->attribute_change_log_
[0];
987 EXPECT_TRUE(entry
.mask
.installing_changed());
988 EXPECT_FALSE(entry
.mask
.waiting_changed());
989 EXPECT_FALSE(entry
.mask
.active_changed());
990 EXPECT_NE(entry
.info
.installing_version
.version_id
,
991 kInvalidServiceWorkerVersionId
);
992 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
993 kInvalidServiceWorkerVersionId
);
994 EXPECT_NE(entry
.info
.active_version
.version_id
,
995 kInvalidServiceWorkerVersionId
);
997 entry
= update_helper
->attribute_change_log_
[1];
998 EXPECT_TRUE(entry
.mask
.installing_changed());
999 EXPECT_TRUE(entry
.mask
.waiting_changed());
1000 EXPECT_FALSE(entry
.mask
.active_changed());
1001 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
1002 kInvalidServiceWorkerVersionId
);
1003 EXPECT_NE(entry
.info
.waiting_version
.version_id
,
1004 kInvalidServiceWorkerVersionId
);
1005 EXPECT_NE(entry
.info
.active_version
.version_id
,
1006 kInvalidServiceWorkerVersionId
);
1008 entry
= update_helper
->attribute_change_log_
[2];
1009 EXPECT_FALSE(entry
.mask
.installing_changed());
1010 EXPECT_TRUE(entry
.mask
.waiting_changed());
1011 EXPECT_TRUE(entry
.mask
.active_changed());
1012 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
1013 kInvalidServiceWorkerVersionId
);
1014 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
1015 kInvalidServiceWorkerVersionId
);
1016 EXPECT_NE(entry
.info
.active_version
.version_id
,
1017 kInvalidServiceWorkerVersionId
);
1019 // expected version state transitions:
1020 // new.installing, new.installed,
1022 // new.activating, new.activated
1023 ASSERT_EQ(5u, update_helper
->state_change_log_
.size());
1025 EXPECT_EQ(registration
->active_version()->version_id(),
1026 update_helper
->state_change_log_
[0].version_id
);
1027 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
1028 update_helper
->state_change_log_
[0].status
);
1030 EXPECT_EQ(registration
->active_version()->version_id(),
1031 update_helper
->state_change_log_
[1].version_id
);
1032 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
1033 update_helper
->state_change_log_
[1].status
);
1035 EXPECT_EQ(first_version
->version_id(),
1036 update_helper
->state_change_log_
[2].version_id
);
1037 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
1038 update_helper
->state_change_log_
[2].status
);
1040 EXPECT_EQ(registration
->active_version()->version_id(),
1041 update_helper
->state_change_log_
[3].version_id
);
1042 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
1043 update_helper
->state_change_log_
[3].status
);
1045 EXPECT_EQ(registration
->active_version()->version_id(),
1046 update_helper
->state_change_log_
[4].version_id
);
1047 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
1048 update_helper
->state_change_log_
[4].status
);
1050 EXPECT_TRUE(update_helper
->update_found_
);
1053 TEST_F(ServiceWorkerJobTest
, Update_NewestVersionChanged
) {
1054 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1055 RunRegisterJob(GURL("http://www.example.com/one/"),
1056 GURL("http://www.example.com/service_worker.js"));
1058 ServiceWorkerVersion
* active_version
= registration
->active_version();
1060 // Queue an Update, it should abort when it starts and sees the new version.
1061 job_coordinator()->Update(registration
.get(), false);
1063 // Add a waiting version with new script.
1064 scoped_refptr
<ServiceWorkerVersion
> version
=
1065 new ServiceWorkerVersion(registration
.get(),
1066 GURL("http://www.example.com/new_worker.js"),
1067 2L /* dummy version id */,
1068 helper_
->context()->AsWeakPtr());
1069 registration
->SetWaitingVersion(version
);
1071 base::RunLoop().RunUntilIdle();
1073 // Verify the registration was not modified by the Update.
1074 EXPECT_EQ(active_version
, registration
->active_version());
1075 EXPECT_EQ(version
.get(), registration
->waiting_version());
1076 EXPECT_EQ(NULL
, registration
->installing_version());
1079 // Test that update succeeds if the incumbent worker was evicted
1080 // during the update job (this can happen on disk cache failure).
1081 TEST_F(ServiceWorkerJobTest
, Update_EvictedIncumbent
) {
1082 EvictIncumbentVersionHelper
* update_helper
=
1083 new EvictIncumbentVersionHelper(render_process_id_
);
1084 helper_
.reset(update_helper
);
1085 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1086 update_helper
->SetupInitialRegistration(kNewVersionOrigin
);
1087 ASSERT_TRUE(registration
.get());
1088 update_helper
->state_change_log_
.clear();
1090 // Run the update job.
1091 registration
->AddListener(update_helper
);
1092 scoped_refptr
<ServiceWorkerVersion
> first_version
=
1093 registration
->active_version();
1094 first_version
->StartUpdate();
1095 base::RunLoop().RunUntilIdle();
1098 ASSERT_TRUE(registration
->active_version());
1099 EXPECT_NE(first_version
.get(), registration
->active_version());
1100 EXPECT_FALSE(registration
->installing_version());
1101 EXPECT_FALSE(registration
->waiting_version());
1102 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, first_version
->status());
1103 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
1104 registration
->active_version()->status());
1105 ASSERT_EQ(4u, update_helper
->attribute_change_log_
.size());
1106 EXPECT_TRUE(update_helper
->update_found_
);
1107 EXPECT_TRUE(update_helper
->registration_failed_
);
1108 EXPECT_FALSE(registration
->is_uninstalled());
1111 TEST_F(ServiceWorkerJobTest
, Update_UninstallingRegistration
) {
1113 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1114 RunRegisterJob(GURL("http://www.example.com/one/"),
1115 GURL("http://www.example.com/service_worker.js"));
1117 // Add a controllee and queue an unregister to force the uninstalling state.
1118 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1119 ServiceWorkerVersion
* active_version
= registration
->active_version();
1120 active_version
->AddControllee(host
.get());
1121 job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
1122 SaveUnregistration(SERVICE_WORKER_OK
, &called
));
1124 // Update should abort after it starts and sees uninstalling.
1125 job_coordinator()->Update(registration
.get(), false);
1127 EXPECT_FALSE(called
);
1128 base::RunLoop().RunUntilIdle();
1129 EXPECT_TRUE(called
);
1131 // Verify the registration was not modified by the Update.
1132 EXPECT_TRUE(registration
->is_uninstalling());
1133 EXPECT_EQ(active_version
, registration
->active_version());
1134 EXPECT_EQ(NULL
, registration
->waiting_version());
1135 EXPECT_EQ(NULL
, registration
->installing_version());
1138 TEST_F(ServiceWorkerJobTest
, RegisterWhileUninstalling
) {
1139 GURL
pattern("http://www.example.com/one/");
1140 GURL
script1("http://www.example.com/service_worker.js");
1141 GURL
script2("http://www.example.com/service_worker.js?new");
1143 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1144 RunRegisterJob(pattern
, script1
);
1146 // Add a controllee and queue an unregister to force the uninstalling state.
1147 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1148 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1149 registration
->active_version();
1150 old_version
->AddControllee(host
.get());
1151 RunUnregisterJob(pattern
);
1153 // Register another script.
1154 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1156 EXPECT_FALSE(registration
->is_uninstalling());
1157 EXPECT_EQ(old_version
, registration
->active_version());
1159 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1160 registration
->waiting_version();
1162 // Verify the new version is installed but not activated yet.
1163 EXPECT_EQ(NULL
, registration
->installing_version());
1164 EXPECT_TRUE(new_version
);
1165 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1166 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1168 old_version
->RemoveControllee(host
.get());
1169 base::RunLoop().RunUntilIdle();
1171 EXPECT_FALSE(registration
->is_uninstalling());
1172 EXPECT_FALSE(registration
->is_uninstalled());
1174 // Verify the new version is activated.
1175 EXPECT_EQ(NULL
, registration
->installing_version());
1176 EXPECT_EQ(NULL
, registration
->waiting_version());
1177 EXPECT_EQ(new_version
, registration
->active_version());
1178 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1179 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1182 TEST_F(ServiceWorkerJobTest
, RegisterAndUnregisterWhileUninstalling
) {
1183 GURL
pattern("http://www.example.com/one/");
1184 GURL
script1("http://www.example.com/service_worker.js");
1185 GURL
script2("http://www.example.com/service_worker.js?new");
1187 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1188 RunRegisterJob(pattern
, script1
);
1190 // Add a controllee and queue an unregister to force the uninstalling state.
1191 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1192 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1193 registration
->active_version();
1194 old_version
->AddControllee(host
.get());
1195 RunUnregisterJob(pattern
);
1197 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1199 EXPECT_EQ(registration
, FindRegistrationForPattern(pattern
));
1200 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1201 registration
->waiting_version();
1202 ASSERT_TRUE(new_version
);
1204 // Unregister the registration (but it's still live).
1205 RunUnregisterJob(pattern
);
1206 // Now it's not found in the storage.
1207 RunUnregisterJob(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1209 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1210 EXPECT_TRUE(registration
->is_uninstalling());
1211 EXPECT_EQ(old_version
, registration
->active_version());
1213 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, old_version
->running_status());
1214 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, old_version
->status());
1215 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1216 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1218 old_version
->RemoveControllee(host
.get());
1219 base::RunLoop().RunUntilIdle();
1221 EXPECT_FALSE(registration
->is_uninstalling());
1222 EXPECT_TRUE(registration
->is_uninstalled());
1224 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1225 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1226 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, new_version
->running_status());
1227 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, new_version
->status());
1230 TEST_F(ServiceWorkerJobTest
, RegisterSameScriptMultipleTimesWhileUninstalling
) {
1231 GURL
pattern("http://www.example.com/one/");
1232 GURL
script1("http://www.example.com/service_worker.js");
1233 GURL
script2("http://www.example.com/service_worker.js?new");
1235 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1236 RunRegisterJob(pattern
, script1
);
1238 // Add a controllee and queue an unregister to force the uninstalling state.
1239 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1240 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1241 registration
->active_version();
1242 old_version
->AddControllee(host
.get());
1243 RunUnregisterJob(pattern
);
1245 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1247 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1248 registration
->waiting_version();
1249 ASSERT_TRUE(new_version
);
1251 RunUnregisterJob(pattern
);
1253 EXPECT_TRUE(registration
->is_uninstalling());
1255 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1257 EXPECT_FALSE(registration
->is_uninstalling());
1258 EXPECT_EQ(new_version
, registration
->waiting_version());
1260 old_version
->RemoveControllee(host
.get());
1261 base::RunLoop().RunUntilIdle();
1263 EXPECT_FALSE(registration
->is_uninstalling());
1264 EXPECT_FALSE(registration
->is_uninstalled());
1266 // Verify the new version is activated.
1267 EXPECT_EQ(NULL
, registration
->installing_version());
1268 EXPECT_EQ(NULL
, registration
->waiting_version());
1269 EXPECT_EQ(new_version
, registration
->active_version());
1270 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1271 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1274 TEST_F(ServiceWorkerJobTest
, RegisterMultipleTimesWhileUninstalling
) {
1275 GURL
pattern("http://www.example.com/one/");
1276 GURL
script1("http://www.example.com/service_worker.js?first");
1277 GURL
script2("http://www.example.com/service_worker.js?second");
1278 GURL
script3("http://www.example.com/service_worker.js?third");
1280 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1281 RunRegisterJob(pattern
, script1
);
1283 // Add a controllee and queue an unregister to force the uninstalling state.
1284 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1285 scoped_refptr
<ServiceWorkerVersion
> first_version
=
1286 registration
->active_version();
1287 first_version
->AddControllee(host
.get());
1288 RunUnregisterJob(pattern
);
1290 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1292 scoped_refptr
<ServiceWorkerVersion
> second_version
=
1293 registration
->waiting_version();
1294 ASSERT_TRUE(second_version
);
1296 RunUnregisterJob(pattern
);
1298 EXPECT_TRUE(registration
->is_uninstalling());
1300 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script3
));
1302 scoped_refptr
<ServiceWorkerVersion
> third_version
=
1303 registration
->waiting_version();
1304 ASSERT_TRUE(third_version
);
1306 EXPECT_FALSE(registration
->is_uninstalling());
1307 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, second_version
->status());
1309 first_version
->RemoveControllee(host
.get());
1310 base::RunLoop().RunUntilIdle();
1312 EXPECT_FALSE(registration
->is_uninstalling());
1313 EXPECT_FALSE(registration
->is_uninstalled());
1315 // Verify the new version is activated.
1316 EXPECT_EQ(NULL
, registration
->installing_version());
1317 EXPECT_EQ(NULL
, registration
->waiting_version());
1318 EXPECT_EQ(third_version
, registration
->active_version());
1319 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, third_version
->running_status());
1320 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, third_version
->status());
1323 class EventCallbackHelper
: public EmbeddedWorkerTestHelper
{
1325 explicit EventCallbackHelper(int mock_render_process_id
)
1326 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
),
1327 install_event_result_(blink::WebServiceWorkerEventResultCompleted
),
1328 activate_event_result_(blink::WebServiceWorkerEventResultCompleted
) {}
1330 void OnInstallEvent(int embedded_worker_id
,
1331 int request_id
) override
{
1332 if (!install_callback_
.is_null())
1333 install_callback_
.Run();
1335 new ServiceWorkerHostMsg_InstallEventFinished(
1336 embedded_worker_id
, request_id
, install_event_result_
));
1338 void OnActivateEvent(int embedded_worker_id
, int request_id
) override
{
1340 new ServiceWorkerHostMsg_ActivateEventFinished(
1341 embedded_worker_id
, request_id
, activate_event_result_
));
1344 void set_install_callback(const base::Closure
& callback
) {
1345 install_callback_
= callback
;
1347 void set_install_event_result(blink::WebServiceWorkerEventResult result
) {
1348 install_event_result_
= result
;
1350 void set_activate_event_result(blink::WebServiceWorkerEventResult result
) {
1351 activate_event_result_
= result
;
1354 base::Closure install_callback_
;
1355 blink::WebServiceWorkerEventResult install_event_result_
;
1356 blink::WebServiceWorkerEventResult activate_event_result_
;
1359 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringInstall
) {
1360 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1361 helper_
.reset(helper
);
1363 GURL
pattern("http://www.example.com/one/");
1364 GURL
script1("http://www.example.com/service_worker.js");
1365 GURL
script2("http://www.example.com/service_worker.js?new");
1367 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1368 RunRegisterJob(pattern
, script1
);
1370 // Add a controllee and queue an unregister to force the uninstalling state.
1371 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1372 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1373 registration
->active_version();
1374 old_version
->AddControllee(host
.get());
1375 RunUnregisterJob(pattern
);
1377 // Register another script. While installing, old_version loses controllee.
1378 helper
->set_install_callback(
1379 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1380 old_version
, host
.get()));
1381 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1383 EXPECT_FALSE(registration
->is_uninstalling());
1384 EXPECT_FALSE(registration
->is_uninstalled());
1386 // Verify the new version is activated.
1387 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1388 registration
->active_version();
1389 EXPECT_NE(old_version
, new_version
);
1390 EXPECT_EQ(NULL
, registration
->installing_version());
1391 EXPECT_EQ(NULL
, registration
->waiting_version());
1392 EXPECT_EQ(new_version
, registration
->active_version());
1393 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1394 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1396 EXPECT_EQ(registration
, FindRegistrationForPattern(pattern
));
1399 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringRejectedInstall
) {
1400 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1401 helper_
.reset(helper
);
1403 GURL
pattern("http://www.example.com/one/");
1404 GURL
script1("http://www.example.com/service_worker.js");
1405 GURL
script2("http://www.example.com/service_worker.js?new");
1407 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1408 RunRegisterJob(pattern
, script1
);
1410 // Add a controllee and queue an unregister to force the uninstalling state.
1411 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1412 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1413 registration
->active_version();
1414 old_version
->AddControllee(host
.get());
1415 RunUnregisterJob(pattern
);
1417 // Register another script that fails to install. While installing,
1418 // old_version loses controllee.
1419 helper
->set_install_callback(
1420 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1421 old_version
, host
.get()));
1422 helper
->set_install_event_result(blink::WebServiceWorkerEventResultRejected
);
1423 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1425 // Verify the registration was uninstalled.
1426 EXPECT_FALSE(registration
->is_uninstalling());
1427 EXPECT_TRUE(registration
->is_uninstalled());
1429 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1430 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1432 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1435 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringInstall_RejectActivate
) {
1436 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1437 helper_
.reset(helper
);
1439 GURL
pattern("http://www.example.com/one/");
1440 GURL
script1("http://www.example.com/service_worker.js");
1441 GURL
script2("http://www.example.com/service_worker.js?new");
1443 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1444 RunRegisterJob(pattern
, script1
);
1446 // Add a controllee and queue an unregister to force the uninstalling state.
1447 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1448 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1449 registration
->active_version();
1450 old_version
->AddControllee(host
.get());
1451 RunUnregisterJob(pattern
);
1453 // Register another script that fails to activate. While installing,
1454 // old_version loses controllee.
1455 helper
->set_install_callback(
1456 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1457 old_version
, host
.get()));
1458 helper
->set_activate_event_result(blink::WebServiceWorkerEventResultRejected
);
1459 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1461 // Verify the registration remains.
1462 EXPECT_FALSE(registration
->is_uninstalling());
1463 EXPECT_FALSE(registration
->is_uninstalled());
1465 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1466 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1468 FindRegistrationForPattern(pattern
, SERVICE_WORKER_OK
);
1471 } // namespace content