Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_database.h
1 // Copyright 2014 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_DATABASE_H_
6 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_
7
8 #include <map>
9 #include <set>
10 #include <vector>
11
12 #include "base/files/file_path.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/macros.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/sequence_checker.h"
17 #include "base/time/time.h"
18 #include "content/common/content_export.h"
19 #include "content/common/service_worker/service_worker_status_code.h"
20 #include "url/gurl.h"
21
22 namespace leveldb {
23 class DB;
24 class Env;
25 class Status;
26 class WriteBatch;
27 }
28
29 namespace content {
30
31 // Class to persist serviceworker registration data in a database.
32 // Should NOT be used on the IO thread since this does blocking
33 // file io. The ServiceWorkerStorage class owns this class and
34 // is responsible for only calling it serially on background
35 // non-IO threads (ala SequencedWorkerPool).
36 class CONTENT_EXPORT ServiceWorkerDatabase {
37  public:
38   // We do leveldb stuff in |path| or in memory if |path| is empty.
39   explicit ServiceWorkerDatabase(const base::FilePath& path);
40   ~ServiceWorkerDatabase();
41
42   // Used in UMA. A new value must be appended only.
43   enum Status {
44     STATUS_OK,
45     STATUS_ERROR_NOT_FOUND,
46     STATUS_ERROR_IO_ERROR,
47     STATUS_ERROR_CORRUPTED,
48     STATUS_ERROR_FAILED,
49     STATUS_ERROR_MAX,
50   };
51   static const char* StatusToString(Status status);
52
53   struct CONTENT_EXPORT RegistrationData {
54     // These values are immutable for the life of a registration.
55     int64 registration_id;
56     GURL scope;
57
58     // Versions are first stored once they successfully install and become
59     // the waiting version. Then transition to the active version. The stored
60     // version may be in the ACTIVATED state or in the INSTALLED state.
61     GURL script;
62     int64 version_id;
63     bool is_active;
64     bool has_fetch_handler;
65     base::Time last_update_check;
66
67     // Not populated until ServiceWorkerStorage::StoreRegistration is called.
68     int64_t resources_total_size_bytes;
69
70     RegistrationData();
71     ~RegistrationData();
72   };
73
74   struct ResourceRecord {
75     int64 resource_id;
76     GURL url;
77     // Signed so we can store -1 to specify an unknown or error state.  When
78     // stored to the database, this value should always be >= 0.
79     int64 size_bytes;
80
81     ResourceRecord() : resource_id(-1), size_bytes(0) {}
82     ResourceRecord(int64 id, GURL url, int64 size_bytes)
83         : resource_id(id), url(url), size_bytes(size_bytes) {}
84   };
85
86   // Reads next available ids from the database. Returns OK if they are
87   // successfully read. Fills the arguments with an initial value and returns
88   // OK if they are not found in the database. Otherwise, returns an error.
89   Status GetNextAvailableIds(
90       int64* next_avail_registration_id,
91       int64* next_avail_version_id,
92       int64* next_avail_resource_id);
93
94   // Reads origins that have one or more than one registration from the
95   // database. Returns OK if they are successfully read or not found.
96   // Otherwise, returns an error.
97   Status GetOriginsWithRegistrations(std::set<GURL>* origins);
98
99   // Reads registrations for |origin| from the database. Returns OK if they are
100   // successfully read or not found. Otherwise, returns an error.
101   Status GetRegistrationsForOrigin(
102       const GURL& origin,
103       std::vector<RegistrationData>* registrations);
104
105   // Reads all registrations from the database. Returns OK if successfully read
106   // or not found. Otherwise, returns an error.
107   Status GetAllRegistrations(std::vector<RegistrationData>* registrations);
108
109   // Saving, retrieving, and updating registration data.
110   // (will bump next_avail_xxxx_ids as needed)
111   // (resource ids will be added/removed from the uncommitted/purgeable
112   // lists as needed)
113
114   // Reads a registration for |registration_id| and resource records associated
115   // with it from the database. Returns OK if they are successfully read.
116   // Otherwise, returns an error.
117   Status ReadRegistration(
118       int64 registration_id,
119       const GURL& origin,
120       RegistrationData* registration,
121       std::vector<ResourceRecord>* resources);
122
123   // Writes |registration| and |resources| into the database and does following
124   // things:
125   //   - If an old version of the registration exists, deletes it and sets
126   //   |deleted_version| to the old version registration data object
127   //   |newly_purgeable_resources| to its resources. Otherwise, sets
128   //   |deleted_version->version_id| to -1.
129   //   - Bumps the next registration id and the next version id if needed.
130   //   - Removes |resources| from the uncommitted list if exist.
131   // Returns OK they are successfully written. Otherwise, returns an error.
132   Status WriteRegistration(const RegistrationData& registration,
133                            const std::vector<ResourceRecord>& resources,
134                            RegistrationData* deleted_version,
135                            std::vector<int64>* newly_purgeable_resources);
136
137   // Updates a registration for |registration_id| to an active state. Returns OK
138   // if it's successfully updated. Otherwise, returns an error.
139   Status UpdateVersionToActive(
140       int64 registration_id,
141       const GURL& origin);
142
143   // Updates last check time of a registration for |registration_id| by |time|.
144   // Returns OK if it's successfully updated. Otherwise, returns an error.
145   Status UpdateLastCheckTime(
146       int64 registration_id,
147       const GURL& origin,
148       const base::Time& time);
149
150   // Deletes a registration for |registration_id| and moves resource records
151   // associated with it into the purgeable list. If deletion occurred, sets
152   // |version_id| to the id of the version that was deleted and
153   // |newly_purgeable_resources| to its resources; otherwise, sets |version_id|
154   // to -1. Returns OK if it's successfully deleted or not found in the
155   // database. Otherwise, returns an error.
156   Status DeleteRegistration(int64 registration_id,
157                             const GURL& origin,
158                             RegistrationData* deleted_version,
159                             std::vector<int64>* newly_purgeable_resources);
160
161   // As new resources are put into the diskcache, they go into an uncommitted
162   // list. When a registration is saved that refers to those ids, they're
163   // removed from that list. When a resource no longer has any registrations or
164   // caches referring to it, it's added to the purgeable list. Periodically,
165   // the purgeable list can be purged from the diskcache. At system startup, all
166   // uncommitted ids are moved to the purgeable list.
167
168   // Reads uncommitted resource ids from the database. Returns OK on success.
169   // Otherwise clears |ids| and returns an error.
170   Status GetUncommittedResourceIds(std::set<int64>* ids);
171
172   // Writes |ids| into the database as uncommitted resources. Returns OK on
173   // success. Otherwise writes nothing and returns an error.
174   Status WriteUncommittedResourceIds(const std::set<int64>& ids);
175
176   // Deletes uncommitted resource ids specified by |ids| from the database.
177   // Returns OK on success. Otherwise deletes nothing and returns an error.
178   Status ClearUncommittedResourceIds(const std::set<int64>& ids);
179
180   // Reads purgeable resource ids from the database. Returns OK on success.
181   // Otherwise clears |ids| and returns an error.
182   Status GetPurgeableResourceIds(std::set<int64>* ids);
183
184   // Writes |ids| into the database as purgeable resources. Returns OK on
185   // success. Otherwise writes nothing and returns an error.
186   Status WritePurgeableResourceIds(const std::set<int64>& ids);
187
188   // Deletes purgeable resource ids specified by |ids| from the database.
189   // Returns OK on success. Otherwise deletes nothing and returns an error.
190   Status ClearPurgeableResourceIds(const std::set<int64>& ids);
191
192   // Moves |ids| from the uncommitted list to the purgeable list.
193   // Returns OK on success. Otherwise deletes nothing and returns an error.
194   Status PurgeUncommittedResourceIds(const std::set<int64>& ids);
195
196   // Deletes all data for |origins|, namely, unique origin, registrations and
197   // resource records. Resources are moved to the purgeable list. Returns OK if
198   // they are successfully deleted or not found in the database. Otherwise,
199   // returns an error.
200   Status DeleteAllDataForOrigins(const std::set<GURL>& origins,
201                                  std::vector<int64>* newly_purgeable_resources);
202
203   // Completely deletes the contents of the database.
204   // Be careful using this function.
205   Status DestroyDatabase();
206
207  private:
208   // Opens the database at the |path_|. This is lazily called when the first
209   // database API is called. Returns OK if the database is successfully opened.
210   // Returns NOT_FOUND if the database does not exist and |create_if_missing| is
211   // false. Otherwise, returns an error.
212   Status LazyOpen(bool create_if_missing);
213
214   // Helper for LazyOpen(). |status| must be the return value from LazyOpen()
215   // and this must be called just after LazyOpen() is called. Returns true if
216   // the database is new or nonexistent, that is, it has never been used.
217   bool IsNewOrNonexistentDatabase(Status status);
218
219   // Reads the next available id for |id_key|. Returns OK if it's successfully
220   // read. Fills |next_avail_id| with an initial value and returns OK if it's
221   // not found in the database. Otherwise, returns an error.
222   Status ReadNextAvailableId(
223       const char* id_key,
224       int64* next_avail_id);
225
226   // Reads registration data for |registration_id| from the database. Returns OK
227   // if successfully reads. Otherwise, returns an error.
228   Status ReadRegistrationData(
229       int64 registration_id,
230       const GURL& origin,
231       RegistrationData* registration);
232
233   // Reads resource records for |version_id| from the database. Returns OK if
234   // it's successfully read or not found in the database. Otherwise, returns an
235   // error.
236   Status ReadResourceRecords(
237       int64 version_id,
238       std::vector<ResourceRecord>* resources);
239
240   // Deletes resource records for |version_id| from the database. Returns OK if
241   // they are successfully deleted or not found in the database. Otherwise,
242   // returns an error.
243   Status DeleteResourceRecords(
244       int64 version_id,
245       std::vector<int64>* newly_purgeable_resources,
246       leveldb::WriteBatch* batch);
247
248   // Reads resource ids for |id_key_prefix| from the database. Returns OK if
249   // it's successfully read or not found in the database. Otherwise, returns an
250   // error.
251   Status ReadResourceIds(
252       const char* id_key_prefix,
253       std::set<int64>* ids);
254
255   // Write resource ids for |id_key_prefix| into the database. Returns OK on
256   // success. Otherwise, returns writes nothing and returns an error.
257   Status WriteResourceIds(
258       const char* id_key_prefix,
259       const std::set<int64>& ids);
260   Status WriteResourceIdsInBatch(
261       const char* id_key_prefix,
262       const std::set<int64>& ids,
263       leveldb::WriteBatch* batch);
264
265   // Deletes resource ids for |id_key_prefix| from the database. Returns OK if
266   // it's successfully deleted or not found in the database. Otherwise, returns
267   // an error.
268   Status DeleteResourceIds(
269       const char* id_key_prefix,
270       const std::set<int64>& ids);
271   Status DeleteResourceIdsInBatch(
272       const char* id_key_prefix,
273       const std::set<int64>& ids,
274       leveldb::WriteBatch* batch);
275
276   // Reads the current schema version from the database. If the database hasn't
277   // been written anything yet, sets |db_version| to 0 and returns OK.
278   Status ReadDatabaseVersion(int64* db_version);
279
280   // Writes a batch into the database.
281   // NOTE: You must call this when you want to put something into the database
282   // because this initializes the database if needed.
283   Status WriteBatch(leveldb::WriteBatch* batch);
284
285   // Bumps the next available id if |used_id| is greater than or equal to the
286   // cached one.
287   void BumpNextRegistrationIdIfNeeded(
288       int64 used_id,
289       leveldb::WriteBatch* batch);
290   void BumpNextResourceIdIfNeeded(
291       int64 used_id,
292       leveldb::WriteBatch* batch);
293   void BumpNextVersionIdIfNeeded(
294       int64 used_id,
295       leveldb::WriteBatch* batch);
296
297   bool IsOpen();
298
299   void Disable(
300       const tracked_objects::Location& from_here,
301       Status status);
302   void HandleOpenResult(
303       const tracked_objects::Location& from_here,
304       Status status);
305   void HandleReadResult(
306       const tracked_objects::Location& from_here,
307       Status status);
308   void HandleWriteResult(
309       const tracked_objects::Location& from_here,
310       Status status);
311
312   base::FilePath path_;
313   scoped_ptr<leveldb::Env> env_;
314   scoped_ptr<leveldb::DB> db_;
315
316   int64 next_avail_registration_id_;
317   int64 next_avail_resource_id_;
318   int64 next_avail_version_id_;
319
320   enum State {
321     UNINITIALIZED,
322     INITIALIZED,
323     DISABLED,
324   };
325   State state_;
326
327   base::SequenceChecker sequence_checker_;
328
329   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase);
330   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase_InMemory);
331   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DatabaseVersion);
332   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, GetNextAvailableIds);
333   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DestroyDatabase);
334
335   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase);
336 };
337
338 }  // namespace content
339
340 #endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_