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 #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
      6 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
      7 
      8 #include <deque>
      9 #include <map>
     10 #include <set>
     11 #include <vector>
     12 
     13 #include "base/bind.h"
     14 #include "base/files/file_path.h"
     15 #include "base/gtest_prod_util.h"
     16 #include "base/memory/scoped_vector.h"
     17 #include "base/memory/weak_ptr.h"
     18 #include "content/browser/service_worker/service_worker_database.h"
     19 #include "content/browser/service_worker/service_worker_version.h"
     20 #include "content/common/content_export.h"
     21 #include "content/common/service_worker/service_worker_status_code.h"
     22 #include "url/gurl.h"
     23 
     24 namespace base {
     25 class SequencedTaskRunner;
     26 class SingleThreadTaskRunner;
     27 }
     28 
     29 namespace storage {
     30 class QuotaManagerProxy;
     31 }
     32 
     33 namespace content {
     34 
     35 class ServiceWorkerContextCore;
     36 class ServiceWorkerDiskCache;
     37 class ServiceWorkerRegistration;
     38 class ServiceWorkerRegistrationInfo;
     39 class ServiceWorkerResponseReader;
     40 class ServiceWorkerResponseWriter;
     41 
     42 // This class provides an interface to store and retrieve ServiceWorker
     43 // registration data.
     44 class CONTENT_EXPORT ServiceWorkerStorage
     45     : NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
     46  public:
     47   typedef std::vector<ServiceWorkerDatabase::ResourceRecord> ResourceList;
     48   typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback;
     49   typedef base::Callback<void(ServiceWorkerStatusCode status,
     50                               const scoped_refptr<ServiceWorkerRegistration>&
     51                                   registration)> FindRegistrationCallback;
     52   typedef base::Callback<
     53       void(const std::vector<ServiceWorkerRegistrationInfo>& registrations)>
     54           GetAllRegistrationInfosCallback;
     55   typedef base::Callback<
     56       void(ServiceWorkerStatusCode status, bool are_equal)>
     57           CompareCallback;
     58 
     59   virtual ~ServiceWorkerStorage();
     60 
     61   static scoped_ptr<ServiceWorkerStorage> Create(
     62       const base::FilePath& path,
     63       base::WeakPtr<ServiceWorkerContextCore> context,
     64       const scoped_refptr<base::SequencedTaskRunner>& database_task_runner,
     65       const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
     66       storage::QuotaManagerProxy* quota_manager_proxy);
     67 
     68   // Used for DeleteAndStartOver. Creates new storage based on |old_storage|.
     69   static scoped_ptr<ServiceWorkerStorage> Create(
     70       base::WeakPtr<ServiceWorkerContextCore> context,
     71       ServiceWorkerStorage* old_storage);
     72 
     73   // Finds registration for |document_url| or |pattern| or |registration_id|.
     74   // The Find methods will find stored and initially installing registrations.
     75   // Returns SERVICE_WORKER_OK with non-null registration if registration
     76   // is found, or returns SERVICE_WORKER_ERROR_NOT_FOUND if no matching
     77   // registration is found.  The FindRegistrationForPattern method is
     78   // guaranteed to return asynchronously. However, the methods to find
     79   // for |document_url| or |registration_id| may complete immediately
     80   // (the callback may be called prior to the method returning) or
     81   // asynchronously.
     82   void FindRegistrationForDocument(const GURL& document_url,
     83                                    const FindRegistrationCallback& callback);
     84   void FindRegistrationForPattern(const GURL& scope,
     85                                   const FindRegistrationCallback& callback);
     86   void FindRegistrationForId(int64 registration_id,
     87                              const GURL& origin,
     88                              const FindRegistrationCallback& callback);
     89 
     90   ServiceWorkerRegistration* GetUninstallingRegistration(const GURL& scope);
     91 
     92   // Returns info about all stored and initially installing registrations.
     93   void GetAllRegistrations(const GetAllRegistrationInfosCallback& callback);
     94 
     95   // Commits |registration| with the installed but not activated |version|
     96   // to storage, overwritting any pre-existing registration data for the scope.
     97   // A pre-existing version's script resources remain available if that version
     98   // is live. PurgeResources should be called when it's OK to delete them.
     99   void StoreRegistration(
    100       ServiceWorkerRegistration* registration,
    101       ServiceWorkerVersion* version,
    102       const StatusCallback& callback);
    103 
    104   // Updates the state of the registration's stored version to active.
    105   void UpdateToActiveState(
    106       ServiceWorkerRegistration* registration,
    107       const StatusCallback& callback);
    108 
    109   // Updates the stored time to match the value of
    110   // registration->last_update_check().
    111   void UpdateLastUpdateCheckTime(ServiceWorkerRegistration* registration);
    112 
    113   // Deletes the registration data for |registration_id|. If the registration's
    114   // version is live, its script resources will remain available.
    115   // PurgeResources should be called when it's OK to delete them.
    116   void DeleteRegistration(int64 registration_id,
    117                           const GURL& origin,
    118                           const StatusCallback& callback);
    119 
    120   scoped_ptr<ServiceWorkerResponseReader> CreateResponseReader(
    121       int64 response_id);
    122   scoped_ptr<ServiceWorkerResponseWriter> CreateResponseWriter(
    123       int64 response_id);
    124 
    125   // Adds |id| to the set of resources ids that are in the disk
    126   // cache but not yet stored with a registration.
    127   void StoreUncommittedResponseId(int64 id);
    128 
    129   // Removes |id| from uncommitted list, adds it to the
    130   // purgeable list and purges it.
    131   void DoomUncommittedResponse(int64 id);
    132 
    133   // Compares only the response bodies.
    134   void CompareScriptResources(int64 lhs_id, int64 rhs_id,
    135                               const CompareCallback& callback);
    136 
    137   // Deletes the storage and starts over.
    138   void DeleteAndStartOver(const StatusCallback& callback);
    139 
    140   // Returns new IDs which are guaranteed to be unique in the storage.
    141   int64 NewRegistrationId();
    142   int64 NewVersionId();
    143   int64 NewResourceId();
    144 
    145   // Intended for use only by ServiceWorkerRegisterJob and
    146   // ServiceWorkerRegistration.
    147   void NotifyInstallingRegistration(
    148       ServiceWorkerRegistration* registration);
    149   void NotifyDoneInstallingRegistration(
    150       ServiceWorkerRegistration* registration,
    151       ServiceWorkerVersion* version,
    152       ServiceWorkerStatusCode status);
    153   void NotifyUninstallingRegistration(ServiceWorkerRegistration* registration);
    154   void NotifyDoneUninstallingRegistration(
    155       ServiceWorkerRegistration* registration);
    156 
    157   void Disable();
    158   bool IsDisabled() const;
    159 
    160   // |resources| must already be on the purgeable list.
    161   void PurgeResources(const ResourceList& resources);
    162 
    163  private:
    164   friend class ServiceWorkerResourceStorageTest;
    165   friend class ServiceWorkerControlleeRequestHandlerTest;
    166   friend class ServiceWorkerContextRequestHandlerTest;
    167   friend class ServiceWorkerRequestHandlerTest;
    168   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
    169                            DeleteRegistration_NoLiveVersion);
    170   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
    171                            DeleteRegistration_WaitingVersion);
    172   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
    173                            DeleteRegistration_ActiveVersion);
    174   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
    175                            UpdateRegistration);
    176   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageDiskTest,
    177                            CleanupOnRestart);
    178 
    179   struct InitialData {
    180     int64 next_registration_id;
    181     int64 next_version_id;
    182     int64 next_resource_id;
    183     std::set<GURL> origins;
    184 
    185     InitialData();
    186     ~InitialData();
    187   };
    188 
    189   // Because there are too many params for base::Bind to wrap a closure around.
    190   struct DidDeleteRegistrationParams {
    191     int64 registration_id;
    192     GURL origin;
    193     StatusCallback callback;
    194 
    195     DidDeleteRegistrationParams();
    196     ~DidDeleteRegistrationParams();
    197   };
    198 
    199   typedef std::vector<ServiceWorkerDatabase::RegistrationData> RegistrationList;
    200   typedef std::map<int64, scoped_refptr<ServiceWorkerRegistration> >
    201       RegistrationRefsById;
    202   typedef base::Callback<void(
    203       InitialData* data,
    204       ServiceWorkerDatabase::Status status)> InitializeCallback;
    205   typedef base::Callback<
    206       void(const GURL& origin,
    207            int64 deleted_version_id,
    208            const std::vector<int64>& newly_purgeable_resources,
    209            ServiceWorkerDatabase::Status status)> WriteRegistrationCallback;
    210   typedef base::Callback<
    211       void(bool origin_is_deletable,
    212            int64 version_id,
    213            const std::vector<int64>& newly_purgeable_resources,
    214            ServiceWorkerDatabase::Status status)> DeleteRegistrationCallback;
    215   typedef base::Callback<void(
    216       const ServiceWorkerDatabase::RegistrationData& data,
    217       const ResourceList& resources,
    218       ServiceWorkerDatabase::Status status)> FindInDBCallback;
    219   typedef base::Callback<void(const std::vector<int64>& resource_ids,
    220                               ServiceWorkerDatabase::Status status)>
    221       GetResourcesCallback;
    222 
    223   ServiceWorkerStorage(
    224       const base::FilePath& path,
    225       base::WeakPtr<ServiceWorkerContextCore> context,
    226       const scoped_refptr<base::SequencedTaskRunner>& database_task_runner,
    227       const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
    228       storage::QuotaManagerProxy* quota_manager_proxy);
    229 
    230   base::FilePath GetDatabasePath();
    231   base::FilePath GetDiskCachePath();
    232 
    233   bool LazyInitialize(
    234       const base::Closure& callback);
    235   void DidReadInitialData(
    236       InitialData* data,
    237       ServiceWorkerDatabase::Status status);
    238   void DidFindRegistrationForDocument(
    239       const GURL& document_url,
    240       const FindRegistrationCallback& callback,
    241       const ServiceWorkerDatabase::RegistrationData& data,
    242       const ResourceList& resources,
    243       ServiceWorkerDatabase::Status status);
    244   void DidFindRegistrationForPattern(
    245       const GURL& scope,
    246       const FindRegistrationCallback& callback,
    247       const ServiceWorkerDatabase::RegistrationData& data,
    248       const ResourceList& resources,
    249       ServiceWorkerDatabase::Status status);
    250   void DidFindRegistrationForId(
    251       const FindRegistrationCallback& callback,
    252       const ServiceWorkerDatabase::RegistrationData& data,
    253       const ResourceList& resources,
    254       ServiceWorkerDatabase::Status status);
    255   void DidGetAllRegistrations(
    256       const GetAllRegistrationInfosCallback& callback,
    257       RegistrationList* registrations,
    258       ServiceWorkerDatabase::Status status);
    259   void DidStoreRegistration(const StatusCallback& callback,
    260                             const GURL& origin,
    261                             int64 deleted_version_id,
    262                             const std::vector<int64>& newly_purgeable_resources,
    263                             ServiceWorkerDatabase::Status status);
    264   void DidUpdateToActiveState(
    265       const StatusCallback& callback,
    266       ServiceWorkerDatabase::Status status);
    267   void DidDeleteRegistration(
    268       const DidDeleteRegistrationParams& params,
    269       bool origin_is_deletable,
    270       int64 version_id,
    271       const std::vector<int64>& newly_purgeable_resources,
    272       ServiceWorkerDatabase::Status status);
    273   void ReturnFoundRegistration(
    274       const FindRegistrationCallback& callback,
    275       const ServiceWorkerDatabase::RegistrationData& data,
    276       const ResourceList& resources);
    277 
    278   scoped_refptr<ServiceWorkerRegistration> GetOrCreateRegistration(
    279       const ServiceWorkerDatabase::RegistrationData& data,
    280       const ResourceList& resources);
    281   ServiceWorkerRegistration* FindInstallingRegistrationForDocument(
    282       const GURL& document_url);
    283   ServiceWorkerRegistration* FindInstallingRegistrationForPattern(
    284       const GURL& scope);
    285   ServiceWorkerRegistration* FindInstallingRegistrationForId(
    286       int64 registration_id);
    287 
    288   // Lazy disk_cache getter.
    289   ServiceWorkerDiskCache* disk_cache();
    290   void OnDiskCacheInitialized(int rv);
    291 
    292   void StartPurgingResources(const std::vector<int64>& ids);
    293   void StartPurgingResources(const ResourceList& resources);
    294   void ContinuePurgingResources();
    295   void PurgeResource(int64 id);
    296   void OnResourcePurged(int64 id, int rv);
    297 
    298   // Deletes purgeable and uncommitted resources left over from the previous
    299   // browser session. This must be called once per session before any database
    300   // operation that may mutate the purgeable or uncommitted resource lists.
    301   void DeleteStaleResources();
    302   void DidCollectStaleResources(const std::vector<int64>& stale_resource_ids,
    303                                 ServiceWorkerDatabase::Status status);
    304 
    305   // Static cross-thread helpers.
    306   static void CollectStaleResourcesFromDB(
    307       ServiceWorkerDatabase* database,
    308       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
    309       const GetResourcesCallback& callback);
    310   static void ReadInitialDataFromDB(
    311       ServiceWorkerDatabase* database,
    312       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
    313       const InitializeCallback& callback);
    314   static void DeleteRegistrationFromDB(
    315       ServiceWorkerDatabase* database,
    316       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
    317       int64 registration_id,
    318       const GURL& origin,
    319       const DeleteRegistrationCallback& callback);
    320   static void WriteRegistrationInDB(
    321       ServiceWorkerDatabase* database,
    322       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
    323       const ServiceWorkerDatabase::RegistrationData& registration,
    324       const ResourceList& resources,
    325       const WriteRegistrationCallback& callback);
    326   static void FindForDocumentInDB(
    327       ServiceWorkerDatabase* database,
    328       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
    329       const GURL& document_url,
    330       const FindInDBCallback& callback);
    331   static void FindForPatternInDB(
    332       ServiceWorkerDatabase* database,
    333       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
    334       const GURL& scope,
    335       const FindInDBCallback& callback);
    336   static void FindForIdInDB(
    337       ServiceWorkerDatabase* database,
    338       scoped_refptr<base::SequencedTaskRunner> original_task_runner,
    339       int64 registration_id,
    340       const GURL& origin,
    341       const FindInDBCallback& callback);
    342 
    343   void ScheduleDeleteAndStartOver();
    344   void DidDeleteDatabase(
    345       const StatusCallback& callback,
    346       ServiceWorkerDatabase::Status status);
    347   void DidDeleteDiskCache(
    348       const StatusCallback& callback,
    349       bool result);
    350 
    351   // For finding registrations being installed or uninstalled.
    352   RegistrationRefsById installing_registrations_;
    353   RegistrationRefsById uninstalling_registrations_;
    354 
    355   // Origins having registations.
    356   std::set<GURL> registered_origins_;
    357 
    358   // Pending database tasks waiting for initialization.
    359   std::vector<base::Closure> pending_tasks_;
    360 
    361   int64 next_registration_id_;
    362   int64 next_version_id_;
    363   int64 next_resource_id_;
    364 
    365   enum State {
    366     UNINITIALIZED,
    367     INITIALIZING,
    368     INITIALIZED,
    369     DISABLED,
    370   };
    371   State state_;
    372 
    373   base::FilePath path_;
    374   base::WeakPtr<ServiceWorkerContextCore> context_;
    375 
    376   // Only accessed on |database_task_runner_|.
    377   scoped_ptr<ServiceWorkerDatabase> database_;
    378 
    379   scoped_refptr<base::SequencedTaskRunner> database_task_runner_;
    380   scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread_;
    381   scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
    382   scoped_ptr<ServiceWorkerDiskCache> disk_cache_;
    383   std::deque<int64> purgeable_resource_ids_;
    384   bool is_purge_pending_;
    385   bool has_checked_for_stale_resources_;
    386   std::set<int64> pending_deletions_;
    387 
    388   base::WeakPtrFactory<ServiceWorkerStorage> weak_factory_;
    389 
    390   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStorage);
    391 };
    392 
    393 }  // namespace content
    394 
    395 #endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
    396