• 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/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