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_
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"
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
{
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.
45 STATUS_ERROR_NOT_FOUND
,
46 STATUS_ERROR_IO_ERROR
,
47 STATUS_ERROR_CORRUPTED
,
52 struct CONTENT_EXPORT RegistrationData
{
53 // These values are immutable for the life of a registration.
54 int64 registration_id
;
57 // Versions are first stored once they successfully install and become
58 // the waiting version. Then transition to the active version. The stored
59 // version may be in the ACTIVATED state or in the INSTALLED state.
63 bool has_fetch_handler
;
64 base::Time last_update_check
;
70 struct ResourceRecord
{
75 ResourceRecord(int64 id
, GURL url
) : resource_id(id
), url(url
) {}
78 // Reads next available ids from the database. Returns OK if they are
79 // successfully read. Fills the arguments with an initial value and returns
80 // OK if they are not found in the database. Otherwise, returns an error.
81 Status
GetNextAvailableIds(
82 int64
* next_avail_registration_id
,
83 int64
* next_avail_version_id
,
84 int64
* next_avail_resource_id
);
86 // Reads origins that have one or more than one registration from the
87 // database. Returns OK if they are successfully read or not found.
88 // Otherwise, returns an error.
89 Status
GetOriginsWithRegistrations(std::set
<GURL
>* origins
);
91 // Reads registrations for |origin| from the database. Returns OK if they are
92 // successfully read or not found. Otherwise, returns an error.
93 Status
GetRegistrationsForOrigin(
95 std::vector
<RegistrationData
>* registrations
);
97 // Reads all registrations from the database. Returns OK if successfully read
98 // or not found. Otherwise, returns an error.
99 Status
GetAllRegistrations(std::vector
<RegistrationData
>* registrations
);
101 // Saving, retrieving, and updating registration data.
102 // (will bump next_avail_xxxx_ids as needed)
103 // (resource ids will be added/removed from the uncommitted/purgeable
106 // Reads a registration for |registration_id| and resource records associated
107 // with it from the database. Returns OK if they are successfully read.
108 // Otherwise, returns an error.
109 Status
ReadRegistration(
110 int64 registration_id
,
112 RegistrationData
* registration
,
113 std::vector
<ResourceRecord
>* resources
);
115 // Writes |registration| and |resources| into the database and does following
117 // - If an old version of the registration exists, deletes it and sets
118 // |deleted_version_id| to the old version id and
119 // |newly_purgeable_resources| to its resources. Otherwise, sets
120 // |deleted_version_id| to -1.
121 // - Bumps the next registration id and the next version id if needed.
122 // - Removes |resources| from the uncommitted list if exist.
123 // Returns OK they are successfully written. Otherwise, returns an error.
124 Status
WriteRegistration(const RegistrationData
& registration
,
125 const std::vector
<ResourceRecord
>& resources
,
126 int64
* deleted_version_id
,
127 std::vector
<int64
>* newly_purgeable_resources
);
129 // Updates a registration for |registration_id| to an active state. Returns OK
130 // if it's successfully updated. Otherwise, returns an error.
131 Status
UpdateVersionToActive(
132 int64 registration_id
,
135 // Updates last check time of a registration for |registration_id| by |time|.
136 // Returns OK if it's successfully updated. Otherwise, returns an error.
137 Status
UpdateLastCheckTime(
138 int64 registration_id
,
140 const base::Time
& time
);
142 // Deletes a registration for |registration_id| and moves resource records
143 // associated with it into the purgeable list. If deletion occurred, sets
144 // |version_id| to the id of the version that was deleted and
145 // |newly_purgeable_resources| to its resources; otherwise, sets |version_id|
146 // to -1. Returns OK if it's successfully deleted or not found in the
147 // database. Otherwise, returns an error.
148 Status
DeleteRegistration(int64 registration_id
,
151 std::vector
<int64
>* newly_purgeable_resources
);
153 // As new resources are put into the diskcache, they go into an uncommitted
154 // list. When a registration is saved that refers to those ids, they're
155 // removed from that list. When a resource no longer has any registrations or
156 // caches referring to it, it's added to the purgeable list. Periodically,
157 // the purgeable list can be purged from the diskcache. At system startup, all
158 // uncommitted ids are moved to the purgeable list.
160 // Reads uncommitted resource ids from the database. Returns OK on success.
161 // Otherwise clears |ids| and returns an error.
162 Status
GetUncommittedResourceIds(std::set
<int64
>* ids
);
164 // Writes |ids| into the database as uncommitted resources. Returns OK on
165 // success. Otherwise writes nothing and returns an error.
166 Status
WriteUncommittedResourceIds(const std::set
<int64
>& ids
);
168 // Deletes uncommitted resource ids specified by |ids| from the database.
169 // Returns OK on success. Otherwise deletes nothing and returns an error.
170 Status
ClearUncommittedResourceIds(const std::set
<int64
>& ids
);
172 // Reads purgeable resource ids from the database. Returns OK on success.
173 // Otherwise clears |ids| and returns an error.
174 Status
GetPurgeableResourceIds(std::set
<int64
>* ids
);
176 // Writes |ids| into the database as purgeable resources. Returns OK on
177 // success. Otherwise writes nothing and returns an error.
178 Status
WritePurgeableResourceIds(const std::set
<int64
>& ids
);
180 // Deletes purgeable resource ids specified by |ids| from the database.
181 // Returns OK on success. Otherwise deletes nothing and returns an error.
182 Status
ClearPurgeableResourceIds(const std::set
<int64
>& ids
);
184 // Moves |ids| from the uncommitted list to the purgeable list.
185 // Returns OK on success. Otherwise deletes nothing and returns an error.
186 Status
PurgeUncommittedResourceIds(const std::set
<int64
>& ids
);
188 // Deletes all data for |origin|, namely, unique origin, registrations and
189 // resource records. Resources are moved to the purgeable list. Returns OK if
190 // they are successfully deleted or not found in the database. Otherwise,
192 Status
DeleteAllDataForOrigin(
194 std::vector
<int64
>* newly_purgeable_resources
);
196 // Completely deletes the contents of the database.
197 // Be careful using this function.
198 Status
DestroyDatabase();
201 // Opens the database at the |path_|. This is lazily called when the first
202 // database API is called. Returns OK if the database is successfully opened.
203 // Returns NOT_FOUND if the database does not exist and |create_if_missing| is
204 // false. Otherwise, returns an error.
205 Status
LazyOpen(bool create_if_missing
);
207 // Helper for LazyOpen(). |status| must be the return value from LazyOpen()
208 // and this must be called just after LazyOpen() is called. Returns true if
209 // the database is new or nonexistent, that is, it has never been used.
210 bool IsNewOrNonexistentDatabase(Status status
);
212 // Reads the next available id for |id_key|. Returns OK if it's successfully
213 // read. Fills |next_avail_id| with an initial value and returns OK if it's
214 // not found in the database. Otherwise, returns an error.
215 Status
ReadNextAvailableId(
217 int64
* next_avail_id
);
219 // Reads registration data for |registration_id| from the database. Returns OK
220 // if successfully reads. Otherwise, returns an error.
221 Status
ReadRegistrationData(
222 int64 registration_id
,
224 RegistrationData
* registration
);
226 // Reads resource records for |version_id| from the database. Returns OK if
227 // it's successfully read or not found in the database. Otherwise, returns an
229 Status
ReadResourceRecords(
231 std::vector
<ResourceRecord
>* resources
);
233 // Deletes resource records for |version_id| from the database. Returns OK if
234 // they are successfully deleted or not found in the database. Otherwise,
236 Status
DeleteResourceRecords(
238 std::vector
<int64
>* newly_purgeable_resources
,
239 leveldb::WriteBatch
* batch
);
241 // Reads resource ids for |id_key_prefix| from the database. Returns OK if
242 // it's successfully read or not found in the database. Otherwise, returns an
244 Status
ReadResourceIds(
245 const char* id_key_prefix
,
246 std::set
<int64
>* ids
);
248 // Write resource ids for |id_key_prefix| into the database. Returns OK on
249 // success. Otherwise, returns writes nothing and returns an error.
250 Status
WriteResourceIds(
251 const char* id_key_prefix
,
252 const std::set
<int64
>& ids
);
253 Status
WriteResourceIdsInBatch(
254 const char* id_key_prefix
,
255 const std::set
<int64
>& ids
,
256 leveldb::WriteBatch
* batch
);
258 // Deletes resource ids for |id_key_prefix| from the database. Returns OK if
259 // it's successfully deleted or not found in the database. Otherwise, returns
261 Status
DeleteResourceIds(
262 const char* id_key_prefix
,
263 const std::set
<int64
>& ids
);
264 Status
DeleteResourceIdsInBatch(
265 const char* id_key_prefix
,
266 const std::set
<int64
>& ids
,
267 leveldb::WriteBatch
* batch
);
269 // Reads the current schema version from the database. If the database hasn't
270 // been written anything yet, sets |db_version| to 0 and returns OK.
271 Status
ReadDatabaseVersion(int64
* db_version
);
273 // Writes a batch into the database.
274 // NOTE: You must call this when you want to put something into the database
275 // because this initializes the database if needed.
276 Status
WriteBatch(leveldb::WriteBatch
* batch
);
278 // Bumps the next available id if |used_id| is greater than or equal to the
280 void BumpNextRegistrationIdIfNeeded(
282 leveldb::WriteBatch
* batch
);
283 void BumpNextResourceIdIfNeeded(
285 leveldb::WriteBatch
* batch
);
286 void BumpNextVersionIdIfNeeded(
288 leveldb::WriteBatch
* batch
);
293 const tracked_objects::Location
& from_here
,
295 void HandleOpenResult(
296 const tracked_objects::Location
& from_here
,
298 void HandleReadResult(
299 const tracked_objects::Location
& from_here
,
301 void HandleWriteResult(
302 const tracked_objects::Location
& from_here
,
305 base::FilePath path_
;
306 scoped_ptr
<leveldb::Env
> env_
;
307 scoped_ptr
<leveldb::DB
> db_
;
309 int64 next_avail_registration_id_
;
310 int64 next_avail_resource_id_
;
311 int64 next_avail_version_id_
;
320 base::SequenceChecker sequence_checker_
;
322 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest
, OpenDatabase
);
323 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest
, OpenDatabase_InMemory
);
324 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest
, DatabaseVersion
);
325 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest
, GetNextAvailableIds
);
326 FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest
, DestroyDatabase
);
328 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase
);
331 } // namespace content
333 #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_