Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_database.h
blob96283c95bd6178dd9b1b33595a9327bf78c361cb
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.
5 #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_
6 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_
8 #include <map>
9 #include <set>
10 #include <vector>
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"
22 namespace leveldb {
23 class DB;
24 class Env;
25 class Status;
26 class WriteBatch;
29 namespace content {
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();
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,
51 static const char* StatusToString(Status status);
53 struct CONTENT_EXPORT RegistrationData {
54 // These values are immutable for the life of a registration.
55 int64 registration_id;
56 GURL scope;
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;
67 // Not populated until ServiceWorkerStorage::StoreRegistration is called.
68 int64_t resources_total_size_bytes;
70 RegistrationData();
71 ~RegistrationData();
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;
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) {}
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);
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);
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);
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);
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)
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);
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);
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);
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);
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);
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.
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);
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);
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);
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);
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);
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);
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);
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);
203 // Completely deletes the contents of the database.
204 // Be careful using this function.
205 Status DestroyDatabase();
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
297 bool IsOpen();
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);
312 base::FilePath path_;
313 scoped_ptr<leveldb::Env> env_;
314 scoped_ptr<leveldb::DB> db_;
316 int64 next_avail_registration_id_;
317 int64 next_avail_resource_id_;
318 int64 next_avail_version_id_;
320 enum State {
321 UNINITIALIZED,
322 INITIALIZED,
323 DISABLED,
325 State state_;
327 base::SequenceChecker sequence_checker_;
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);
335 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase);
338 } // namespace content
340 #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_