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 NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener)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