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/common/content_export.h" 20 #include "content/common/service_worker/service_worker_status_code.h" 21 #include "url/gurl.h" 22 23 namespace base { 24 class MessageLoopProxy; 25 class SequencedTaskRunner; 26 } 27 28 namespace quota { 29 class QuotaManagerProxy; 30 } 31 32 namespace content { 33 34 class ServiceWorkerContextCore; 35 class ServiceWorkerDiskCache; 36 class ServiceWorkerRegistration; 37 class ServiceWorkerRegistrationInfo; 38 class ServiceWorkerResponseReader; 39 class ServiceWorkerResponseWriter; 40 class ServiceWorkerVersion; 41 42 // This class provides an interface to store and retrieve ServiceWorker 43 // registration data. 44 class CONTENT_EXPORT ServiceWorkerStorage { 45 public: 46 typedef std::vector<ServiceWorkerDatabase::ResourceRecord> ResourceList; 47 typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback; 48 typedef base::Callback<void(ServiceWorkerStatusCode status, 49 const scoped_refptr<ServiceWorkerRegistration>& 50 registration)> FindRegistrationCallback; 51 typedef base::Callback< 52 void(const std::vector<ServiceWorkerRegistrationInfo>& registrations)> 53 GetAllRegistrationInfosCallback; 54 typedef base::Callback< 55 void(ServiceWorkerStatusCode status, int result)> 56 CompareCallback; 57 58 ServiceWorkerStorage(const base::FilePath& path, 59 base::WeakPtr<ServiceWorkerContextCore> context, 60 base::SequencedTaskRunner* database_task_runner, 61 base::MessageLoopProxy* disk_cache_thread, 62 quota::QuotaManagerProxy* quota_manager_proxy); 63 ~ServiceWorkerStorage(); 64 65 // Finds registration for |document_url| or |pattern| or |registration_id|. 66 // The Find methods will find stored and initially installing registrations. 67 // Returns SERVICE_WORKER_OK with non-null registration if registration 68 // is found, or returns SERVICE_WORKER_ERROR_NOT_FOUND if no matching 69 // registration is found. The FindRegistrationForPattern method is 70 // guaranteed to return asynchronously. However, the methods to find 71 // for |document_url| or |registration_id| may complete immediately 72 // (the callback may be called prior to the method returning) or 73 // asynchronously. 74 void FindRegistrationForDocument(const GURL& document_url, 75 const FindRegistrationCallback& callback); 76 void FindRegistrationForPattern(const GURL& scope, 77 const FindRegistrationCallback& callback); 78 void FindRegistrationForId(int64 registration_id, 79 const GURL& origin, 80 const FindRegistrationCallback& callback); 81 82 // Returns info about all stored and initially installing registrations. 83 void GetAllRegistrations(const GetAllRegistrationInfosCallback& callback); 84 85 // Commits |registration| with the installed but not activated |version| 86 // to storage, overwritting any pre-existing registration data for the scope. 87 // A pre-existing version's script resources will remain available until 88 // either a browser restart or DeleteVersionResources is called. 89 void StoreRegistration( 90 ServiceWorkerRegistration* registration, 91 ServiceWorkerVersion* version, 92 const StatusCallback& callback); 93 94 // Updates the state of the registration's stored version to active. 95 void UpdateToActiveState( 96 ServiceWorkerRegistration* registration, 97 const StatusCallback& callback); 98 99 // Deletes the registration data for |registration_id|, the 100 // script resources for the registration's stored version 101 // will remain available until either a browser restart or 102 // DeleteVersionResources is called. 103 void DeleteRegistration(int64 registration_id, 104 const GURL& origin, 105 const StatusCallback& callback); 106 107 scoped_ptr<ServiceWorkerResponseReader> CreateResponseReader( 108 int64 response_id); 109 scoped_ptr<ServiceWorkerResponseWriter> CreateResponseWriter( 110 int64 response_id); 111 112 // Adds |id| to the set of resources ids that are in the disk 113 // cache but not yet stored with a registration. 114 void StoreUncommittedReponseId(int64 id); 115 116 // Removes |id| from uncommitted list, adds it to the 117 // purgeable list and purges it. 118 void DoomUncommittedResponse(int64 id); 119 120 // Returns new IDs which are guaranteed to be unique in the storage. 121 int64 NewRegistrationId(); 122 int64 NewVersionId(); 123 int64 NewResourceId(); 124 125 // Intended for use only by ServiceWorkerRegisterJob. 126 void NotifyInstallingRegistration( 127 ServiceWorkerRegistration* registration); 128 void NotifyDoneInstallingRegistration( 129 ServiceWorkerRegistration* registration, 130 ServiceWorkerVersion* version, 131 ServiceWorkerStatusCode status); 132 133 private: 134 friend class ServiceWorkerStorageTest; 135 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStorageTest, 136 ResourceIdsAreStoredAndPurged); 137 138 struct InitialData { 139 int64 next_registration_id; 140 int64 next_version_id; 141 int64 next_resource_id; 142 std::set<GURL> origins; 143 144 InitialData(); 145 ~InitialData(); 146 }; 147 148 typedef std::vector<ServiceWorkerDatabase::RegistrationData> RegistrationList; 149 typedef std::map<int64, scoped_refptr<ServiceWorkerRegistration> > 150 RegistrationRefsById; 151 typedef base::Callback<void( 152 InitialData* data, 153 ServiceWorkerDatabase::Status status)> InitializeCallback; 154 typedef base::Callback<void( 155 const GURL& origin, 156 const std::vector<int64>& newly_purgeable_resources, 157 ServiceWorkerDatabase::Status status)> WriteRegistrationCallback; 158 typedef base::Callback<void( 159 bool origin_is_deletable, 160 const std::vector<int64>& newly_purgeable_resources, 161 ServiceWorkerDatabase::Status status)> DeleteRegistrationCallback; 162 typedef base::Callback<void( 163 const ServiceWorkerDatabase::RegistrationData& data, 164 const ResourceList& resources, 165 ServiceWorkerDatabase::Status status)> FindInDBCallback; 166 167 base::FilePath GetDatabasePath(); 168 base::FilePath GetDiskCachePath(); 169 170 bool LazyInitialize( 171 const base::Closure& callback); 172 void DidReadInitialData( 173 InitialData* data, 174 ServiceWorkerDatabase::Status status); 175 void DidFindRegistrationForDocument( 176 const GURL& document_url, 177 const FindRegistrationCallback& callback, 178 const ServiceWorkerDatabase::RegistrationData& data, 179 const ResourceList& resources, 180 ServiceWorkerDatabase::Status status); 181 void DidFindRegistrationForPattern( 182 const GURL& scope, 183 const FindRegistrationCallback& callback, 184 const ServiceWorkerDatabase::RegistrationData& data, 185 const ResourceList& resources, 186 ServiceWorkerDatabase::Status status); 187 void DidFindRegistrationForId( 188 const FindRegistrationCallback& callback, 189 const ServiceWorkerDatabase::RegistrationData& data, 190 const ResourceList& resources, 191 ServiceWorkerDatabase::Status status); 192 void DidGetAllRegistrations( 193 const GetAllRegistrationInfosCallback& callback, 194 RegistrationList* registrations, 195 ServiceWorkerDatabase::Status status); 196 void DidStoreRegistration( 197 const StatusCallback& callback, 198 const GURL& origin, 199 const std::vector<int64>& newly_purgeable_resources, 200 ServiceWorkerDatabase::Status status); 201 void DidUpdateToActiveState( 202 const StatusCallback& callback, 203 ServiceWorkerDatabase::Status status); 204 void DidDeleteRegistration( 205 const GURL& origin, 206 const StatusCallback& callback, 207 bool origin_is_deletable, 208 const std::vector<int64>& newly_purgeable_resources, 209 ServiceWorkerDatabase::Status status); 210 211 scoped_refptr<ServiceWorkerRegistration> GetOrCreateRegistration( 212 const ServiceWorkerDatabase::RegistrationData& data, 213 const ResourceList& resources); 214 ServiceWorkerRegistration* FindInstallingRegistrationForDocument( 215 const GURL& document_url); 216 ServiceWorkerRegistration* FindInstallingRegistrationForPattern( 217 const GURL& scope); 218 ServiceWorkerRegistration* FindInstallingRegistrationForId( 219 int64 registration_id); 220 221 // Lazy disk_cache getter. 222 ServiceWorkerDiskCache* disk_cache(); 223 void OnDiskCacheInitialized(int rv); 224 225 void StartPurgingResources(const std::vector<int64>& ids); 226 void StartPurgingResources(const ResourceList& resources); 227 void ContinuePurgingResources(); 228 void PurgeResource(int64 id); 229 void OnResourcePurged(int64 id, int rv); 230 231 // Static cross-thread helpers. 232 static void ReadInitialDataFromDB( 233 ServiceWorkerDatabase* database, 234 scoped_refptr<base::SequencedTaskRunner> original_task_runner, 235 const InitializeCallback& callback); 236 static void DeleteRegistrationFromDB( 237 ServiceWorkerDatabase* database, 238 scoped_refptr<base::SequencedTaskRunner> original_task_runner, 239 int64 registration_id, 240 const GURL& origin, 241 const DeleteRegistrationCallback& callback); 242 static void WriteRegistrationInDB( 243 ServiceWorkerDatabase* database, 244 scoped_refptr<base::SequencedTaskRunner> original_task_runner, 245 const ServiceWorkerDatabase::RegistrationData& registration, 246 const ResourceList& resources, 247 const WriteRegistrationCallback& callback); 248 static void FindForDocumentInDB( 249 ServiceWorkerDatabase* database, 250 scoped_refptr<base::SequencedTaskRunner> original_task_runner, 251 const GURL& document_url, 252 const FindInDBCallback& callback); 253 static void FindForPatternInDB( 254 ServiceWorkerDatabase* database, 255 scoped_refptr<base::SequencedTaskRunner> original_task_runner, 256 const GURL& scope, 257 const FindInDBCallback& callback); 258 static void FindForIdInDB( 259 ServiceWorkerDatabase* database, 260 scoped_refptr<base::SequencedTaskRunner> original_task_runner, 261 int64 registration_id, 262 const GURL& origin, 263 const FindInDBCallback& callback); 264 265 // For finding registrations being installed. 266 RegistrationRefsById installing_registrations_; 267 268 // Origins having registations. 269 std::set<GURL> registered_origins_; 270 271 // Pending database tasks waiting for initialization. 272 std::vector<base::Closure> pending_tasks_; 273 274 int64 next_registration_id_; 275 int64 next_version_id_; 276 int64 next_resource_id_; 277 278 enum State { 279 UNINITIALIZED, 280 INITIALIZING, 281 INITIALIZED, 282 DISABLED, 283 }; 284 State state_; 285 286 base::FilePath path_; 287 base::WeakPtr<ServiceWorkerContextCore> context_; 288 289 // Only accessed on |database_task_runner_|. 290 scoped_ptr<ServiceWorkerDatabase> database_; 291 292 scoped_refptr<base::SequencedTaskRunner> database_task_runner_; 293 scoped_refptr<base::MessageLoopProxy> disk_cache_thread_; 294 scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_; 295 scoped_ptr<ServiceWorkerDiskCache> disk_cache_; 296 std::deque<int64> purgeable_reource_ids_; 297 bool is_purge_pending_; 298 299 base::WeakPtrFactory<ServiceWorkerStorage> weak_factory_; 300 301 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStorage); 302 }; 303 304 } // namespace content 305 306 #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_ 307