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