Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_database.h
blob8dd0b623eac0fcdb2b411aee2e36aad9b3c36de8
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 <string>
11 #include <vector>
13 #include "base/files/file_path.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/macros.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/sequence_checker.h"
18 #include "base/time/time.h"
19 #include "content/common/content_export.h"
20 #include "content/common/service_worker/service_worker_status_code.h"
21 #include "url/gurl.h"
23 namespace leveldb {
24 class DB;
25 class Env;
26 class Status;
27 class WriteBatch;
30 namespace content {
32 // Class to persist serviceworker registration data in a database.
33 // Should NOT be used on the IO thread since this does blocking
34 // file io. The ServiceWorkerStorage class owns this class and
35 // is responsible for only calling it serially on background
36 // non-IO threads (ala SequencedWorkerPool).
37 class CONTENT_EXPORT ServiceWorkerDatabase {
38 public:
39 // We do leveldb stuff in |path| or in memory if |path| is empty.
40 explicit ServiceWorkerDatabase(const base::FilePath& path);
41 ~ServiceWorkerDatabase();
43 // Used in UMA. A new value must be appended only.
44 enum Status {
45 STATUS_OK,
46 STATUS_ERROR_NOT_FOUND,
47 STATUS_ERROR_IO_ERROR,
48 STATUS_ERROR_CORRUPTED,
49 STATUS_ERROR_FAILED,
50 STATUS_ERROR_MAX,
52 static const char* StatusToString(Status status);
54 struct CONTENT_EXPORT RegistrationData {
55 // These values are immutable for the life of a registration.
56 int64 registration_id;
57 GURL scope;
59 // Versions are first stored once they successfully install and become
60 // the waiting version. Then transition to the active version. The stored
61 // version may be in the ACTIVATED state or in the INSTALLED state.
62 GURL script;
63 int64 version_id;
64 bool is_active;
65 bool has_fetch_handler;
66 base::Time last_update_check;
68 // Not populated until ServiceWorkerStorage::StoreRegistration is called.
69 int64_t resources_total_size_bytes;
71 RegistrationData();
72 ~RegistrationData();
75 struct ResourceRecord {
76 int64 resource_id;
77 GURL url;
78 // Signed so we can store -1 to specify an unknown or error state. When
79 // stored to the database, this value should always be >= 0.
80 int64 size_bytes;
82 ResourceRecord() : resource_id(-1), size_bytes(0) {}
83 ResourceRecord(int64 id, GURL url, int64 size_bytes)
84 : resource_id(id), url(url), size_bytes(size_bytes) {}
87 // Reads next available ids from the database. Returns OK if they are
88 // successfully read. Fills the arguments with an initial value and returns
89 // OK if they are not found in the database. Otherwise, returns an error.
90 Status GetNextAvailableIds(
91 int64* next_avail_registration_id,
92 int64* next_avail_version_id,
93 int64* next_avail_resource_id);
95 // Used for diskcache migration (http://crbug.com/487482). Returns true if the
96 // storage needs to migrate a disk cache.
97 Status IsDiskCacheMigrationNeeded(bool* migration_needed);
98 Status SetDiskCacheMigrationNotNeeded();
100 // Used for diskcache migration (http://crbug.com/487482). Returns true if the
101 // storage needs to delete an old disk cache.
102 Status IsOldDiskCacheDeletionNeeded(bool* deletion_needed);
103 Status SetOldDiskCacheDeletionNotNeeded();
105 // Reads origins that have one or more than one registration from the
106 // database. Returns OK if they are successfully read or not found.
107 // Otherwise, returns an error.
108 Status GetOriginsWithRegistrations(std::set<GURL>* origins);
110 // Reads registrations for |origin| from the database. Returns OK if they are
111 // successfully read or not found. Otherwise, returns an error.
112 Status GetRegistrationsForOrigin(
113 const GURL& origin,
114 std::vector<RegistrationData>* registrations,
115 std::vector<std::vector<ResourceRecord>>* opt_resources_list);
117 // Reads all registrations from the database. Returns OK if successfully read
118 // or not found. Otherwise, returns an error.
119 Status GetAllRegistrations(std::vector<RegistrationData>* registrations);
121 // Saving, retrieving, and updating registration data.
122 // (will bump next_avail_xxxx_ids as needed)
123 // (resource ids will be added/removed from the uncommitted/purgeable
124 // lists as needed)
126 // Reads a registration for |registration_id| and resource records associated
127 // with it from the database. Returns OK if they are successfully read.
128 // Otherwise, returns an error.
129 Status ReadRegistration(
130 int64 registration_id,
131 const GURL& origin,
132 RegistrationData* registration,
133 std::vector<ResourceRecord>* resources);
135 // Looks up the origin for the registration with |registration_id|. Returns OK
136 // if a registration was found and read successfully. Otherwise, returns an
137 // error.
138 Status ReadRegistrationOrigin(int64 registration_id, GURL* origin);
140 // Writes |registration| and |resources| into the database and does following
141 // things:
142 // - If an old version of the registration exists, deletes it and sets
143 // |deleted_version| to the old version registration data object
144 // |newly_purgeable_resources| to its resources. Otherwise, sets
145 // |deleted_version->version_id| to -1.
146 // - Bumps the next registration id and the next version id if needed.
147 // - Removes |resources| from the uncommitted list if exist.
148 // Returns OK they are successfully written. Otherwise, returns an error.
149 Status WriteRegistration(const RegistrationData& registration,
150 const std::vector<ResourceRecord>& resources,
151 RegistrationData* deleted_version,
152 std::vector<int64>* newly_purgeable_resources);
154 // Updates a registration for |registration_id| to an active state. Returns OK
155 // if it's successfully updated. Otherwise, returns an error.
156 Status UpdateVersionToActive(
157 int64 registration_id,
158 const GURL& origin);
160 // Updates last check time of a registration for |registration_id| by |time|.
161 // Returns OK if it's successfully updated. Otherwise, returns an error.
162 Status UpdateLastCheckTime(
163 int64 registration_id,
164 const GURL& origin,
165 const base::Time& time);
167 // Deletes a registration for |registration_id| and moves resource records
168 // associated with it into the purgeable list. If deletion occurred, sets
169 // |version_id| to the id of the version that was deleted and
170 // |newly_purgeable_resources| to its resources; otherwise, sets |version_id|
171 // to -1. Returns OK if it's successfully deleted or not found in the
172 // database. Otherwise, returns an error.
173 Status DeleteRegistration(int64 registration_id,
174 const GURL& origin,
175 RegistrationData* deleted_version,
176 std::vector<int64>* newly_purgeable_resources);
178 // Reads user data for |registration_id| and |user_data_name| from the
179 // database.
180 Status ReadUserData(int64 registration_id,
181 const std::string& user_data_name,
182 std::string* user_data);
184 // Writes |user_data| into the database. Returns NOT_FOUND if the registration
185 // specified by |registration_id| does not exist in the database.
186 Status WriteUserData(int64 registration_id,
187 const GURL& origin,
188 const std::string& user_data_name,
189 const std::string& user_data);
191 // Deletes user data for |registration_id| and |user_data_name| from the
192 // database. Returns OK if it's successfully deleted or not found in the
193 // database.
194 Status DeleteUserData(int64 registration_id,
195 const std::string& user_data_name);
197 // Reads user data for all registrations that have data with |user_data_name|
198 // from the database. Returns OK if they are successfully read or not found.
199 Status ReadUserDataForAllRegistrations(
200 const std::string& user_data_name,
201 std::vector<std::pair<int64, std::string>>* user_data);
203 // As new resources are put into the diskcache, they go into an uncommitted
204 // list. When a registration is saved that refers to those ids, they're
205 // removed from that list. When a resource no longer has any registrations or
206 // caches referring to it, it's added to the purgeable list. Periodically,
207 // the purgeable list can be purged from the diskcache. At system startup, all
208 // uncommitted ids are moved to the purgeable list.
210 // Reads uncommitted resource ids from the database. Returns OK on success.
211 // Otherwise clears |ids| and returns an error.
212 Status GetUncommittedResourceIds(std::set<int64>* ids);
214 // Writes |ids| into the database as uncommitted resources. Returns OK on
215 // success. Otherwise writes nothing and returns an error.
216 Status WriteUncommittedResourceIds(const std::set<int64>& ids);
218 // Deletes uncommitted resource ids specified by |ids| from the database.
219 // Returns OK on success. Otherwise deletes nothing and returns an error.
220 Status ClearUncommittedResourceIds(const std::set<int64>& ids);
222 // Reads purgeable resource ids from the database. Returns OK on success.
223 // Otherwise clears |ids| and returns an error.
224 Status GetPurgeableResourceIds(std::set<int64>* ids);
226 // Writes |ids| into the database as purgeable resources. Returns OK on
227 // success. Otherwise writes nothing and returns an error.
228 Status WritePurgeableResourceIds(const std::set<int64>& ids);
230 // Deletes purgeable resource ids specified by |ids| from the database.
231 // Returns OK on success. Otherwise deletes nothing and returns an error.
232 Status ClearPurgeableResourceIds(const std::set<int64>& ids);
234 // Moves |ids| from the uncommitted list to the purgeable list.
235 // Returns OK on success. Otherwise deletes nothing and returns an error.
236 Status PurgeUncommittedResourceIds(const std::set<int64>& ids);
238 // Deletes all data for |origins|, namely, unique origin, registrations and
239 // resource records. Resources are moved to the purgeable list. Returns OK if
240 // they are successfully deleted or not found in the database. Otherwise,
241 // returns an error.
242 Status DeleteAllDataForOrigins(const std::set<GURL>& origins,
243 std::vector<int64>* newly_purgeable_resources);
245 // Completely deletes the contents of the database.
246 // Be careful using this function.
247 Status DestroyDatabase();
249 private:
250 // Opens the database at the |path_|. This is lazily called when the first
251 // database API is called. Returns OK if the database is successfully opened.
252 // Returns NOT_FOUND if the database does not exist and |create_if_missing| is
253 // false. Otherwise, returns an error.
254 Status LazyOpen(bool create_if_missing);
256 // Helper for LazyOpen(). |status| must be the return value from LazyOpen()
257 // and this must be called just after LazyOpen() is called. Returns true if
258 // the database is new or nonexistent, that is, it has never been used.
259 bool IsNewOrNonexistentDatabase(Status status);
261 // Upgrades the database schema from version 1 to version 2. Called by
262 // LazyOpen() when the stored schema is older than version 2.
263 Status UpgradeDatabaseSchemaFromV1ToV2();
265 // Reads the next available id for |id_key|. Returns OK if it's successfully
266 // read. Fills |next_avail_id| with an initial value and returns OK if it's
267 // not found in the database. Otherwise, returns an error.
268 Status ReadNextAvailableId(
269 const char* id_key,
270 int64* next_avail_id);
272 // Reads registration data for |registration_id| from the database. Returns OK
273 // if successfully reads. Otherwise, returns an error.
274 Status ReadRegistrationData(
275 int64 registration_id,
276 const GURL& origin,
277 RegistrationData* registration);
279 // Reads resource records for |version_id| from the database. Returns OK if
280 // it's successfully read or not found in the database. Otherwise, returns an
281 // error.
282 Status ReadResourceRecords(
283 int64 version_id,
284 std::vector<ResourceRecord>* resources);
286 // Deletes resource records for |version_id| from the database. Returns OK if
287 // they are successfully deleted or not found in the database. Otherwise,
288 // returns an error.
289 Status DeleteResourceRecords(
290 int64 version_id,
291 std::vector<int64>* newly_purgeable_resources,
292 leveldb::WriteBatch* batch);
294 // Reads resource ids for |id_key_prefix| from the database. Returns OK if
295 // it's successfully read or not found in the database. Otherwise, returns an
296 // error.
297 Status ReadResourceIds(
298 const char* id_key_prefix,
299 std::set<int64>* ids);
301 // Write resource ids for |id_key_prefix| into the database. Returns OK on
302 // success. Otherwise, returns writes nothing and returns an error.
303 Status WriteResourceIds(
304 const char* id_key_prefix,
305 const std::set<int64>& ids);
306 Status WriteResourceIdsInBatch(
307 const char* id_key_prefix,
308 const std::set<int64>& ids,
309 leveldb::WriteBatch* batch);
311 // Deletes resource ids for |id_key_prefix| from the database. Returns OK if
312 // it's successfully deleted or not found in the database. Otherwise, returns
313 // an error.
314 Status DeleteResourceIds(
315 const char* id_key_prefix,
316 const std::set<int64>& ids);
317 Status DeleteResourceIdsInBatch(
318 const char* id_key_prefix,
319 const std::set<int64>& ids,
320 leveldb::WriteBatch* batch);
322 // Deletes all user data for |registration_id| from the database. Returns OK
323 // if they are successfully deleted or not found in the database.
324 Status DeleteUserDataForRegistration(
325 int64 registration_id,
326 leveldb::WriteBatch* batch);
328 // Reads the current schema version from the database. If the database hasn't
329 // been written anything yet, sets |db_version| to 0 and returns OK.
330 Status ReadDatabaseVersion(int64* db_version);
332 // Writes a batch into the database.
333 // NOTE: You must call this when you want to put something into the database
334 // because this initializes the database if needed.
335 Status WriteBatch(leveldb::WriteBatch* batch);
337 // Bumps the next available id if |used_id| is greater than or equal to the
338 // cached one.
339 void BumpNextRegistrationIdIfNeeded(
340 int64 used_id,
341 leveldb::WriteBatch* batch);
342 void BumpNextResourceIdIfNeeded(
343 int64 used_id,
344 leveldb::WriteBatch* batch);
345 void BumpNextVersionIdIfNeeded(
346 int64 used_id,
347 leveldb::WriteBatch* batch);
349 bool IsOpen();
351 void Disable(
352 const tracked_objects::Location& from_here,
353 Status status);
354 void HandleOpenResult(
355 const tracked_objects::Location& from_here,
356 Status status);
357 void HandleReadResult(
358 const tracked_objects::Location& from_here,
359 Status status);
360 void HandleWriteResult(
361 const tracked_objects::Location& from_here,
362 Status status);
364 const base::FilePath path_;
365 scoped_ptr<leveldb::Env> env_;
366 scoped_ptr<leveldb::DB> db_;
368 int64 next_avail_registration_id_;
369 int64 next_avail_resource_id_;
370 int64 next_avail_version_id_;
372 enum State {
373 UNINITIALIZED,
374 INITIALIZED,
375 DISABLED,
377 State state_;
379 bool IsDatabaseInMemory() const;
381 void set_skip_writing_diskcache_migration_state_on_init_for_testing() {
382 skip_writing_diskcache_migration_state_on_init_for_testing_ = true;
384 bool skip_writing_diskcache_migration_state_on_init_for_testing_;
386 base::SequenceChecker sequence_checker_;
388 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase);
389 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase_InMemory);
390 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DatabaseVersion);
391 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, GetNextAvailableIds);
392 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest,
393 Registration_UninitializedDatabase);
394 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest,
395 UserData_UninitializedDatabase);
396 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DestroyDatabase);
397 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DiskCacheMigrationState);
398 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, UpgradeSchemaToVersion2);
399 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
400 MigrateOnDiskCacheAccess);
401 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDiskCacheMigratorTest,
402 NotMigrateOnDatabaseAccess);
404 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase);
407 } // namespace content
409 #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_