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