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
) override
{
366 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
367 registry()->OnWorkerStopped(worker
->process_id(), embedded_worker_id
);
371 TEST_F(ServiceWorkerJobTest
, Register_FailToStartWorker
) {
372 helper_
.reset(new FailToStartWorkerTestHelper(render_process_id_
));
374 scoped_refptr
<ServiceWorkerRegistration
> registration
=
375 RunRegisterJob(GURL("http://www.example.com/"),
376 GURL("http://www.example.com/service_worker.js"),
377 SERVICE_WORKER_ERROR_START_WORKER_FAILED
);
379 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(NULL
), registration
);
382 // Register and then unregister the pattern, in parallel. Job coordinator should
383 // process jobs until the last job.
384 TEST_F(ServiceWorkerJobTest
, ParallelRegUnreg
) {
385 GURL
pattern("http://www.example.com/");
386 GURL
script_url("http://www.example.com/service_worker.js");
388 bool registration_called
= false;
389 scoped_refptr
<ServiceWorkerRegistration
> registration
;
390 job_coordinator()->Register(
394 SaveRegistration(SERVICE_WORKER_OK
, ®istration_called
, ®istration
));
396 bool unregistration_called
= false;
397 job_coordinator()->Unregister(
399 SaveUnregistration(SERVICE_WORKER_OK
, &unregistration_called
));
401 ASSERT_FALSE(registration_called
);
402 ASSERT_FALSE(unregistration_called
);
403 base::RunLoop().RunUntilIdle();
404 ASSERT_TRUE(registration_called
);
405 ASSERT_TRUE(unregistration_called
);
407 registration
= FindRegistrationForPattern(pattern
,
408 SERVICE_WORKER_ERROR_NOT_FOUND
);
410 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
413 // Register conflicting scripts for the same pattern. The most recent
414 // registration should win, and the old registration should have been
416 TEST_F(ServiceWorkerJobTest
, ParallelRegNewScript
) {
417 GURL
pattern("http://www.example.com/");
419 GURL
script_url1("http://www.example.com/service_worker1.js");
420 bool registration1_called
= false;
421 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
422 job_coordinator()->Register(
427 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
429 GURL
script_url2("http://www.example.com/service_worker2.js");
430 bool registration2_called
= false;
431 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
432 job_coordinator()->Register(
437 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
439 ASSERT_FALSE(registration1_called
);
440 ASSERT_FALSE(registration2_called
);
441 base::RunLoop().RunUntilIdle();
442 ASSERT_TRUE(registration1_called
);
443 ASSERT_TRUE(registration2_called
);
445 scoped_refptr
<ServiceWorkerRegistration
> registration
=
446 FindRegistrationForPattern(pattern
);
448 ASSERT_EQ(registration2
, registration
);
451 // Register the exact same pattern + script. Requests should be
452 // coalesced such that both callers get the exact same registration
454 TEST_F(ServiceWorkerJobTest
, ParallelRegSameScript
) {
455 GURL
pattern("http://www.example.com/");
457 GURL
script_url("http://www.example.com/service_worker1.js");
458 bool registration1_called
= false;
459 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
460 job_coordinator()->Register(
465 SERVICE_WORKER_OK
, ®istration1_called
, ®istration1
));
467 bool registration2_called
= false;
468 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
469 job_coordinator()->Register(
474 SERVICE_WORKER_OK
, ®istration2_called
, ®istration2
));
476 ASSERT_FALSE(registration1_called
);
477 ASSERT_FALSE(registration2_called
);
478 base::RunLoop().RunUntilIdle();
479 ASSERT_TRUE(registration1_called
);
480 ASSERT_TRUE(registration2_called
);
482 ASSERT_EQ(registration1
, registration2
);
484 scoped_refptr
<ServiceWorkerRegistration
> registration
=
485 FindRegistrationForPattern(pattern
);
487 ASSERT_EQ(registration
, registration1
);
490 // Call simulataneous unregister calls.
491 TEST_F(ServiceWorkerJobTest
, ParallelUnreg
) {
492 GURL
pattern("http://www.example.com/");
494 GURL
script_url("http://www.example.com/service_worker.js");
495 bool unregistration1_called
= false;
496 job_coordinator()->Unregister(
498 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
499 &unregistration1_called
));
501 bool unregistration2_called
= false;
502 job_coordinator()->Unregister(
504 SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND
,
505 &unregistration2_called
));
507 ASSERT_FALSE(unregistration1_called
);
508 ASSERT_FALSE(unregistration2_called
);
509 base::RunLoop().RunUntilIdle();
510 ASSERT_TRUE(unregistration1_called
);
511 ASSERT_TRUE(unregistration2_called
);
513 // There isn't really a way to test that they are being coalesced,
514 // but we can make sure they can exist simultaneously without
516 scoped_refptr
<ServiceWorkerRegistration
> registration
=
517 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
519 ASSERT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
522 TEST_F(ServiceWorkerJobTest
, AbortAll_Register
) {
523 GURL
pattern1("http://www1.example.com/");
524 GURL
pattern2("http://www2.example.com/");
525 GURL
script_url1("http://www1.example.com/service_worker.js");
526 GURL
script_url2("http://www2.example.com/service_worker.js");
528 bool registration_called1
= false;
529 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
530 job_coordinator()->Register(
534 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
535 ®istration_called1
, ®istration1
));
537 bool registration_called2
= false;
538 scoped_refptr
<ServiceWorkerRegistration
> registration2
;
539 job_coordinator()->Register(
543 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
544 ®istration_called2
, ®istration2
));
546 ASSERT_FALSE(registration_called1
);
547 ASSERT_FALSE(registration_called2
);
548 job_coordinator()->AbortAll();
550 base::RunLoop().RunUntilIdle();
551 ASSERT_TRUE(registration_called1
);
552 ASSERT_TRUE(registration_called2
);
554 bool find_called1
= false;
555 storage()->FindRegistrationForPattern(
557 SaveFoundRegistration(
558 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called1
, ®istration1
));
560 bool find_called2
= false;
561 storage()->FindRegistrationForPattern(
563 SaveFoundRegistration(
564 SERVICE_WORKER_ERROR_NOT_FOUND
, &find_called2
, ®istration2
));
566 base::RunLoop().RunUntilIdle();
567 ASSERT_TRUE(find_called1
);
568 ASSERT_TRUE(find_called2
);
569 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration1
);
570 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration2
);
573 TEST_F(ServiceWorkerJobTest
, AbortAll_Unregister
) {
574 GURL
pattern1("http://www1.example.com/");
575 GURL
pattern2("http://www2.example.com/");
577 bool unregistration_called1
= false;
578 scoped_refptr
<ServiceWorkerRegistration
> registration1
;
579 job_coordinator()->Unregister(
581 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
582 &unregistration_called1
));
584 bool unregistration_called2
= false;
585 job_coordinator()->Unregister(
587 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
588 &unregistration_called2
));
590 ASSERT_FALSE(unregistration_called1
);
591 ASSERT_FALSE(unregistration_called2
);
592 job_coordinator()->AbortAll();
594 base::RunLoop().RunUntilIdle();
595 ASSERT_TRUE(unregistration_called1
);
596 ASSERT_TRUE(unregistration_called2
);
599 TEST_F(ServiceWorkerJobTest
, AbortAll_RegUnreg
) {
600 GURL
pattern("http://www.example.com/");
601 GURL
script_url("http://www.example.com/service_worker.js");
603 bool registration_called
= false;
604 scoped_refptr
<ServiceWorkerRegistration
> registration
;
605 job_coordinator()->Register(
609 SaveRegistration(SERVICE_WORKER_ERROR_ABORT
,
610 ®istration_called
, ®istration
));
612 bool unregistration_called
= false;
613 job_coordinator()->Unregister(
615 SaveUnregistration(SERVICE_WORKER_ERROR_ABORT
,
616 &unregistration_called
));
618 ASSERT_FALSE(registration_called
);
619 ASSERT_FALSE(unregistration_called
);
620 job_coordinator()->AbortAll();
622 base::RunLoop().RunUntilIdle();
623 ASSERT_TRUE(registration_called
);
624 ASSERT_TRUE(unregistration_called
);
626 registration
= FindRegistrationForPattern(pattern
,
627 SERVICE_WORKER_ERROR_NOT_FOUND
);
629 EXPECT_EQ(scoped_refptr
<ServiceWorkerRegistration
>(), registration
);
632 // Tests that the waiting worker enters the 'redundant' state upon
634 TEST_F(ServiceWorkerJobTest
, UnregisterWaitingSetsRedundant
) {
635 GURL
script_url("http://www.example.com/service_worker.js");
636 scoped_refptr
<ServiceWorkerRegistration
> registration
=
637 RunRegisterJob(GURL("http://www.example.com/"), script_url
);
638 ASSERT_TRUE(registration
.get());
640 // Manually create the waiting worker since there is no way to become a
641 // waiting worker until Update is implemented.
642 scoped_refptr
<ServiceWorkerVersion
> version
= new ServiceWorkerVersion(
643 registration
.get(), script_url
, 1L, helper_
->context()->AsWeakPtr());
644 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
645 version
->StartWorker(CreateReceiverOnCurrentThread(&status
));
646 base::RunLoop().RunUntilIdle();
647 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
649 version
->SetStatus(ServiceWorkerVersion::INSTALLED
);
650 registration
->SetWaitingVersion(version
);
651 EXPECT_EQ(ServiceWorkerVersion::RUNNING
,
652 version
->running_status());
653 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, version
->status());
655 RunUnregisterJob(GURL("http://www.example.com/"));
657 // The version should be stopped since there is no controllee after
659 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
660 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
663 // Tests that the active worker enters the 'redundant' state upon
665 TEST_F(ServiceWorkerJobTest
, UnregisterActiveSetsRedundant
) {
666 scoped_refptr
<ServiceWorkerRegistration
> registration
=
667 RunRegisterJob(GURL("http://www.example.com/"),
668 GURL("http://www.example.com/service_worker.js"));
669 ASSERT_TRUE(registration
.get());
671 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
672 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
673 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
675 RunUnregisterJob(GURL("http://www.example.com/"));
677 // The version should be stopped since there is no controllee after
679 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
680 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
683 // Tests that the active worker enters the 'redundant' state upon
685 TEST_F(ServiceWorkerJobTest
,
686 UnregisterActiveSetsRedundant_WaitForNoControllee
) {
687 scoped_refptr
<ServiceWorkerRegistration
> registration
=
688 RunRegisterJob(GURL("http://www.example.com/"),
689 GURL("http://www.example.com/service_worker.js"));
690 ASSERT_TRUE(registration
.get());
692 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
693 registration
->active_version()->AddControllee(host
.get());
695 scoped_refptr
<ServiceWorkerVersion
> version
= registration
->active_version();
696 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
697 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
699 RunUnregisterJob(GURL("http://www.example.com/"));
701 // The version should be running since there is still a controllee.
702 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, version
->running_status());
703 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, version
->status());
705 registration
->active_version()->RemoveControllee(host
.get());
706 base::RunLoop().RunUntilIdle();
708 // The version should be stopped since there is no controllee.
709 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, version
->running_status());
710 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version
->status());
713 namespace { // Helpers for the update job tests.
715 const GURL
kNoChangeOrigin("http://nochange/");
716 const GURL
kNewVersionOrigin("http://newversion/");
717 const std::string
kScope("scope/");
718 const std::string
kScript("script.js");
720 void RunNestedUntilIdle() {
721 base::MessageLoop::ScopedNestableTaskAllower
allow(
722 base::MessageLoop::current());
723 base::MessageLoop::current()->RunUntilIdle();
726 void OnIOComplete(int* rv_out
, int rv
) {
731 ServiceWorkerStorage
* storage
, int64 id
,
732 const std::string
& headers
,
733 IOBuffer
* body
, int length
) {
734 scoped_ptr
<ServiceWorkerResponseWriter
> writer
=
735 storage
->CreateResponseWriter(id
);
737 scoped_ptr
<net::HttpResponseInfo
> info(new net::HttpResponseInfo
);
738 info
->request_time
= base::Time::Now();
739 info
->response_time
= base::Time::Now();
740 info
->was_cached
= false;
741 info
->headers
= new net::HttpResponseHeaders(headers
);
742 scoped_refptr
<HttpResponseInfoIOBuffer
> info_buffer
=
743 new HttpResponseInfoIOBuffer(info
.release());
746 writer
->WriteInfo(info_buffer
.get(), base::Bind(&OnIOComplete
, &rv
));
747 RunNestedUntilIdle();
751 writer
->WriteData(body
, length
,
752 base::Bind(&OnIOComplete
, &rv
));
753 RunNestedUntilIdle();
754 EXPECT_EQ(length
, rv
);
757 void WriteStringResponse(
758 ServiceWorkerStorage
* storage
, int64 id
,
759 const std::string
& body
) {
760 scoped_refptr
<IOBuffer
> body_buffer(new WrappedIOBuffer(body
.data()));
761 const char kHttpHeaders
[] = "HTTP/1.0 200 HONKYDORY\0\0";
762 std::string
headers(kHttpHeaders
, arraysize(kHttpHeaders
));
763 WriteResponse(storage
, id
, headers
, body_buffer
.get(), body
.length());
766 class UpdateJobTestHelper
767 : public EmbeddedWorkerTestHelper
,
768 public ServiceWorkerRegistration::Listener
,
769 public ServiceWorkerVersion::Listener
{
771 struct AttributeChangeLogEntry
{
772 int64 registration_id
;
773 ChangedVersionAttributesMask mask
;
774 ServiceWorkerRegistrationInfo info
;
777 struct StateChangeLogEntry
{
779 ServiceWorkerVersion::Status status
;
782 UpdateJobTestHelper(int mock_render_process_id
)
783 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
),
784 update_found_(false) {}
785 ~UpdateJobTestHelper() override
{
786 if (registration_
.get())
787 registration_
->RemoveListener(this);
790 ServiceWorkerStorage
* storage() { return context()->storage(); }
791 ServiceWorkerJobCoordinator
* job_coordinator() {
792 return context()->job_coordinator();
795 scoped_refptr
<ServiceWorkerRegistration
> SetupInitialRegistration(
796 const GURL
& test_origin
) {
797 scoped_refptr
<ServiceWorkerRegistration
> registration
;
799 job_coordinator()->Register(
800 test_origin
.Resolve(kScope
),
801 test_origin
.Resolve(kScript
),
803 SaveRegistration(SERVICE_WORKER_OK
, &called
, ®istration
));
804 base::RunLoop().RunUntilIdle();
806 EXPECT_TRUE(registration
.get());
807 EXPECT_TRUE(registration
->active_version());
808 EXPECT_FALSE(registration
->installing_version());
809 EXPECT_FALSE(registration
->waiting_version());
810 registration_
= registration
;
814 // EmbeddedWorkerTestHelper overrides
815 void OnStartWorker(int embedded_worker_id
,
818 const GURL
& script
) override
{
819 const std::string kMockScriptBody
= "mock_script";
820 const uint64 kMockScriptSize
= 19284;
821 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
822 ServiceWorkerRegistration
* registration
=
823 context()->GetLiveRegistration(version
->registration_id());
824 bool is_update
= registration
->active_version() &&
825 version
!= registration
->active_version();
827 ASSERT_TRUE(version
);
828 version
->AddListener(this);
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 if (script
.GetOrigin() == kNoChangeOrigin
) {
839 version
->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS
);
840 EmbeddedWorkerTestHelper::OnStopWorker(embedded_worker_id
);
844 // Spoof caching the script for the new version.
845 int64 resource_id
= storage()->NewResourceId();
846 version
->script_cache_map()->NotifyStartedCaching(script
, resource_id
);
847 WriteStringResponse(storage(), resource_id
, "mock_different_script");
848 version
->script_cache_map()->NotifyFinishedCaching(
849 script
, kMockScriptSize
, net::URLRequestStatus(), std::string());
851 EmbeddedWorkerTestHelper::OnStartWorker(embedded_worker_id
, version_id
,
855 // ServiceWorkerRegistration::Listener overrides
856 void OnVersionAttributesChanged(
857 ServiceWorkerRegistration
* registration
,
858 ChangedVersionAttributesMask changed_mask
,
859 const ServiceWorkerRegistrationInfo
& info
) override
{
860 AttributeChangeLogEntry entry
;
861 entry
.registration_id
= registration
->id();
862 entry
.mask
= changed_mask
;
864 attribute_change_log_
.push_back(entry
);
867 void OnRegistrationFailed(ServiceWorkerRegistration
* registration
) override
{
871 void OnUpdateFound(ServiceWorkerRegistration
* registration
) override
{
872 ASSERT_FALSE(update_found_
);
873 update_found_
= true;
876 // ServiceWorkerVersion::Listener overrides
877 void OnVersionStateChanged(ServiceWorkerVersion
* version
) override
{
878 StateChangeLogEntry entry
;
879 entry
.version_id
= version
->version_id();
880 entry
.status
= version
->status();
881 state_change_log_
.push_back(entry
);
884 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
886 std::vector
<AttributeChangeLogEntry
> attribute_change_log_
;
887 std::vector
<StateChangeLogEntry
> state_change_log_
;
891 // Helper class for update tests that evicts the active version when the update
892 // worker is about to be started.
893 class EvictIncumbentVersionHelper
: public UpdateJobTestHelper
{
895 EvictIncumbentVersionHelper(int mock_render_process_id
)
896 : UpdateJobTestHelper(mock_render_process_id
) {}
897 ~EvictIncumbentVersionHelper() override
{}
899 void OnStartWorker(int embedded_worker_id
,
902 const GURL
& script
) override
{
903 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
904 ServiceWorkerRegistration
* registration
=
905 context()->GetLiveRegistration(version
->registration_id());
906 bool is_update
= registration
->active_version() &&
907 version
!= registration
->active_version();
909 // Evict the incumbent worker.
910 ASSERT_FALSE(registration
->waiting_version());
911 registration
->DeleteVersion(
912 make_scoped_refptr(registration
->active_version()));
914 UpdateJobTestHelper::OnStartWorker(embedded_worker_id
, version_id
, scope
,
918 void OnRegistrationFailed(ServiceWorkerRegistration
* registration
) override
{
919 registration_failed_
= true;
922 bool registration_failed_
= false;
927 TEST_F(ServiceWorkerJobTest
, Update_NoChange
) {
928 UpdateJobTestHelper
* update_helper
=
929 new UpdateJobTestHelper(render_process_id_
);
930 helper_
.reset(update_helper
);
931 scoped_refptr
<ServiceWorkerRegistration
> registration
=
932 update_helper
->SetupInitialRegistration(kNoChangeOrigin
);
933 ASSERT_TRUE(registration
.get());
934 ASSERT_EQ(4u, update_helper
->state_change_log_
.size());
935 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
936 update_helper
->state_change_log_
[0].status
);
937 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
938 update_helper
->state_change_log_
[1].status
);
939 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
940 update_helper
->state_change_log_
[2].status
);
941 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
942 update_helper
->state_change_log_
[3].status
);
943 update_helper
->state_change_log_
.clear();
945 // Run the update job.
946 registration
->AddListener(update_helper
);
947 scoped_refptr
<ServiceWorkerVersion
> first_version
=
948 registration
->active_version();
949 first_version
->StartUpdate();
950 base::RunLoop().RunUntilIdle();
953 ASSERT_TRUE(registration
->active_version());
954 EXPECT_EQ(first_version
.get(), registration
->active_version());
955 EXPECT_FALSE(registration
->installing_version());
956 EXPECT_FALSE(registration
->waiting_version());
957 EXPECT_TRUE(update_helper
->attribute_change_log_
.empty());
958 ASSERT_EQ(1u, update_helper
->state_change_log_
.size());
959 EXPECT_NE(registration
->active_version()->version_id(),
960 update_helper
->state_change_log_
[0].version_id
);
961 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
962 update_helper
->state_change_log_
[0].status
);
963 EXPECT_FALSE(update_helper
->update_found_
);
966 TEST_F(ServiceWorkerJobTest
, Update_BumpLastUpdateCheckTime
) {
967 const base::Time kToday
= base::Time::Now();
968 const base::Time kYesterday
=
969 kToday
- base::TimeDelta::FromDays(1) - base::TimeDelta::FromHours(1);
970 UpdateJobTestHelper
* update_helper
=
971 new UpdateJobTestHelper(render_process_id_
);
972 helper_
.reset(update_helper
);
973 scoped_refptr
<ServiceWorkerRegistration
> registration
=
974 update_helper
->SetupInitialRegistration(kNoChangeOrigin
);
976 // Run an update where the last update check was less than 24 hours ago. The
977 // check time shouldn't change, as we didn't bypass cache.
978 registration
->set_last_update_check(kToday
);
979 registration
->active_version()->StartUpdate();
980 base::RunLoop().RunUntilIdle();
981 EXPECT_EQ(kToday
, registration
->last_update_check());
983 // Run an update where the last update check was over 24 hours ago. The
984 // check time should change, as the cache was bypassed.
985 registration
->set_last_update_check(kYesterday
);
986 registration
->active_version()->StartUpdate();
987 base::RunLoop().RunUntilIdle();
988 EXPECT_LT(kYesterday
, registration
->last_update_check());
991 TEST_F(ServiceWorkerJobTest
, Update_NewVersion
) {
992 UpdateJobTestHelper
* update_helper
=
993 new UpdateJobTestHelper(render_process_id_
);
994 helper_
.reset(update_helper
);
995 scoped_refptr
<ServiceWorkerRegistration
> registration
=
996 update_helper
->SetupInitialRegistration(kNewVersionOrigin
);
997 ASSERT_TRUE(registration
.get());
998 update_helper
->state_change_log_
.clear();
1000 // Run the update job.
1001 registration
->AddListener(update_helper
);
1002 scoped_refptr
<ServiceWorkerVersion
> first_version
=
1003 registration
->active_version();
1004 first_version
->StartUpdate();
1005 base::RunLoop().RunUntilIdle();
1008 ASSERT_TRUE(registration
->active_version());
1009 EXPECT_NE(first_version
.get(), registration
->active_version());
1010 EXPECT_FALSE(registration
->installing_version());
1011 EXPECT_FALSE(registration
->waiting_version());
1012 ASSERT_EQ(3u, update_helper
->attribute_change_log_
.size());
1014 UpdateJobTestHelper::AttributeChangeLogEntry entry
;
1015 entry
= update_helper
->attribute_change_log_
[0];
1016 EXPECT_TRUE(entry
.mask
.installing_changed());
1017 EXPECT_FALSE(entry
.mask
.waiting_changed());
1018 EXPECT_FALSE(entry
.mask
.active_changed());
1019 EXPECT_NE(entry
.info
.installing_version
.version_id
,
1020 kInvalidServiceWorkerVersionId
);
1021 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
1022 kInvalidServiceWorkerVersionId
);
1023 EXPECT_NE(entry
.info
.active_version
.version_id
,
1024 kInvalidServiceWorkerVersionId
);
1026 entry
= update_helper
->attribute_change_log_
[1];
1027 EXPECT_TRUE(entry
.mask
.installing_changed());
1028 EXPECT_TRUE(entry
.mask
.waiting_changed());
1029 EXPECT_FALSE(entry
.mask
.active_changed());
1030 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
1031 kInvalidServiceWorkerVersionId
);
1032 EXPECT_NE(entry
.info
.waiting_version
.version_id
,
1033 kInvalidServiceWorkerVersionId
);
1034 EXPECT_NE(entry
.info
.active_version
.version_id
,
1035 kInvalidServiceWorkerVersionId
);
1037 entry
= update_helper
->attribute_change_log_
[2];
1038 EXPECT_FALSE(entry
.mask
.installing_changed());
1039 EXPECT_TRUE(entry
.mask
.waiting_changed());
1040 EXPECT_TRUE(entry
.mask
.active_changed());
1041 EXPECT_EQ(entry
.info
.installing_version
.version_id
,
1042 kInvalidServiceWorkerVersionId
);
1043 EXPECT_EQ(entry
.info
.waiting_version
.version_id
,
1044 kInvalidServiceWorkerVersionId
);
1045 EXPECT_NE(entry
.info
.active_version
.version_id
,
1046 kInvalidServiceWorkerVersionId
);
1048 // expected version state transitions:
1049 // new.installing, new.installed,
1051 // new.activating, new.activated
1052 ASSERT_EQ(5u, update_helper
->state_change_log_
.size());
1054 EXPECT_EQ(registration
->active_version()->version_id(),
1055 update_helper
->state_change_log_
[0].version_id
);
1056 EXPECT_EQ(ServiceWorkerVersion::INSTALLING
,
1057 update_helper
->state_change_log_
[0].status
);
1059 EXPECT_EQ(registration
->active_version()->version_id(),
1060 update_helper
->state_change_log_
[1].version_id
);
1061 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
,
1062 update_helper
->state_change_log_
[1].status
);
1064 EXPECT_EQ(first_version
->version_id(),
1065 update_helper
->state_change_log_
[2].version_id
);
1066 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
,
1067 update_helper
->state_change_log_
[2].status
);
1069 EXPECT_EQ(registration
->active_version()->version_id(),
1070 update_helper
->state_change_log_
[3].version_id
);
1071 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING
,
1072 update_helper
->state_change_log_
[3].status
);
1074 EXPECT_EQ(registration
->active_version()->version_id(),
1075 update_helper
->state_change_log_
[4].version_id
);
1076 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
1077 update_helper
->state_change_log_
[4].status
);
1079 EXPECT_TRUE(update_helper
->update_found_
);
1082 TEST_F(ServiceWorkerJobTest
, Update_NewestVersionChanged
) {
1083 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1084 RunRegisterJob(GURL("http://www.example.com/one/"),
1085 GURL("http://www.example.com/service_worker.js"));
1087 ServiceWorkerVersion
* active_version
= registration
->active_version();
1089 // Queue an Update, it should abort when it starts and sees the new version.
1090 job_coordinator()->Update(registration
.get(), false);
1092 // Add a waiting version with new script.
1093 scoped_refptr
<ServiceWorkerVersion
> version
=
1094 new ServiceWorkerVersion(registration
.get(),
1095 GURL("http://www.example.com/new_worker.js"),
1096 2L /* dummy version id */,
1097 helper_
->context()->AsWeakPtr());
1098 registration
->SetWaitingVersion(version
);
1100 base::RunLoop().RunUntilIdle();
1102 // Verify the registration was not modified by the Update.
1103 EXPECT_EQ(active_version
, registration
->active_version());
1104 EXPECT_EQ(version
.get(), registration
->waiting_version());
1105 EXPECT_EQ(NULL
, registration
->installing_version());
1108 // Test that update succeeds if the incumbent worker was evicted
1109 // during the update job (this can happen on disk cache failure).
1110 TEST_F(ServiceWorkerJobTest
, Update_EvictedIncumbent
) {
1111 EvictIncumbentVersionHelper
* update_helper
=
1112 new EvictIncumbentVersionHelper(render_process_id_
);
1113 helper_
.reset(update_helper
);
1114 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1115 update_helper
->SetupInitialRegistration(kNewVersionOrigin
);
1116 ASSERT_TRUE(registration
.get());
1117 update_helper
->state_change_log_
.clear();
1119 // Run the update job.
1120 registration
->AddListener(update_helper
);
1121 scoped_refptr
<ServiceWorkerVersion
> first_version
=
1122 registration
->active_version();
1123 first_version
->StartUpdate();
1124 base::RunLoop().RunUntilIdle();
1127 ASSERT_TRUE(registration
->active_version());
1128 EXPECT_NE(first_version
.get(), registration
->active_version());
1129 EXPECT_FALSE(registration
->installing_version());
1130 EXPECT_FALSE(registration
->waiting_version());
1131 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, first_version
->status());
1132 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
,
1133 registration
->active_version()->status());
1134 ASSERT_EQ(4u, update_helper
->attribute_change_log_
.size());
1135 EXPECT_TRUE(update_helper
->update_found_
);
1136 EXPECT_TRUE(update_helper
->registration_failed_
);
1137 EXPECT_FALSE(registration
->is_uninstalled());
1140 TEST_F(ServiceWorkerJobTest
, Update_UninstallingRegistration
) {
1142 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1143 RunRegisterJob(GURL("http://www.example.com/one/"),
1144 GURL("http://www.example.com/service_worker.js"));
1146 // Add a controllee and queue an unregister to force the uninstalling state.
1147 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1148 ServiceWorkerVersion
* active_version
= registration
->active_version();
1149 active_version
->AddControllee(host
.get());
1150 job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
1151 SaveUnregistration(SERVICE_WORKER_OK
, &called
));
1153 // Update should abort after it starts and sees uninstalling.
1154 job_coordinator()->Update(registration
.get(), false);
1156 EXPECT_FALSE(called
);
1157 base::RunLoop().RunUntilIdle();
1158 EXPECT_TRUE(called
);
1160 // Verify the registration was not modified by the Update.
1161 EXPECT_TRUE(registration
->is_uninstalling());
1162 EXPECT_EQ(active_version
, registration
->active_version());
1163 EXPECT_EQ(NULL
, registration
->waiting_version());
1164 EXPECT_EQ(NULL
, registration
->installing_version());
1167 TEST_F(ServiceWorkerJobTest
, RegisterWhileUninstalling
) {
1168 GURL
pattern("http://www.example.com/one/");
1169 GURL
script1("http://www.example.com/service_worker.js");
1170 GURL
script2("http://www.example.com/service_worker.js?new");
1172 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1173 RunRegisterJob(pattern
, script1
);
1175 // Add a controllee and queue an unregister to force the uninstalling state.
1176 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1177 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1178 registration
->active_version();
1179 old_version
->AddControllee(host
.get());
1180 RunUnregisterJob(pattern
);
1182 // Register another script.
1183 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1185 EXPECT_FALSE(registration
->is_uninstalling());
1186 EXPECT_EQ(old_version
, registration
->active_version());
1188 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1189 registration
->waiting_version();
1191 // Verify the new version is installed but not activated yet.
1192 EXPECT_EQ(NULL
, registration
->installing_version());
1193 EXPECT_TRUE(new_version
);
1194 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1195 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1197 old_version
->RemoveControllee(host
.get());
1198 base::RunLoop().RunUntilIdle();
1200 EXPECT_FALSE(registration
->is_uninstalling());
1201 EXPECT_FALSE(registration
->is_uninstalled());
1203 // Verify the new version is activated.
1204 EXPECT_EQ(NULL
, registration
->installing_version());
1205 EXPECT_EQ(NULL
, registration
->waiting_version());
1206 EXPECT_EQ(new_version
, registration
->active_version());
1207 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1208 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1211 TEST_F(ServiceWorkerJobTest
, RegisterAndUnregisterWhileUninstalling
) {
1212 GURL
pattern("http://www.example.com/one/");
1213 GURL
script1("http://www.example.com/service_worker.js");
1214 GURL
script2("http://www.example.com/service_worker.js?new");
1216 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1217 RunRegisterJob(pattern
, script1
);
1219 // Add a controllee and queue an unregister to force the uninstalling state.
1220 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1221 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1222 registration
->active_version();
1223 old_version
->AddControllee(host
.get());
1224 RunUnregisterJob(pattern
);
1226 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1228 EXPECT_EQ(registration
, FindRegistrationForPattern(pattern
));
1229 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1230 registration
->waiting_version();
1231 ASSERT_TRUE(new_version
);
1233 // Unregister the registration (but it's still live).
1234 RunUnregisterJob(pattern
);
1235 // Now it's not found in the storage.
1236 RunUnregisterJob(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1238 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1239 EXPECT_TRUE(registration
->is_uninstalling());
1240 EXPECT_EQ(old_version
, registration
->active_version());
1242 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, old_version
->running_status());
1243 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, old_version
->status());
1244 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1245 EXPECT_EQ(ServiceWorkerVersion::INSTALLED
, new_version
->status());
1247 old_version
->RemoveControllee(host
.get());
1248 base::RunLoop().RunUntilIdle();
1250 EXPECT_FALSE(registration
->is_uninstalling());
1251 EXPECT_TRUE(registration
->is_uninstalled());
1253 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1254 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1255 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, new_version
->running_status());
1256 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, new_version
->status());
1259 TEST_F(ServiceWorkerJobTest
, RegisterSameScriptMultipleTimesWhileUninstalling
) {
1260 GURL
pattern("http://www.example.com/one/");
1261 GURL
script1("http://www.example.com/service_worker.js");
1262 GURL
script2("http://www.example.com/service_worker.js?new");
1264 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1265 RunRegisterJob(pattern
, script1
);
1267 // Add a controllee and queue an unregister to force the uninstalling state.
1268 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1269 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1270 registration
->active_version();
1271 old_version
->AddControllee(host
.get());
1272 RunUnregisterJob(pattern
);
1274 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1276 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1277 registration
->waiting_version();
1278 ASSERT_TRUE(new_version
);
1280 RunUnregisterJob(pattern
);
1282 EXPECT_TRUE(registration
->is_uninstalling());
1284 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1286 EXPECT_FALSE(registration
->is_uninstalling());
1287 EXPECT_EQ(new_version
, registration
->waiting_version());
1289 old_version
->RemoveControllee(host
.get());
1290 base::RunLoop().RunUntilIdle();
1292 EXPECT_FALSE(registration
->is_uninstalling());
1293 EXPECT_FALSE(registration
->is_uninstalled());
1295 // Verify the new version is activated.
1296 EXPECT_EQ(NULL
, registration
->installing_version());
1297 EXPECT_EQ(NULL
, registration
->waiting_version());
1298 EXPECT_EQ(new_version
, registration
->active_version());
1299 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1300 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1303 TEST_F(ServiceWorkerJobTest
, RegisterMultipleTimesWhileUninstalling
) {
1304 GURL
pattern("http://www.example.com/one/");
1305 GURL
script1("http://www.example.com/service_worker.js?first");
1306 GURL
script2("http://www.example.com/service_worker.js?second");
1307 GURL
script3("http://www.example.com/service_worker.js?third");
1309 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1310 RunRegisterJob(pattern
, script1
);
1312 // Add a controllee and queue an unregister to force the uninstalling state.
1313 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1314 scoped_refptr
<ServiceWorkerVersion
> first_version
=
1315 registration
->active_version();
1316 first_version
->AddControllee(host
.get());
1317 RunUnregisterJob(pattern
);
1319 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1321 scoped_refptr
<ServiceWorkerVersion
> second_version
=
1322 registration
->waiting_version();
1323 ASSERT_TRUE(second_version
);
1325 RunUnregisterJob(pattern
);
1327 EXPECT_TRUE(registration
->is_uninstalling());
1329 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script3
));
1331 scoped_refptr
<ServiceWorkerVersion
> third_version
=
1332 registration
->waiting_version();
1333 ASSERT_TRUE(third_version
);
1335 EXPECT_FALSE(registration
->is_uninstalling());
1336 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, second_version
->status());
1338 first_version
->RemoveControllee(host
.get());
1339 base::RunLoop().RunUntilIdle();
1341 EXPECT_FALSE(registration
->is_uninstalling());
1342 EXPECT_FALSE(registration
->is_uninstalled());
1344 // Verify the new version is activated.
1345 EXPECT_EQ(NULL
, registration
->installing_version());
1346 EXPECT_EQ(NULL
, registration
->waiting_version());
1347 EXPECT_EQ(third_version
, registration
->active_version());
1348 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, third_version
->running_status());
1349 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, third_version
->status());
1352 class EventCallbackHelper
: public EmbeddedWorkerTestHelper
{
1354 explicit EventCallbackHelper(int mock_render_process_id
)
1355 : EmbeddedWorkerTestHelper(base::FilePath(), mock_render_process_id
),
1356 install_event_result_(blink::WebServiceWorkerEventResultCompleted
),
1357 activate_event_result_(blink::WebServiceWorkerEventResultCompleted
) {}
1359 void OnInstallEvent(int embedded_worker_id
,
1360 int request_id
) override
{
1361 if (!install_callback_
.is_null())
1362 install_callback_
.Run();
1364 new ServiceWorkerHostMsg_InstallEventFinished(
1365 embedded_worker_id
, request_id
, install_event_result_
));
1367 void OnActivateEvent(int embedded_worker_id
, int request_id
) override
{
1369 new ServiceWorkerHostMsg_ActivateEventFinished(
1370 embedded_worker_id
, request_id
, activate_event_result_
));
1373 void set_install_callback(const base::Closure
& callback
) {
1374 install_callback_
= callback
;
1376 void set_install_event_result(blink::WebServiceWorkerEventResult result
) {
1377 install_event_result_
= result
;
1379 void set_activate_event_result(blink::WebServiceWorkerEventResult result
) {
1380 activate_event_result_
= result
;
1383 base::Closure install_callback_
;
1384 blink::WebServiceWorkerEventResult install_event_result_
;
1385 blink::WebServiceWorkerEventResult activate_event_result_
;
1388 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringInstall
) {
1389 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1390 helper_
.reset(helper
);
1392 GURL
pattern("http://www.example.com/one/");
1393 GURL
script1("http://www.example.com/service_worker.js");
1394 GURL
script2("http://www.example.com/service_worker.js?new");
1396 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1397 RunRegisterJob(pattern
, script1
);
1399 // Add a controllee and queue an unregister to force the uninstalling state.
1400 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1401 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1402 registration
->active_version();
1403 old_version
->AddControllee(host
.get());
1404 RunUnregisterJob(pattern
);
1406 // Register another script. While installing, old_version loses controllee.
1407 helper
->set_install_callback(
1408 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1409 old_version
, host
.get()));
1410 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1412 EXPECT_FALSE(registration
->is_uninstalling());
1413 EXPECT_FALSE(registration
->is_uninstalled());
1415 // Verify the new version is activated.
1416 scoped_refptr
<ServiceWorkerVersion
> new_version
=
1417 registration
->active_version();
1418 EXPECT_NE(old_version
, new_version
);
1419 EXPECT_EQ(NULL
, registration
->installing_version());
1420 EXPECT_EQ(NULL
, registration
->waiting_version());
1421 EXPECT_EQ(new_version
, registration
->active_version());
1422 EXPECT_EQ(ServiceWorkerVersion::RUNNING
, new_version
->running_status());
1423 EXPECT_EQ(ServiceWorkerVersion::ACTIVATED
, new_version
->status());
1425 EXPECT_EQ(registration
, FindRegistrationForPattern(pattern
));
1428 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringRejectedInstall
) {
1429 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1430 helper_
.reset(helper
);
1432 GURL
pattern("http://www.example.com/one/");
1433 GURL
script1("http://www.example.com/service_worker.js");
1434 GURL
script2("http://www.example.com/service_worker.js?new");
1436 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1437 RunRegisterJob(pattern
, script1
);
1439 // Add a controllee and queue an unregister to force the uninstalling state.
1440 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1441 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1442 registration
->active_version();
1443 old_version
->AddControllee(host
.get());
1444 RunUnregisterJob(pattern
);
1446 // Register another script that fails to install. While installing,
1447 // old_version loses controllee.
1448 helper
->set_install_callback(
1449 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1450 old_version
, host
.get()));
1451 helper
->set_install_event_result(blink::WebServiceWorkerEventResultRejected
);
1452 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1454 // Verify the registration was uninstalled.
1455 EXPECT_FALSE(registration
->is_uninstalling());
1456 EXPECT_TRUE(registration
->is_uninstalled());
1458 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1459 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1461 FindRegistrationForPattern(pattern
, SERVICE_WORKER_ERROR_NOT_FOUND
);
1464 TEST_F(ServiceWorkerJobTest
, RemoveControlleeDuringInstall_RejectActivate
) {
1465 EventCallbackHelper
* helper
= new EventCallbackHelper(render_process_id_
);
1466 helper_
.reset(helper
);
1468 GURL
pattern("http://www.example.com/one/");
1469 GURL
script1("http://www.example.com/service_worker.js");
1470 GURL
script2("http://www.example.com/service_worker.js?new");
1472 scoped_refptr
<ServiceWorkerRegistration
> registration
=
1473 RunRegisterJob(pattern
, script1
);
1475 // Add a controllee and queue an unregister to force the uninstalling state.
1476 scoped_ptr
<ServiceWorkerProviderHost
> host
= CreateControllee();
1477 scoped_refptr
<ServiceWorkerVersion
> old_version
=
1478 registration
->active_version();
1479 old_version
->AddControllee(host
.get());
1480 RunUnregisterJob(pattern
);
1482 // Register another script that fails to activate. While installing,
1483 // old_version loses controllee.
1484 helper
->set_install_callback(
1485 base::Bind(&ServiceWorkerVersion::RemoveControllee
,
1486 old_version
, host
.get()));
1487 helper
->set_activate_event_result(blink::WebServiceWorkerEventResultRejected
);
1488 EXPECT_EQ(registration
, RunRegisterJob(pattern
, script2
));
1490 // Verify the registration remains.
1491 EXPECT_FALSE(registration
->is_uninstalling());
1492 EXPECT_FALSE(registration
->is_uninstalled());
1494 EXPECT_EQ(ServiceWorkerVersion::STOPPED
, old_version
->running_status());
1495 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, old_version
->status());
1497 FindRegistrationForPattern(pattern
, SERVICE_WORKER_OK
);
1500 } // namespace content