Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_job_unittest.cc
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.
4
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/public/test/test_browser_thread_bundle.h"
18 #include "ipc/ipc_test_sink.h"
19 #include "net/base/io_buffer.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/test_completion_callback.h"
22 #include "net/http/http_response_headers.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using net::IOBuffer;
26 using net::TestCompletionCallback;
27 using net::WrappedIOBuffer;
28
29 // Unit tests for testing all job registration tasks.
30 namespace content {
31
32 namespace {
33
34 int kMockRenderProcessId = 88;
35
36 void SaveRegistrationCallback(
37     ServiceWorkerStatusCode expected_status,
38     bool* called,
39     scoped_refptr<ServiceWorkerRegistration>* registration_out,
40     ServiceWorkerStatusCode status,
41     ServiceWorkerRegistration* registration) {
42   EXPECT_EQ(expected_status, status);
43   *called = true;
44   *registration_out = registration;
45 }
46
47 void SaveFoundRegistrationCallback(
48     ServiceWorkerStatusCode expected_status,
49     bool* called,
50     scoped_refptr<ServiceWorkerRegistration>* registration,
51     ServiceWorkerStatusCode status,
52     const scoped_refptr<ServiceWorkerRegistration>& result) {
53   EXPECT_EQ(expected_status, status);
54   *called = true;
55   *registration = result;
56 }
57
58 // Creates a callback which both keeps track of if it's been called,
59 // as well as the resulting registration. Whent the callback is fired,
60 // it ensures that the resulting status matches the expectation.
61 // 'called' is useful for making sure a sychronous callback is or
62 // isn't called.
63 ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration(
64     ServiceWorkerStatusCode expected_status,
65     bool* called,
66     scoped_refptr<ServiceWorkerRegistration>* registration) {
67   *called = false;
68   return base::Bind(
69       &SaveRegistrationCallback, expected_status, called, registration);
70 }
71
72 ServiceWorkerStorage::FindRegistrationCallback SaveFoundRegistration(
73     ServiceWorkerStatusCode expected_status,
74     bool* called,
75     scoped_refptr<ServiceWorkerRegistration>* registration) {
76   *called = false;
77   return base::Bind(&SaveFoundRegistrationCallback,
78                     expected_status,
79                     called,
80                     registration);
81 }
82
83 void SaveUnregistrationCallback(ServiceWorkerStatusCode expected_status,
84                                 bool* called,
85                                 ServiceWorkerStatusCode status) {
86   EXPECT_EQ(expected_status, status);
87   *called = true;
88 }
89
90 ServiceWorkerUnregisterJob::UnregistrationCallback SaveUnregistration(
91     ServiceWorkerStatusCode expected_status,
92     bool* called) {
93   *called = false;
94   return base::Bind(&SaveUnregistrationCallback, expected_status, called);
95 }
96
97 }  // namespace
98
99 class ServiceWorkerJobTest : public testing::Test {
100  public:
101   ServiceWorkerJobTest()
102       : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
103         render_process_id_(kMockRenderProcessId) {}
104
105   void SetUp() override {
106     helper_.reset(new EmbeddedWorkerTestHelper(render_process_id_));
107   }
108
109   void TearDown() override { helper_.reset(); }
110
111   ServiceWorkerContextCore* context() const { return helper_->context(); }
112
113   ServiceWorkerJobCoordinator* job_coordinator() const {
114     return context()->job_coordinator();
115   }
116   ServiceWorkerStorage* storage() const { return context()->storage(); }
117
118  protected:
119   TestBrowserThreadBundle browser_thread_bundle_;
120   scoped_ptr<EmbeddedWorkerTestHelper> helper_;
121   int render_process_id_;
122 };
123
124 TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
125   scoped_refptr<ServiceWorkerRegistration> original_registration;
126   bool called;
127   job_coordinator()->Register(
128       GURL("http://www.example.com/"),
129       GURL("http://www.example.com/service_worker.js"),
130       NULL,
131       SaveRegistration(SERVICE_WORKER_OK, &called, &original_registration));
132   EXPECT_FALSE(called);
133   base::RunLoop().RunUntilIdle();
134   EXPECT_TRUE(called);
135
136   scoped_refptr<ServiceWorkerRegistration> registration1;
137   storage()->FindRegistrationForDocument(
138       GURL("http://www.example.com/"),
139       SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
140   scoped_refptr<ServiceWorkerRegistration> registration2;
141   storage()->FindRegistrationForDocument(
142       GURL("http://www.example.com/"),
143       SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
144   base::RunLoop().RunUntilIdle();
145   EXPECT_TRUE(called);
146   ASSERT_TRUE(registration1.get());
147   ASSERT_EQ(registration1, original_registration);
148   ASSERT_EQ(registration1, registration2);
149 }
150
151 TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
152   bool called;
153   scoped_refptr<ServiceWorkerRegistration> original_registration;
154   job_coordinator()->Register(
155       GURL("http://www.example.com/"),
156       GURL("http://www.example.com/service_worker.js"),
157       NULL,
158       SaveRegistration(SERVICE_WORKER_OK, &called, &original_registration));
159   EXPECT_FALSE(called);
160   base::RunLoop().RunUntilIdle();
161   EXPECT_TRUE(called);
162   ASSERT_NE(static_cast<ServiceWorkerRegistration*>(NULL),
163             original_registration.get());
164
165   scoped_refptr<ServiceWorkerRegistration> registration1;
166   storage()->FindRegistrationForDocument(
167       GURL("http://www.example.com/one"),
168       SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
169   base::RunLoop().RunUntilIdle();
170   EXPECT_TRUE(called);
171
172   scoped_refptr<ServiceWorkerRegistration> registration2;
173   storage()->FindRegistrationForDocument(
174       GURL("http://www.example.com/two"),
175       SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
176   base::RunLoop().RunUntilIdle();
177   EXPECT_TRUE(called);
178   ASSERT_EQ(registration1, original_registration);
179   ASSERT_EQ(registration1, registration2);
180 }
181
182 TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
183   bool called1;
184   scoped_refptr<ServiceWorkerRegistration> original_registration1;
185   job_coordinator()->Register(
186       GURL("http://www.example.com/one/"),
187       GURL("http://www.example.com/service_worker.js"),
188       NULL,
189       SaveRegistration(SERVICE_WORKER_OK, &called1, &original_registration1));
190
191   bool called2;
192   scoped_refptr<ServiceWorkerRegistration> original_registration2;
193   job_coordinator()->Register(
194       GURL("http://www.example.com/two/"),
195       GURL("http://www.example.com/service_worker.js"),
196       NULL,
197       SaveRegistration(SERVICE_WORKER_OK, &called2, &original_registration2));
198
199   EXPECT_FALSE(called1);
200   EXPECT_FALSE(called2);
201   base::RunLoop().RunUntilIdle();
202   EXPECT_TRUE(called2);
203   EXPECT_TRUE(called1);
204
205   scoped_refptr<ServiceWorkerRegistration> registration1;
206   storage()->FindRegistrationForDocument(
207       GURL("http://www.example.com/one/"),
208       SaveFoundRegistration(SERVICE_WORKER_OK, &called1, &registration1));
209   scoped_refptr<ServiceWorkerRegistration> registration2;
210   storage()->FindRegistrationForDocument(
211       GURL("http://www.example.com/two/"),
212       SaveFoundRegistration(SERVICE_WORKER_OK, &called2, &registration2));
213
214   base::RunLoop().RunUntilIdle();
215   EXPECT_TRUE(called2);
216   EXPECT_TRUE(called1);
217   ASSERT_NE(registration1, registration2);
218 }
219
220 // Make sure basic registration is working.
221 TEST_F(ServiceWorkerJobTest, Register) {
222   bool called = false;
223   scoped_refptr<ServiceWorkerRegistration> registration;
224   job_coordinator()->Register(
225       GURL("http://www.example.com/"),
226       GURL("http://www.example.com/service_worker.js"),
227       NULL,
228       SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
229
230   ASSERT_FALSE(called);
231   base::RunLoop().RunUntilIdle();
232   ASSERT_TRUE(called);
233
234   ASSERT_NE(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
235 }
236
237 // Make sure registrations are cleaned up when they are unregistered.
238 TEST_F(ServiceWorkerJobTest, Unregister) {
239   GURL pattern("http://www.example.com/");
240
241   bool called;
242   scoped_refptr<ServiceWorkerRegistration> registration;
243   job_coordinator()->Register(
244       pattern,
245       GURL("http://www.example.com/service_worker.js"),
246       NULL,
247       SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
248
249   ASSERT_FALSE(called);
250   base::RunLoop().RunUntilIdle();
251   ASSERT_TRUE(called);
252
253   job_coordinator()->Unregister(pattern,
254                                 SaveUnregistration(SERVICE_WORKER_OK, &called));
255
256   ASSERT_FALSE(called);
257   base::RunLoop().RunUntilIdle();
258   ASSERT_TRUE(called);
259
260   ASSERT_TRUE(registration->HasOneRef());
261
262   storage()->FindRegistrationForPattern(
263       pattern,
264       SaveFoundRegistration(SERVICE_WORKER_ERROR_NOT_FOUND,
265                             &called, &registration));
266
267   ASSERT_FALSE(called);
268   base::RunLoop().RunUntilIdle();
269   ASSERT_TRUE(called);
270
271   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
272 }
273
274 TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
275   GURL pattern("http://www.example.com/");
276
277   bool called;
278   job_coordinator()->Unregister(
279       pattern,
280       SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND, &called));
281
282   ASSERT_FALSE(called);
283   base::RunLoop().RunUntilIdle();
284   ASSERT_TRUE(called);
285 }
286
287 // Make sure registering a new script creates a new version and shares an
288 // existing registration.
289 TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
290   GURL pattern("http://www.example.com/");
291
292   bool called;
293   scoped_refptr<ServiceWorkerRegistration> old_registration;
294   job_coordinator()->Register(
295       pattern,
296       GURL("http://www.example.com/service_worker.js"),
297       NULL,
298       SaveRegistration(SERVICE_WORKER_OK, &called, &old_registration));
299
300   ASSERT_FALSE(called);
301   base::RunLoop().RunUntilIdle();
302   ASSERT_TRUE(called);
303
304   scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern;
305   storage()->FindRegistrationForPattern(
306       pattern,
307       SaveFoundRegistration(
308           SERVICE_WORKER_OK, &called, &old_registration_by_pattern));
309
310   ASSERT_FALSE(called);
311   base::RunLoop().RunUntilIdle();
312   ASSERT_TRUE(called);
313
314   ASSERT_EQ(old_registration, old_registration_by_pattern);
315   old_registration_by_pattern = NULL;
316
317   scoped_refptr<ServiceWorkerRegistration> new_registration;
318   job_coordinator()->Register(
319       pattern,
320       GURL("http://www.example.com/service_worker_new.js"),
321       NULL,
322       SaveRegistration(SERVICE_WORKER_OK, &called, &new_registration));
323
324   ASSERT_FALSE(called);
325   base::RunLoop().RunUntilIdle();
326   ASSERT_TRUE(called);
327
328   ASSERT_EQ(old_registration, new_registration);
329
330   scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern;
331   storage()->FindRegistrationForPattern(
332       pattern,
333       SaveFoundRegistration(
334           SERVICE_WORKER_OK, &called, &new_registration));
335
336   ASSERT_FALSE(called);
337   base::RunLoop().RunUntilIdle();
338   ASSERT_TRUE(called);
339
340   ASSERT_NE(new_registration_by_pattern, old_registration);
341 }
342
343 // Make sure that when registering a duplicate pattern+script_url
344 // combination, that the same registration is used.
345 TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
346   GURL pattern("http://www.example.com/");
347   GURL script_url("http://www.example.com/service_worker.js");
348
349   bool called;
350   scoped_refptr<ServiceWorkerRegistration> old_registration;
351   job_coordinator()->Register(
352       pattern,
353       script_url,
354       NULL,
355       SaveRegistration(SERVICE_WORKER_OK, &called, &old_registration));
356
357   ASSERT_FALSE(called);
358   base::RunLoop().RunUntilIdle();
359   ASSERT_TRUE(called);
360
361   scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern;
362   storage()->FindRegistrationForPattern(
363       pattern,
364       SaveFoundRegistration(
365           SERVICE_WORKER_OK, &called, &old_registration_by_pattern));
366   ASSERT_FALSE(called);
367   base::RunLoop().RunUntilIdle();
368   ASSERT_TRUE(called);
369
370   ASSERT_TRUE(old_registration_by_pattern.get());
371
372   scoped_refptr<ServiceWorkerRegistration> new_registration;
373   job_coordinator()->Register(
374       pattern,
375       script_url,
376       NULL,
377       SaveRegistration(SERVICE_WORKER_OK, &called, &new_registration));
378
379   ASSERT_FALSE(called);
380   base::RunLoop().RunUntilIdle();
381   ASSERT_TRUE(called);
382
383   ASSERT_EQ(old_registration, new_registration);
384
385   ASSERT_FALSE(old_registration->HasOneRef());
386
387   scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern;
388   storage()->FindRegistrationForPattern(
389       pattern,
390       SaveFoundRegistration(
391           SERVICE_WORKER_OK, &called, &new_registration_by_pattern));
392
393   ASSERT_FALSE(called);
394   base::RunLoop().RunUntilIdle();
395   ASSERT_TRUE(called);
396
397   ASSERT_EQ(new_registration, old_registration);
398 }
399
400 class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
401  public:
402   explicit FailToStartWorkerTestHelper(int mock_render_process_id)
403       : EmbeddedWorkerTestHelper(mock_render_process_id) {}
404
405   void OnStartWorker(int embedded_worker_id,
406                      int64 service_worker_version_id,
407                      const GURL& scope,
408                      const GURL& script_url,
409                      bool pause_after_download) override {
410     EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
411     registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
412   }
413 };
414
415 TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
416   helper_.reset(new FailToStartWorkerTestHelper(render_process_id_));
417
418   bool called = false;
419   scoped_refptr<ServiceWorkerRegistration> registration;
420   job_coordinator()->Register(
421       GURL("http://www.example.com/"),
422       GURL("http://www.example.com/service_worker.js"),
423       NULL,
424       SaveRegistration(
425           SERVICE_WORKER_ERROR_START_WORKER_FAILED, &called, &registration));
426
427   ASSERT_FALSE(called);
428   base::RunLoop().RunUntilIdle();
429
430   ASSERT_TRUE(called);
431   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
432 }
433
434 // Register and then unregister the pattern, in parallel. Job coordinator should
435 // process jobs until the last job.
436 TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
437   GURL pattern("http://www.example.com/");
438   GURL script_url("http://www.example.com/service_worker.js");
439
440   bool registration_called = false;
441   scoped_refptr<ServiceWorkerRegistration> registration;
442   job_coordinator()->Register(
443       pattern,
444       script_url,
445       NULL,
446       SaveRegistration(SERVICE_WORKER_OK, &registration_called, &registration));
447
448   bool unregistration_called = false;
449   job_coordinator()->Unregister(
450       pattern,
451       SaveUnregistration(SERVICE_WORKER_OK, &unregistration_called));
452
453   ASSERT_FALSE(registration_called);
454   ASSERT_FALSE(unregistration_called);
455   base::RunLoop().RunUntilIdle();
456   ASSERT_TRUE(registration_called);
457   ASSERT_TRUE(unregistration_called);
458
459   bool find_called = false;
460   storage()->FindRegistrationForPattern(
461       pattern,
462       SaveFoundRegistration(
463           SERVICE_WORKER_ERROR_NOT_FOUND, &find_called, &registration));
464
465   base::RunLoop().RunUntilIdle();
466
467   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
468 }
469
470 // Register conflicting scripts for the same pattern. The most recent
471 // registration should win, and the old registration should have been
472 // shutdown.
473 TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
474   GURL pattern("http://www.example.com/");
475
476   GURL script_url1("http://www.example.com/service_worker1.js");
477   bool registration1_called = false;
478   scoped_refptr<ServiceWorkerRegistration> registration1;
479   job_coordinator()->Register(
480       pattern,
481       script_url1,
482       NULL,
483       SaveRegistration(
484           SERVICE_WORKER_OK, &registration1_called, &registration1));
485
486   GURL script_url2("http://www.example.com/service_worker2.js");
487   bool registration2_called = false;
488   scoped_refptr<ServiceWorkerRegistration> registration2;
489   job_coordinator()->Register(
490       pattern,
491       script_url2,
492       NULL,
493       SaveRegistration(
494           SERVICE_WORKER_OK, &registration2_called, &registration2));
495
496   ASSERT_FALSE(registration1_called);
497   ASSERT_FALSE(registration2_called);
498   base::RunLoop().RunUntilIdle();
499   ASSERT_TRUE(registration1_called);
500   ASSERT_TRUE(registration2_called);
501
502   scoped_refptr<ServiceWorkerRegistration> registration;
503   bool find_called = false;
504   storage()->FindRegistrationForPattern(
505       pattern,
506       SaveFoundRegistration(
507           SERVICE_WORKER_OK, &find_called, &registration));
508
509   base::RunLoop().RunUntilIdle();
510
511   ASSERT_EQ(registration2, registration);
512 }
513
514 // Register the exact same pattern + script. Requests should be
515 // coalesced such that both callers get the exact same registration
516 // object.
517 TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
518   GURL pattern("http://www.example.com/");
519
520   GURL script_url("http://www.example.com/service_worker1.js");
521   bool registration1_called = false;
522   scoped_refptr<ServiceWorkerRegistration> registration1;
523   job_coordinator()->Register(
524       pattern,
525       script_url,
526       NULL,
527       SaveRegistration(
528           SERVICE_WORKER_OK, &registration1_called, &registration1));
529
530   bool registration2_called = false;
531   scoped_refptr<ServiceWorkerRegistration> registration2;
532   job_coordinator()->Register(
533       pattern,
534       script_url,
535       NULL,
536       SaveRegistration(
537           SERVICE_WORKER_OK, &registration2_called, &registration2));
538
539   ASSERT_FALSE(registration1_called);
540   ASSERT_FALSE(registration2_called);
541   base::RunLoop().RunUntilIdle();
542   ASSERT_TRUE(registration1_called);
543   ASSERT_TRUE(registration2_called);
544
545   ASSERT_EQ(registration1, registration2);
546
547   scoped_refptr<ServiceWorkerRegistration> registration;
548   bool find_called = false;
549   storage()->FindRegistrationForPattern(
550       pattern,
551       SaveFoundRegistration(
552           SERVICE_WORKER_OK, &find_called, &registration));
553
554   base::RunLoop().RunUntilIdle();
555   ASSERT_EQ(registration, registration1);
556 }
557
558 // Call simulataneous unregister calls.
559 TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
560   GURL pattern("http://www.example.com/");
561
562   GURL script_url("http://www.example.com/service_worker.js");
563   bool unregistration1_called = false;
564   job_coordinator()->Unregister(
565       pattern,
566       SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
567                          &unregistration1_called));
568
569   bool unregistration2_called = false;
570   job_coordinator()->Unregister(
571       pattern,
572       SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
573                          &unregistration2_called));
574
575   ASSERT_FALSE(unregistration1_called);
576   ASSERT_FALSE(unregistration2_called);
577   base::RunLoop().RunUntilIdle();
578   ASSERT_TRUE(unregistration1_called);
579   ASSERT_TRUE(unregistration2_called);
580
581   // There isn't really a way to test that they are being coalesced,
582   // but we can make sure they can exist simultaneously without
583   // crashing.
584   scoped_refptr<ServiceWorkerRegistration> registration;
585   bool find_called = false;
586   storage()->FindRegistrationForPattern(
587       pattern,
588       SaveFoundRegistration(
589           SERVICE_WORKER_ERROR_NOT_FOUND, &find_called, &registration));
590
591   base::RunLoop().RunUntilIdle();
592   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
593 }
594
595 TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
596   GURL pattern1("http://www1.example.com/");
597   GURL pattern2("http://www2.example.com/");
598   GURL script_url1("http://www1.example.com/service_worker.js");
599   GURL script_url2("http://www2.example.com/service_worker.js");
600
601   bool registration_called1 = false;
602   scoped_refptr<ServiceWorkerRegistration> registration1;
603   job_coordinator()->Register(
604       pattern1,
605       script_url1,
606       NULL,
607       SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
608                        &registration_called1, &registration1));
609
610   bool registration_called2 = false;
611   scoped_refptr<ServiceWorkerRegistration> registration2;
612   job_coordinator()->Register(
613       pattern2,
614       script_url2,
615       NULL,
616       SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
617                        &registration_called2, &registration2));
618
619   ASSERT_FALSE(registration_called1);
620   ASSERT_FALSE(registration_called2);
621   job_coordinator()->AbortAll();
622
623   base::RunLoop().RunUntilIdle();
624   ASSERT_TRUE(registration_called1);
625   ASSERT_TRUE(registration_called2);
626
627   bool find_called1 = false;
628   storage()->FindRegistrationForPattern(
629       pattern1,
630       SaveFoundRegistration(
631           SERVICE_WORKER_ERROR_NOT_FOUND, &find_called1, &registration1));
632
633   bool find_called2 = false;
634   storage()->FindRegistrationForPattern(
635       pattern2,
636       SaveFoundRegistration(
637           SERVICE_WORKER_ERROR_NOT_FOUND, &find_called2, &registration2));
638
639   base::RunLoop().RunUntilIdle();
640   ASSERT_TRUE(find_called1);
641   ASSERT_TRUE(find_called2);
642   EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration1);
643   EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration2);
644 }
645
646 TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
647   GURL pattern1("http://www1.example.com/");
648   GURL pattern2("http://www2.example.com/");
649
650   bool unregistration_called1 = false;
651   scoped_refptr<ServiceWorkerRegistration> registration1;
652   job_coordinator()->Unregister(
653       pattern1,
654       SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
655                          &unregistration_called1));
656
657   bool unregistration_called2 = false;
658   job_coordinator()->Unregister(
659       pattern2,
660       SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
661                          &unregistration_called2));
662
663   ASSERT_FALSE(unregistration_called1);
664   ASSERT_FALSE(unregistration_called2);
665   job_coordinator()->AbortAll();
666
667   base::RunLoop().RunUntilIdle();
668   ASSERT_TRUE(unregistration_called1);
669   ASSERT_TRUE(unregistration_called2);
670 }
671
672 TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
673   GURL pattern("http://www.example.com/");
674   GURL script_url("http://www.example.com/service_worker.js");
675
676   bool registration_called = false;
677   scoped_refptr<ServiceWorkerRegistration> registration;
678   job_coordinator()->Register(
679       pattern,
680       script_url,
681       NULL,
682       SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
683                        &registration_called, &registration));
684
685   bool unregistration_called = false;
686   job_coordinator()->Unregister(
687       pattern,
688       SaveUnregistration(SERVICE_WORKER_ERROR_ABORT,
689                          &unregistration_called));
690
691   ASSERT_FALSE(registration_called);
692   ASSERT_FALSE(unregistration_called);
693   job_coordinator()->AbortAll();
694
695   base::RunLoop().RunUntilIdle();
696   ASSERT_TRUE(registration_called);
697   ASSERT_TRUE(unregistration_called);
698
699   bool find_called = false;
700   storage()->FindRegistrationForPattern(
701       pattern,
702       SaveFoundRegistration(
703           SERVICE_WORKER_ERROR_NOT_FOUND, &find_called, &registration));
704
705   base::RunLoop().RunUntilIdle();
706   ASSERT_TRUE(find_called);
707   EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
708 }
709
710 // Tests that the waiting worker enters the 'redundant' state upon
711 // unregistration.
712 TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
713   scoped_refptr<ServiceWorkerRegistration> registration;
714   bool called = false;
715   GURL script_url("http://www.example.com/service_worker.js");
716   job_coordinator()->Register(
717       GURL("http://www.example.com/"),
718       script_url,
719       NULL,
720       SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
721   base::RunLoop().RunUntilIdle();
722   ASSERT_TRUE(called);
723   ASSERT_TRUE(registration.get());
724
725   // Manually create the waiting worker since there is no way to become a
726   // waiting worker until Update is implemented.
727   scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
728       registration.get(), script_url, 1L, helper_->context()->AsWeakPtr());
729   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
730   version->StartWorker(CreateReceiverOnCurrentThread(&status));
731   base::RunLoop().RunUntilIdle();
732   ASSERT_EQ(SERVICE_WORKER_OK, status);
733
734   version->SetStatus(ServiceWorkerVersion::INSTALLED);
735   registration->SetWaitingVersion(version.get());
736   EXPECT_EQ(ServiceWorkerVersion::RUNNING,
737             version->running_status());
738   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
739
740   called = false;
741   job_coordinator()->Unregister(GURL("http://www.example.com/"),
742                                 SaveUnregistration(SERVICE_WORKER_OK, &called));
743   base::RunLoop().RunUntilIdle();
744   ASSERT_TRUE(called);
745
746   // The version should be stopped since there is no controllee after
747   // unregistration.
748   EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
749   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
750 }
751
752 // Tests that the active worker enters the 'redundant' state upon
753 // unregistration.
754 TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
755   scoped_refptr<ServiceWorkerRegistration> registration;
756   bool called = false;
757   job_coordinator()->Register(
758       GURL("http://www.example.com/"),
759       GURL("http://www.example.com/service_worker.js"),
760       NULL,
761       SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
762   base::RunLoop().RunUntilIdle();
763   ASSERT_TRUE(called);
764   ASSERT_TRUE(registration.get());
765
766   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
767   EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
768   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
769
770   called = false;
771   job_coordinator()->Unregister(GURL("http://www.example.com/"),
772                                 SaveUnregistration(SERVICE_WORKER_OK, &called));
773   base::RunLoop().RunUntilIdle();
774   ASSERT_TRUE(called);
775
776   // The version should be stopped since there is no controllee after
777   // unregistration.
778   EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
779   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
780 }
781
782 // Tests that the active worker enters the 'redundant' state upon
783 // unregistration.
784 TEST_F(ServiceWorkerJobTest,
785        UnregisterActiveSetsRedundant_WaitForNoControllee) {
786   scoped_refptr<ServiceWorkerRegistration> registration;
787   bool called = false;
788   job_coordinator()->Register(
789       GURL("http://www.example.com/"),
790       GURL("http://www.example.com/service_worker.js"),
791       NULL,
792       SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
793   base::RunLoop().RunUntilIdle();
794   ASSERT_TRUE(called);
795   ASSERT_TRUE(registration.get());
796
797   scoped_ptr<ServiceWorkerProviderHost> host(
798       new ServiceWorkerProviderHost(33 /* dummy render process id */,
799                                     1 /* dummy provider_id */,
800                                     context()->AsWeakPtr(),
801                                     NULL));
802   registration->active_version()->AddControllee(host.get());
803
804   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
805   EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
806   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
807
808   called = false;
809   job_coordinator()->Unregister(GURL("http://www.example.com/"),
810                                 SaveUnregistration(SERVICE_WORKER_OK, &called));
811   base::RunLoop().RunUntilIdle();
812   ASSERT_TRUE(called);
813
814   // The version should be running since there is still a controllee.
815   EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
816   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
817
818   registration->active_version()->RemoveControllee(host.get());
819   base::RunLoop().RunUntilIdle();
820
821   // The version should be stopped since there is no controllee.
822   EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
823   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
824 }
825
826 namespace {  // Helpers for the update job tests.
827
828 const GURL kNoChangeOrigin("http://nochange/");
829 const GURL kNewVersionOrigin("http://newversion/");
830 const std::string kScope("scope/");
831 const std::string kScript("script.js");
832
833 void RunNestedUntilIdle() {
834   base::MessageLoop::ScopedNestableTaskAllower allow(
835       base::MessageLoop::current());
836   base::MessageLoop::current()->RunUntilIdle();
837 }
838
839 void OnIOComplete(int* rv_out, int rv) {
840   *rv_out = rv;
841 }
842
843 void WriteResponse(
844     ServiceWorkerStorage* storage, int64 id,
845     const std::string& headers,
846     IOBuffer* body, int length) {
847   scoped_ptr<ServiceWorkerResponseWriter> writer =
848       storage->CreateResponseWriter(id);
849
850   scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
851   info->request_time = base::Time::Now();
852   info->response_time = base::Time::Now();
853   info->was_cached = false;
854   info->headers = new net::HttpResponseHeaders(headers);
855   scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
856       new HttpResponseInfoIOBuffer(info.release());
857
858   int rv = -1234;
859   writer->WriteInfo(info_buffer.get(), base::Bind(&OnIOComplete, &rv));
860   RunNestedUntilIdle();
861   EXPECT_LT(0, rv);
862
863   rv = -1234;
864   writer->WriteData(body, length,
865                     base::Bind(&OnIOComplete, &rv));
866   RunNestedUntilIdle();
867   EXPECT_EQ(length, rv);
868 }
869
870 void WriteStringResponse(
871     ServiceWorkerStorage* storage, int64 id,
872     const std::string& body) {
873   scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
874   const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
875   std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
876   WriteResponse(storage, id, headers, body_buffer.get(), body.length());
877 }
878
879 class UpdateJobTestHelper
880     : public EmbeddedWorkerTestHelper,
881       public ServiceWorkerRegistration::Listener,
882       public ServiceWorkerVersion::Listener {
883  public:
884   struct AttributeChangeLogEntry {
885     int64 registration_id;
886     ChangedVersionAttributesMask mask;
887     ServiceWorkerRegistrationInfo info;
888   };
889
890   struct StateChangeLogEntry {
891     int64 version_id;
892     ServiceWorkerVersion::Status status;
893   };
894
895   UpdateJobTestHelper(int mock_render_process_id)
896       : EmbeddedWorkerTestHelper(mock_render_process_id),
897         update_found_(false) {}
898   ~UpdateJobTestHelper() override {
899     if (registration_.get())
900       registration_->RemoveListener(this);
901   }
902
903   ServiceWorkerStorage* storage() { return context()->storage(); }
904   ServiceWorkerJobCoordinator* job_coordinator() {
905     return context()->job_coordinator();
906   }
907
908   scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration(
909       const GURL& test_origin) {
910     scoped_refptr<ServiceWorkerRegistration> registration;
911     bool called = false;
912     job_coordinator()->Register(
913         test_origin.Resolve(kScope),
914         test_origin.Resolve(kScript),
915         NULL,
916         SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
917     base::RunLoop().RunUntilIdle();
918     EXPECT_TRUE(called);
919     EXPECT_TRUE(registration.get());
920     EXPECT_TRUE(registration->active_version());
921     EXPECT_FALSE(registration->installing_version());
922     EXPECT_FALSE(registration->waiting_version());
923     registration_ = registration;
924     return registration;
925   }
926
927   // EmbeddedWorkerTestHelper overrides
928   void OnStartWorker(int embedded_worker_id,
929                      int64 version_id,
930                      const GURL& scope,
931                      const GURL& script,
932                      bool pause_after_download) override {
933     const std::string kMockScriptBody = "mock_script";
934     const uint64 kMockScriptSize = 19284;
935     ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
936     ASSERT_TRUE(version);
937     version->AddListener(this);
938
939     if (!pause_after_download) {
940       // Spoof caching the script for the initial version.
941       int64 resource_id = storage()->NewResourceId();
942       version->script_cache_map()->NotifyStartedCaching(script, resource_id);
943       WriteStringResponse(storage(), resource_id, kMockScriptBody);
944       version->script_cache_map()->NotifyFinishedCaching(
945           script, kMockScriptSize, net::URLRequestStatus());
946     } else {
947       // Spoof caching the script for the new version.
948       int64 resource_id = storage()->NewResourceId();
949       version->script_cache_map()->NotifyStartedCaching(script, resource_id);
950       if (script.GetOrigin() == kNoChangeOrigin)
951         WriteStringResponse(storage(), resource_id, kMockScriptBody);
952       else
953         WriteStringResponse(storage(), resource_id, "mock_different_script");
954       version->script_cache_map()->NotifyFinishedCaching(
955           script, kMockScriptSize, net::URLRequestStatus());
956     }
957     EmbeddedWorkerTestHelper::OnStartWorker(
958         embedded_worker_id, version_id, scope, script, pause_after_download);
959   }
960
961   // ServiceWorkerRegistration::Listener overrides
962   void OnVersionAttributesChanged(
963       ServiceWorkerRegistration* registration,
964       ChangedVersionAttributesMask changed_mask,
965       const ServiceWorkerRegistrationInfo& info) override {
966     AttributeChangeLogEntry entry;
967     entry.registration_id = registration->id();
968     entry.mask = changed_mask;
969     entry.info = info;
970     attribute_change_log_.push_back(entry);
971   }
972
973   void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
974     NOTREACHED();
975   }
976
977   void OnRegistrationFinishedUninstalling(
978       ServiceWorkerRegistration* registration) override {
979     NOTREACHED();
980   }
981
982   void OnUpdateFound(ServiceWorkerRegistration* registration) override {
983     ASSERT_FALSE(update_found_);
984     update_found_ = true;
985   }
986
987   // ServiceWorkerVersion::Listener overrides
988   void OnVersionStateChanged(ServiceWorkerVersion* version) override {
989     StateChangeLogEntry entry;
990     entry.version_id = version->version_id();
991     entry.status = version->status();
992     state_change_log_.push_back(entry);
993   }
994
995   scoped_refptr<ServiceWorkerRegistration> registration_;
996
997   std::vector<AttributeChangeLogEntry> attribute_change_log_;
998   std::vector<StateChangeLogEntry> state_change_log_;
999   bool update_found_;
1000 };
1001
1002 }  // namespace
1003
1004 TEST_F(ServiceWorkerJobTest, Update_NoChange) {
1005   UpdateJobTestHelper* update_helper =
1006       new UpdateJobTestHelper(render_process_id_);
1007   helper_.reset(update_helper);
1008   scoped_refptr<ServiceWorkerRegistration> registration =
1009       update_helper->SetupInitialRegistration(kNoChangeOrigin);
1010   ASSERT_TRUE(registration.get());
1011   ASSERT_EQ(4u, update_helper->state_change_log_.size());
1012   EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
1013             update_helper->state_change_log_[0].status);
1014   EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
1015             update_helper->state_change_log_[1].status);
1016   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
1017             update_helper->state_change_log_[2].status);
1018   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1019             update_helper->state_change_log_[3].status);
1020   update_helper->state_change_log_.clear();
1021
1022   // Run the update job.
1023   registration->AddListener(update_helper);
1024   scoped_refptr<ServiceWorkerVersion> first_version =
1025       registration->active_version();
1026   first_version->StartUpdate();
1027   base::RunLoop().RunUntilIdle();
1028
1029   // Verify results.
1030   ASSERT_TRUE(registration->active_version());
1031   EXPECT_EQ(first_version.get(), registration->active_version());
1032   EXPECT_FALSE(registration->installing_version());
1033   EXPECT_FALSE(registration->waiting_version());
1034   EXPECT_TRUE(update_helper->attribute_change_log_.empty());
1035   ASSERT_EQ(1u, update_helper->state_change_log_.size());
1036   EXPECT_NE(registration->active_version()->version_id(),
1037             update_helper->state_change_log_[0].version_id);
1038   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
1039             update_helper->state_change_log_[0].status);
1040   EXPECT_FALSE(update_helper->update_found_);
1041 }
1042
1043 TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
1044   UpdateJobTestHelper* update_helper =
1045       new UpdateJobTestHelper(render_process_id_);
1046   helper_.reset(update_helper);
1047   scoped_refptr<ServiceWorkerRegistration> registration =
1048       update_helper->SetupInitialRegistration(kNewVersionOrigin);
1049   ASSERT_TRUE(registration.get());
1050   update_helper->state_change_log_.clear();
1051
1052   // Run the update job.
1053   registration->AddListener(update_helper);
1054   scoped_refptr<ServiceWorkerVersion> first_version =
1055       registration->active_version();
1056   first_version->StartUpdate();
1057   base::RunLoop().RunUntilIdle();
1058
1059   // Verify results.
1060   ASSERT_TRUE(registration->active_version());
1061   EXPECT_NE(first_version.get(), registration->active_version());
1062   EXPECT_FALSE(registration->installing_version());
1063   EXPECT_FALSE(registration->waiting_version());
1064   ASSERT_EQ(3u, update_helper->attribute_change_log_.size());
1065
1066   UpdateJobTestHelper::AttributeChangeLogEntry entry;
1067   entry = update_helper->attribute_change_log_[0];
1068   EXPECT_TRUE(entry.mask.installing_changed());
1069   EXPECT_FALSE(entry.mask.waiting_changed());
1070   EXPECT_FALSE(entry.mask.active_changed());
1071   EXPECT_NE(entry.info.installing_version.version_id,
1072             kInvalidServiceWorkerVersionId);
1073   EXPECT_EQ(entry.info.waiting_version.version_id,
1074             kInvalidServiceWorkerVersionId);
1075   EXPECT_NE(entry.info.active_version.version_id,
1076             kInvalidServiceWorkerVersionId);
1077
1078   entry = update_helper->attribute_change_log_[1];
1079   EXPECT_TRUE(entry.mask.installing_changed());
1080   EXPECT_TRUE(entry.mask.waiting_changed());
1081   EXPECT_FALSE(entry.mask.active_changed());
1082   EXPECT_EQ(entry.info.installing_version.version_id,
1083             kInvalidServiceWorkerVersionId);
1084   EXPECT_NE(entry.info.waiting_version.version_id,
1085             kInvalidServiceWorkerVersionId);
1086   EXPECT_NE(entry.info.active_version.version_id,
1087             kInvalidServiceWorkerVersionId);
1088
1089   entry = update_helper->attribute_change_log_[2];
1090   EXPECT_FALSE(entry.mask.installing_changed());
1091   EXPECT_TRUE(entry.mask.waiting_changed());
1092   EXPECT_TRUE(entry.mask.active_changed());
1093   EXPECT_EQ(entry.info.installing_version.version_id,
1094             kInvalidServiceWorkerVersionId);
1095   EXPECT_EQ(entry.info.waiting_version.version_id,
1096             kInvalidServiceWorkerVersionId);
1097   EXPECT_NE(entry.info.active_version.version_id,
1098             kInvalidServiceWorkerVersionId);
1099
1100   // expected version state transitions:
1101   // new.installing, new.installed,
1102   // old.redundant,
1103   // new.activating, new.activated
1104   ASSERT_EQ(5u, update_helper->state_change_log_.size());
1105
1106   EXPECT_EQ(registration->active_version()->version_id(),
1107             update_helper->state_change_log_[0].version_id);
1108   EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
1109             update_helper->state_change_log_[0].status);
1110
1111   EXPECT_EQ(registration->active_version()->version_id(),
1112             update_helper->state_change_log_[1].version_id);
1113   EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
1114             update_helper->state_change_log_[1].status);
1115
1116   EXPECT_EQ(first_version->version_id(),
1117             update_helper->state_change_log_[2].version_id);
1118   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
1119             update_helper->state_change_log_[2].status);
1120
1121   EXPECT_EQ(registration->active_version()->version_id(),
1122             update_helper->state_change_log_[3].version_id);
1123   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
1124             update_helper->state_change_log_[3].status);
1125
1126   EXPECT_EQ(registration->active_version()->version_id(),
1127             update_helper->state_change_log_[4].version_id);
1128   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1129             update_helper->state_change_log_[4].status);
1130
1131   EXPECT_TRUE(update_helper->update_found_);
1132 }
1133
1134 TEST_F(ServiceWorkerJobTest, Update_NewestVersionChanged) {
1135   bool called;
1136   scoped_refptr<ServiceWorkerRegistration> registration;
1137   job_coordinator()->Register(
1138       GURL("http://www.example.com/one/"),
1139       GURL("http://www.example.com/service_worker.js"),
1140       NULL,
1141       SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
1142
1143   EXPECT_FALSE(called);
1144   base::RunLoop().RunUntilIdle();
1145   EXPECT_TRUE(called);
1146   ServiceWorkerVersion* active_version = registration->active_version();
1147
1148   // Queue an Update, it should abort when it starts and sees the new version.
1149   job_coordinator()->Update(registration.get());
1150
1151   // Add a waiting version with new script.
1152   scoped_refptr<ServiceWorkerVersion> version =
1153       new ServiceWorkerVersion(registration.get(),
1154                                GURL("http://www.example.com/new_worker.js"),
1155                                2L /* dummy version id */,
1156                                helper_->context()->AsWeakPtr());
1157   registration->SetWaitingVersion(version.get());
1158
1159   base::RunLoop().RunUntilIdle();
1160
1161   // Verify the registration was not modified by the Update.
1162   EXPECT_EQ(active_version, registration->active_version());
1163   EXPECT_EQ(version.get(), registration->waiting_version());
1164   EXPECT_EQ(NULL, registration->installing_version());
1165 }
1166
1167 TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
1168   bool called;
1169   scoped_refptr<ServiceWorkerRegistration> registration;
1170   job_coordinator()->Register(
1171       GURL("http://www.example.com/one/"),
1172       GURL("http://www.example.com/service_worker.js"),
1173       NULL,
1174       SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
1175
1176   EXPECT_FALSE(called);
1177   base::RunLoop().RunUntilIdle();
1178   EXPECT_TRUE(called);
1179
1180   // Add a controllee and queue an unregister to force the uninstalling state.
1181   scoped_ptr<ServiceWorkerProviderHost> host(
1182       new ServiceWorkerProviderHost(33 /* dummy render_process id */,
1183                                     1 /* dummy provider_id */,
1184                                     helper_->context()->AsWeakPtr(),
1185                                     NULL));
1186   ServiceWorkerVersion* active_version = registration->active_version();
1187   active_version->AddControllee(host.get());
1188   job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
1189                                 SaveUnregistration(SERVICE_WORKER_OK, &called));
1190
1191   // Update should abort after it starts and sees uninstalling.
1192   job_coordinator()->Update(registration.get());
1193
1194   EXPECT_FALSE(called);
1195   base::RunLoop().RunUntilIdle();
1196   EXPECT_TRUE(called);
1197
1198   // Verify the registration was not modified by the Update.
1199   EXPECT_TRUE(registration->is_uninstalling());
1200   EXPECT_EQ(active_version, registration->active_version());
1201   EXPECT_EQ(NULL, registration->waiting_version());
1202   EXPECT_EQ(NULL, registration->installing_version());
1203 }
1204
1205 }  // namespace content