Home | History | Annotate | Download | only in service_worker
      1 // Copyright 2013 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 <string>
      6 
      7 #include "base/logging.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/run_loop.h"
     10 #include "content/browser/browser_thread_impl.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_registration.h"
     14 #include "content/browser/service_worker/service_worker_storage.h"
     15 #include "content/browser/service_worker/service_worker_version.h"
     16 #include "content/common/service_worker/service_worker_status_code.h"
     17 #include "content/public/test/test_browser_thread_bundle.h"
     18 #include "net/base/io_buffer.h"
     19 #include "net/base/net_errors.h"
     20 #include "net/http/http_response_headers.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 using net::IOBuffer;
     24 using net::WrappedIOBuffer;
     25 
     26 namespace content {
     27 
     28 namespace {
     29 
     30 typedef ServiceWorkerDatabase::RegistrationData RegistrationData;
     31 typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord;
     32 
     33 void StatusCallback(bool* was_called,
     34                     ServiceWorkerStatusCode* result,
     35                     ServiceWorkerStatusCode status) {
     36   *was_called = true;
     37   *result = status;
     38 }
     39 
     40 ServiceWorkerStorage::StatusCallback MakeStatusCallback(
     41     bool* was_called,
     42     ServiceWorkerStatusCode* result) {
     43   return base::Bind(&StatusCallback, was_called, result);
     44 }
     45 
     46 void FindCallback(
     47     bool* was_called,
     48     ServiceWorkerStatusCode* result,
     49     scoped_refptr<ServiceWorkerRegistration>* found,
     50     ServiceWorkerStatusCode status,
     51     const scoped_refptr<ServiceWorkerRegistration>& registration) {
     52   *was_called = true;
     53   *result = status;
     54   *found = registration;
     55 }
     56 
     57 ServiceWorkerStorage::FindRegistrationCallback MakeFindCallback(
     58     bool* was_called,
     59     ServiceWorkerStatusCode* result,
     60     scoped_refptr<ServiceWorkerRegistration>* found) {
     61   return base::Bind(&FindCallback, was_called, result, found);
     62 }
     63 
     64 void GetAllCallback(
     65     bool* was_called,
     66     std::vector<ServiceWorkerRegistrationInfo>* all_out,
     67     const std::vector<ServiceWorkerRegistrationInfo>& all) {
     68   *was_called = true;
     69   *all_out = all;
     70 }
     71 
     72 ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback(
     73     bool* was_called,
     74     std::vector<ServiceWorkerRegistrationInfo>* all) {
     75   return base::Bind(&GetAllCallback, was_called, all);
     76 }
     77 
     78 void OnIOComplete(int* rv_out, int rv) {
     79   *rv_out = rv;
     80 }
     81 
     82 void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) {
     83   scoped_ptr<ServiceWorkerResponseWriter> writer =
     84       storage->CreateResponseWriter(id);
     85 
     86   const char kHttpHeaders[] =
     87       "HTTP/1.0 200 HONKYDORY\0Content-Length: 6\0\0";
     88   const char kHttpBody[] = "Hello\0";
     89   scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
     90   std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
     91   scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
     92   info->request_time = base::Time::Now();
     93   info->response_time = base::Time::Now();
     94   info->was_cached = false;
     95   info->headers = new net::HttpResponseHeaders(raw_headers);
     96   scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
     97       new HttpResponseInfoIOBuffer(info.release());
     98 
     99   int rv = -1234;
    100   writer->WriteInfo(info_buffer, base::Bind(&OnIOComplete, &rv));
    101   base::RunLoop().RunUntilIdle();
    102   EXPECT_LT(0, rv);
    103 
    104   rv = -1234;
    105   writer->WriteData(body, arraysize(kHttpBody),
    106                     base::Bind(&OnIOComplete, &rv));
    107   base::RunLoop().RunUntilIdle();
    108   EXPECT_EQ(static_cast<int>(arraysize(kHttpBody)), rv);
    109 }
    110 
    111 bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id,
    112                          bool expected_positive_result) {
    113   const char kExpectedHttpBody[] = "Hello\0";
    114   scoped_ptr<ServiceWorkerResponseReader> reader =
    115       storage->CreateResponseReader(id);
    116   scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
    117       new HttpResponseInfoIOBuffer();
    118   int rv = -1234;
    119   reader->ReadInfo(info_buffer, base::Bind(&OnIOComplete, &rv));
    120   base::RunLoop().RunUntilIdle();
    121   if (expected_positive_result)
    122     EXPECT_LT(0, rv);
    123   if (rv <= 0)
    124     return false;
    125 
    126   const int kBigEnough = 512;
    127   scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
    128   rv = -1234;
    129   reader->ReadData(buffer, kBigEnough, base::Bind(&OnIOComplete, &rv));
    130   base::RunLoop().RunUntilIdle();
    131   EXPECT_EQ(static_cast<int>(arraysize(kExpectedHttpBody)), rv);
    132   if (rv <= 0)
    133     return false;
    134 
    135   bool status_match =
    136       std::string("HONKYDORY") ==
    137           info_buffer->http_info->headers->GetStatusText();
    138   bool data_match =
    139       std::string(kExpectedHttpBody) == std::string(buffer->data());
    140 
    141   EXPECT_TRUE(status_match);
    142   EXPECT_TRUE(data_match);
    143   return status_match && data_match;
    144 }
    145 
    146 }  // namespace
    147 
    148 class ServiceWorkerStorageTest : public testing::Test {
    149  public:
    150   ServiceWorkerStorageTest()
    151       : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
    152   }
    153 
    154   virtual void SetUp() OVERRIDE {
    155     context_.reset(
    156         new ServiceWorkerContextCore(base::FilePath(),
    157                                      base::MessageLoopProxy::current(),
    158                                      base::MessageLoopProxy::current(),
    159                                      NULL,
    160                                      NULL,
    161                                      NULL));
    162     context_ptr_ = context_->AsWeakPtr();
    163   }
    164 
    165   virtual void TearDown() OVERRIDE {
    166     context_.reset();
    167   }
    168 
    169   ServiceWorkerStorage* storage() { return context_->storage(); }
    170 
    171   // A static class method for friendliness.
    172   static void VerifyPurgeableListStatusCallback(
    173       ServiceWorkerDatabase* database,
    174       std::set<int64> *purgeable_ids,
    175       bool* was_called,
    176       ServiceWorkerStatusCode* result,
    177       ServiceWorkerStatusCode status) {
    178     *was_called = true;
    179     *result = status;
    180     EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
    181               database->GetPurgeableResourceIds(purgeable_ids));
    182   }
    183 
    184  protected:
    185   ServiceWorkerStatusCode StoreRegistration(
    186       scoped_refptr<ServiceWorkerRegistration> registration,
    187       scoped_refptr<ServiceWorkerVersion> version) {
    188     bool was_called = false;
    189     ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
    190     storage()->StoreRegistration(
    191         registration, version, MakeStatusCallback(&was_called, &result));
    192     EXPECT_FALSE(was_called);  // always async
    193     base::RunLoop().RunUntilIdle();
    194     EXPECT_TRUE(was_called);
    195     return result;
    196   }
    197 
    198   ServiceWorkerStatusCode DeleteRegistration(
    199       int64 registration_id,
    200       const GURL& origin) {
    201     bool was_called = false;
    202     ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
    203     storage()->DeleteRegistration(
    204         registration_id, origin, MakeStatusCallback(&was_called, &result));
    205     EXPECT_FALSE(was_called);  // always async
    206     base::RunLoop().RunUntilIdle();
    207     EXPECT_TRUE(was_called);
    208     return result;
    209   }
    210 
    211   void GetAllRegistrations(
    212       std::vector<ServiceWorkerRegistrationInfo>* registrations) {
    213     bool was_called = false;
    214     storage()->GetAllRegistrations(
    215         MakeGetAllCallback(&was_called, registrations));
    216     EXPECT_FALSE(was_called);  // always async
    217     base::RunLoop().RunUntilIdle();
    218     EXPECT_TRUE(was_called);
    219   }
    220 
    221   ServiceWorkerStatusCode UpdateToActiveState(
    222       scoped_refptr<ServiceWorkerRegistration> registration) {
    223     bool was_called = false;
    224     ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
    225     storage()->UpdateToActiveState(
    226         registration, MakeStatusCallback(&was_called, &result));
    227     EXPECT_FALSE(was_called);  // always async
    228     base::RunLoop().RunUntilIdle();
    229     EXPECT_TRUE(was_called);
    230     return result;
    231   }
    232 
    233   ServiceWorkerStatusCode FindRegistrationForDocument(
    234       const GURL& document_url,
    235       scoped_refptr<ServiceWorkerRegistration>* registration) {
    236     bool was_called = false;
    237     ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
    238     storage()->FindRegistrationForDocument(
    239         document_url, MakeFindCallback(&was_called, &result, registration));
    240     base::RunLoop().RunUntilIdle();
    241     EXPECT_TRUE(was_called);
    242     return result;
    243   }
    244 
    245   ServiceWorkerStatusCode FindRegistrationForPattern(
    246       const GURL& scope,
    247       scoped_refptr<ServiceWorkerRegistration>* registration) {
    248     bool was_called = false;
    249     ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
    250     storage()->FindRegistrationForPattern(
    251         scope, MakeFindCallback(&was_called, &result, registration));
    252     EXPECT_FALSE(was_called);  // always async
    253     base::RunLoop().RunUntilIdle();
    254     EXPECT_TRUE(was_called);
    255     return result;
    256   }
    257 
    258   ServiceWorkerStatusCode FindRegistrationForId(
    259       int64 registration_id,
    260       const GURL& origin,
    261       scoped_refptr<ServiceWorkerRegistration>* registration) {
    262     bool was_called = false;
    263     ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
    264     storage()->FindRegistrationForId(
    265         registration_id, origin,
    266         MakeFindCallback(&was_called, &result, registration));
    267     base::RunLoop().RunUntilIdle();
    268     EXPECT_TRUE(was_called);
    269     return result;
    270   }
    271 
    272   scoped_ptr<ServiceWorkerContextCore> context_;
    273   base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
    274   TestBrowserThreadBundle browser_thread_bundle_;
    275 };
    276 
    277 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
    278   const GURL kScope("http://www.test.not/scope/*");
    279   const GURL kScript("http://www.test.not/script.js");
    280   const GURL kDocumentUrl("http://www.test.not/scope/document.html");
    281   const int64 kRegistrationId = 0;
    282   const int64 kVersionId = 0;
    283 
    284   scoped_refptr<ServiceWorkerRegistration> found_registration;
    285 
    286   // We shouldn't find anything without having stored anything.
    287   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    288             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    289   EXPECT_FALSE(found_registration);
    290 
    291   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    292             FindRegistrationForPattern(kScope, &found_registration));
    293   EXPECT_FALSE(found_registration);
    294 
    295   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    296             FindRegistrationForId(
    297                 kRegistrationId, kScope.GetOrigin(), &found_registration));
    298   EXPECT_FALSE(found_registration);
    299 
    300   // Store something.
    301   scoped_refptr<ServiceWorkerRegistration> live_registration =
    302       new ServiceWorkerRegistration(
    303           kScope, kScript, kRegistrationId, context_ptr_);
    304   scoped_refptr<ServiceWorkerVersion> live_version =
    305       new ServiceWorkerVersion(
    306           live_registration, kVersionId, context_ptr_);
    307   live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
    308   live_registration->set_waiting_version(live_version);
    309   EXPECT_EQ(SERVICE_WORKER_OK,
    310             StoreRegistration(live_registration, live_version));
    311 
    312   // Now we should find it and get the live ptr back immediately.
    313   EXPECT_EQ(SERVICE_WORKER_OK,
    314             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    315   EXPECT_EQ(live_registration, found_registration);
    316   found_registration = NULL;
    317 
    318   // But FindRegistrationForPattern is always async.
    319   EXPECT_EQ(SERVICE_WORKER_OK,
    320             FindRegistrationForPattern(kScope, &found_registration));
    321   EXPECT_EQ(live_registration, found_registration);
    322   found_registration = NULL;
    323 
    324   // Can be found by id too.
    325   EXPECT_EQ(SERVICE_WORKER_OK,
    326             FindRegistrationForId(
    327                 kRegistrationId, kScope.GetOrigin(), &found_registration));
    328   ASSERT_TRUE(found_registration);
    329   EXPECT_EQ(kRegistrationId, found_registration->id());
    330   EXPECT_EQ(live_registration, found_registration);
    331   found_registration = NULL;
    332 
    333   // Drop the live registration, but keep the version live.
    334   live_registration = NULL;
    335 
    336   // Now FindRegistrationForDocument should be async.
    337   EXPECT_EQ(SERVICE_WORKER_OK,
    338             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    339   ASSERT_TRUE(found_registration);
    340   EXPECT_EQ(kRegistrationId, found_registration->id());
    341   EXPECT_TRUE(found_registration->HasOneRef());
    342   EXPECT_EQ(live_version, found_registration->waiting_version());
    343   found_registration = NULL;
    344 
    345   // Drop the live version too.
    346   live_version = NULL;
    347 
    348   // And FindRegistrationForPattern is always async.
    349   EXPECT_EQ(SERVICE_WORKER_OK,
    350             FindRegistrationForPattern(kScope, &found_registration));
    351   ASSERT_TRUE(found_registration);
    352   EXPECT_EQ(kRegistrationId, found_registration->id());
    353   EXPECT_TRUE(found_registration->HasOneRef());
    354   EXPECT_FALSE(found_registration->active_version());
    355   ASSERT_TRUE(found_registration->waiting_version());
    356   EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
    357             found_registration->waiting_version()->status());
    358 
    359   // Update to active.
    360   scoped_refptr<ServiceWorkerVersion> temp_version =
    361       found_registration->waiting_version();
    362   found_registration->set_waiting_version(NULL);
    363   temp_version->SetStatus(ServiceWorkerVersion::ACTIVE);
    364   found_registration->set_active_version(temp_version);
    365   temp_version = NULL;
    366   EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration));
    367   found_registration = NULL;
    368 
    369   // Trying to update a unstored registration to active should fail.
    370   scoped_refptr<ServiceWorkerRegistration> unstored_registration =
    371       new ServiceWorkerRegistration(
    372           kScope, kScript, kRegistrationId + 1, context_ptr_);
    373   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    374             UpdateToActiveState(unstored_registration));
    375   unstored_registration = NULL;
    376 
    377   // The Find methods should return a registration with an active version.
    378   EXPECT_EQ(SERVICE_WORKER_OK,
    379             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    380   ASSERT_TRUE(found_registration);
    381   EXPECT_EQ(kRegistrationId, found_registration->id());
    382   EXPECT_TRUE(found_registration->HasOneRef());
    383   EXPECT_FALSE(found_registration->waiting_version());
    384   ASSERT_TRUE(found_registration->active_version());
    385   EXPECT_EQ(ServiceWorkerVersion::ACTIVE,
    386             found_registration->active_version()->status());
    387 
    388   // Delete from storage but with a instance still live.
    389   EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
    390   EXPECT_EQ(SERVICE_WORKER_OK,
    391             DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
    392   EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
    393 
    394   // Should no longer be found.
    395   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    396             FindRegistrationForId(
    397                 kRegistrationId, kScope.GetOrigin(), &found_registration));
    398   EXPECT_FALSE(found_registration);
    399 
    400   // Deleting an unstored registration should succeed.
    401   EXPECT_EQ(SERVICE_WORKER_OK,
    402             DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
    403 }
    404 
    405 TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
    406   const GURL kScope("http://www.test.not/scope/*");
    407   const GURL kScript("http://www.test.not/script.js");
    408   const GURL kDocumentUrl("http://www.test.not/scope/document.html");
    409   const int64 kRegistrationId = 0;
    410   const int64 kVersionId = 0;
    411 
    412   scoped_refptr<ServiceWorkerRegistration> found_registration;
    413 
    414   // Create an unstored registration.
    415   scoped_refptr<ServiceWorkerRegistration> live_registration =
    416       new ServiceWorkerRegistration(
    417           kScope, kScript, kRegistrationId, context_ptr_);
    418   scoped_refptr<ServiceWorkerVersion> live_version =
    419       new ServiceWorkerVersion(
    420           live_registration, kVersionId, context_ptr_);
    421   live_version->SetStatus(ServiceWorkerVersion::INSTALLING);
    422   live_registration->set_waiting_version(live_version);
    423 
    424   // Should not be findable, including by GetAllRegistrations.
    425   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    426             FindRegistrationForId(
    427                 kRegistrationId, kScope.GetOrigin(), &found_registration));
    428   EXPECT_FALSE(found_registration);
    429 
    430   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    431             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    432   EXPECT_FALSE(found_registration);
    433 
    434   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    435             FindRegistrationForPattern(kScope, &found_registration));
    436   EXPECT_FALSE(found_registration);
    437 
    438   std::vector<ServiceWorkerRegistrationInfo> all_registrations;
    439   GetAllRegistrations(&all_registrations);
    440   EXPECT_TRUE(all_registrations.empty());
    441 
    442   // Notify storage of it being installed.
    443   storage()->NotifyInstallingRegistration(live_registration);
    444 
    445   // Now should be findable.
    446   EXPECT_EQ(SERVICE_WORKER_OK,
    447             FindRegistrationForId(
    448                 kRegistrationId, kScope.GetOrigin(), &found_registration));
    449   EXPECT_EQ(live_registration, found_registration);
    450   found_registration = NULL;
    451 
    452   EXPECT_EQ(SERVICE_WORKER_OK,
    453             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    454   EXPECT_EQ(live_registration, found_registration);
    455   found_registration = NULL;
    456 
    457   EXPECT_EQ(SERVICE_WORKER_OK,
    458             FindRegistrationForPattern(kScope, &found_registration));
    459   EXPECT_EQ(live_registration, found_registration);
    460   found_registration = NULL;
    461 
    462   GetAllRegistrations(&all_registrations);
    463   EXPECT_EQ(1u, all_registrations.size());
    464   all_registrations.clear();
    465 
    466   // Notify storage of installation no longer happening.
    467   storage()->NotifyDoneInstallingRegistration(
    468       live_registration, NULL, SERVICE_WORKER_OK);
    469 
    470   // Once again, should not be findable.
    471   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    472             FindRegistrationForId(
    473                 kRegistrationId, kScope.GetOrigin(), &found_registration));
    474   EXPECT_FALSE(found_registration);
    475 
    476   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    477             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    478   EXPECT_FALSE(found_registration);
    479 
    480   EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
    481             FindRegistrationForPattern(kScope, &found_registration));
    482   EXPECT_FALSE(found_registration);
    483 
    484   GetAllRegistrations(&all_registrations);
    485   EXPECT_TRUE(all_registrations.empty());
    486 }
    487 
    488 TEST_F(ServiceWorkerStorageTest, ResourceIdsAreStoredAndPurged) {
    489   storage()->LazyInitialize(base::Bind(&base::DoNothing));
    490   base::RunLoop().RunUntilIdle();
    491   const GURL kScope("http://www.test.not/scope/*");
    492   const GURL kScript("http://www.test.not/script.js");
    493   const GURL kImport("http://www.test.not/import.js");
    494   const GURL kDocumentUrl("http://www.test.not/scope/document.html");
    495   const int64 kRegistrationId = storage()->NewRegistrationId();
    496   const int64 kVersionId = storage()->NewVersionId();
    497   const int64 kResourceId1 = storage()->NewResourceId();
    498   const int64 kResourceId2 = storage()->NewResourceId();
    499 
    500   // Cons up a new registration+version with two script resources.
    501   RegistrationData data;
    502   data.registration_id = kRegistrationId;
    503   data.scope = kScope;
    504   data.script = kScript;
    505   data.version_id = kVersionId;
    506   data.is_active = false;
    507   std::vector<ResourceRecord> resources;
    508   resources.push_back(ResourceRecord(kResourceId1, kScript));
    509   resources.push_back(ResourceRecord(kResourceId2, kImport));
    510   scoped_refptr<ServiceWorkerRegistration> registration =
    511       storage()->GetOrCreateRegistration(data, resources);
    512   registration->waiting_version()->SetStatus(ServiceWorkerVersion::NEW);
    513 
    514   // Add the resources ids to the uncommitted list.
    515   std::set<int64> resource_ids;
    516   resource_ids.insert(kResourceId1);
    517   resource_ids.insert(kResourceId2);
    518   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
    519             storage()->database_->WriteUncommittedResourceIds(resource_ids));
    520 
    521   // And dump something in the disk cache for them.
    522   WriteBasicResponse(storage(), kResourceId1);
    523   WriteBasicResponse(storage(), kResourceId2);
    524   EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId1, true));
    525   EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId2, true));
    526 
    527   // Storing the registration/version should take the resources ids out
    528   // of the uncommitted list.
    529   EXPECT_EQ(SERVICE_WORKER_OK,
    530             StoreRegistration(registration, registration->waiting_version()));
    531   std::set<int64> verify_ids;
    532   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
    533             storage()->database_->GetUncommittedResourceIds(&verify_ids));
    534   EXPECT_TRUE(verify_ids.empty());
    535 
    536   // Deleting it should result in the resources being added to the
    537   // purgeable list and then doomed in the disk cache and removed from
    538   // that list.
    539   bool was_called = false;
    540   ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
    541   verify_ids.clear();
    542   storage()->DeleteRegistration(
    543       registration->id(), kScope.GetOrigin(),
    544       base::Bind(&VerifyPurgeableListStatusCallback,
    545                  base::Unretained(storage()->database_.get()),
    546                  &verify_ids, &was_called, &result));
    547   base::RunLoop().RunUntilIdle();
    548   ASSERT_TRUE(was_called);
    549   EXPECT_EQ(SERVICE_WORKER_OK, result);
    550   EXPECT_EQ(2u, verify_ids.size());
    551   verify_ids.clear();
    552   EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
    553             storage()->database_->GetPurgeableResourceIds(&verify_ids));
    554   EXPECT_TRUE(verify_ids.empty());
    555 
    556   EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId1, false));
    557   EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId2, false));
    558 }
    559 
    560 TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
    561   const GURL kDocumentUrl("http://www.example.com/scope/foo");
    562   scoped_refptr<ServiceWorkerRegistration> found_registration;
    563 
    564   // Registration for "/scope/*".
    565   const GURL kScope1("http://www.example.com/scope/*");
    566   const GURL kScript1("http://www.example.com/script1.js");
    567   const int64 kRegistrationId1 = 1;
    568   const int64 kVersionId1 = 1;
    569   scoped_refptr<ServiceWorkerRegistration> live_registration1 =
    570       new ServiceWorkerRegistration(
    571           kScope1, kScript1, kRegistrationId1, context_ptr_);
    572   scoped_refptr<ServiceWorkerVersion> live_version1 =
    573       new ServiceWorkerVersion(
    574           live_registration1, kVersionId1, context_ptr_);
    575   live_version1->SetStatus(ServiceWorkerVersion::INSTALLED);
    576   live_registration1->set_waiting_version(live_version1);
    577 
    578   // Registration for "/scope/foo*".
    579   const GURL kScope2("http://www.example.com/scope/foo*");
    580   const GURL kScript2("http://www.example.com/script2.js");
    581   const int64 kRegistrationId2 = 2;
    582   const int64 kVersionId2 = 2;
    583   scoped_refptr<ServiceWorkerRegistration> live_registration2 =
    584       new ServiceWorkerRegistration(
    585           kScope2, kScript2, kRegistrationId2, context_ptr_);
    586   scoped_refptr<ServiceWorkerVersion> live_version2 =
    587       new ServiceWorkerVersion(
    588           live_registration2, kVersionId2, context_ptr_);
    589   live_version2->SetStatus(ServiceWorkerVersion::INSTALLED);
    590   live_registration2->set_waiting_version(live_version2);
    591 
    592   // Registration for "/scope/foo".
    593   const GURL kScope3("http://www.example.com/scope/foo");
    594   const GURL kScript3("http://www.example.com/script3.js");
    595   const int64 kRegistrationId3 = 3;
    596   const int64 kVersionId3 = 3;
    597   scoped_refptr<ServiceWorkerRegistration> live_registration3 =
    598       new ServiceWorkerRegistration(
    599           kScope3, kScript3, kRegistrationId3, context_ptr_);
    600   scoped_refptr<ServiceWorkerVersion> live_version3 =
    601       new ServiceWorkerVersion(
    602           live_registration3, kVersionId3, context_ptr_);
    603   live_version3->SetStatus(ServiceWorkerVersion::INSTALLED);
    604   live_registration3->set_waiting_version(live_version3);
    605 
    606   // Notify storage of they being installed.
    607   storage()->NotifyInstallingRegistration(live_registration1);
    608   storage()->NotifyInstallingRegistration(live_registration2);
    609   storage()->NotifyInstallingRegistration(live_registration3);
    610 
    611   // Find a registration among installing ones.
    612   EXPECT_EQ(SERVICE_WORKER_OK,
    613             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    614   EXPECT_EQ(live_registration2, found_registration);
    615   found_registration = NULL;
    616 
    617   // Store registrations.
    618   EXPECT_EQ(SERVICE_WORKER_OK,
    619             StoreRegistration(live_registration1, live_version1));
    620   EXPECT_EQ(SERVICE_WORKER_OK,
    621             StoreRegistration(live_registration2, live_version2));
    622   EXPECT_EQ(SERVICE_WORKER_OK,
    623             StoreRegistration(live_registration3, live_version3));
    624 
    625   // Notify storage of installations no longer happening.
    626   storage()->NotifyDoneInstallingRegistration(
    627       live_registration1, NULL, SERVICE_WORKER_OK);
    628   storage()->NotifyDoneInstallingRegistration(
    629       live_registration2, NULL, SERVICE_WORKER_OK);
    630   storage()->NotifyDoneInstallingRegistration(
    631       live_registration3, NULL, SERVICE_WORKER_OK);
    632 
    633   // Find a registration among installed ones.
    634   EXPECT_EQ(SERVICE_WORKER_OK,
    635             FindRegistrationForDocument(kDocumentUrl, &found_registration));
    636   EXPECT_EQ(live_registration2, found_registration);
    637 }
    638 
    639 }  // namespace content
    640