• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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