Upstream version 7.36.149.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/macros.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/sequence_checker.h"
16 #include "base/time/time.h"
17 #include "content/browser/service_worker/service_worker_version.h"
18 #include "content/common/content_export.h"
19 #include "url/gurl.h"
20
21 namespace leveldb {
22 class DB;
23 class Env;
24 class Status;
25 class WriteBatch;
26 }
27
28 namespace content {
29
30 // Class to persist serviceworker registration data in a database.
31 // Should NOT be used on the IO thread since this does blocking
32 // file io. The ServiceWorkerStorage class owns this class and
33 // is responsible for only calling it serially on background
34 // non-IO threads (ala SequencedWorkerPool).
35 class CONTENT_EXPORT ServiceWorkerDatabase {
36  public:
37   // We do leveldb stuff in |path| or in memory if |path| is empty.
38   explicit ServiceWorkerDatabase(const base::FilePath& path);
39   ~ServiceWorkerDatabase();
40
41   struct CONTENT_EXPORT RegistrationData {
42     // These values are immutable for the life of a registration.
43     int64 registration_id;
44     GURL scope;
45     GURL script;
46
47     // Versions are first stored once they successfully install and become
48     // the waiting version. Then transition to the active version. The stored
49     // version may be in the ACTIVE state or in the INSTALLED state.
50     int64 version_id;
51     bool is_active;
52     bool has_fetch_handler;
53     base::Time last_update_check;
54
55     ServiceWorkerVersion::Status GetVersionStatus() const {
56       if (is_active)
57         return ServiceWorkerVersion::ACTIVE;
58       return ServiceWorkerVersion::INSTALLED;
59     }
60
61     RegistrationData();
62     ~RegistrationData();
63   };
64
65   struct ResourceRecord {
66     int64 resource_id;
67     GURL url;
68   };
69
70   // For use during initialization.
71   bool GetNextAvailableIds(int64* next_avail_registration_id,
72                            int64* next_avail_version_id,
73                            int64* next_avail_resource_id);
74   bool GetOriginsWithRegistrations(std::set<GURL>* origins);
75
76   // For use when first handling a request in an origin with registrations.
77   bool GetRegistrationsForOrigin(const GURL& origin,
78                                  std::vector<RegistrationData>* registrations);
79
80   bool GetAllRegistrations(std::vector<RegistrationData>* registrations);
81
82   // Saving, retrieving, and updating registration data.
83   // (will bump next_avail_xxxx_ids as needed)
84   // (resource ids will be added/removed from the uncommitted/purgeable
85   // lists as needed)
86
87   bool ReadRegistration(int64 registration_id,
88                         const GURL& origin,
89                         RegistrationData* registration,
90                         std::vector<ResourceRecord>* resources);
91   bool WriteRegistration(const RegistrationData& registration,
92                          const std::vector<ResourceRecord>& resources);
93
94   bool UpdateVersionToActive(int64 registration_id,
95                              const GURL& origin);
96   bool UpdateLastCheckTime(int64 registration_id,
97                            const GURL& origin,
98                            const base::Time& time);
99   bool DeleteRegistration(int64 registration_id,
100                           const GURL& origin);
101
102   // As new resources are put into the diskcache, they go into an uncommitted
103   // list. When a registration is saved that refers to those ids, they're
104   // removed from that list. When a resource no longer has any registrations or
105   // caches referring to it, it's added to the purgeable list. Periodically,
106   // the purgeable list can be purged from the diskcache. At system startup, all
107   // uncommitted ids are moved to the purgeable list.
108
109   // Reads uncommitted resource ids from the database. Returns true on success.
110   // Otherwise clears |ids| and returns false.
111   bool GetUncommittedResourceIds(std::set<int64>* ids);
112
113   // Writes |ids| into the database as uncommitted resources. Returns true on
114   // success. Otherwise writes nothing and returns false.
115   bool WriteUncommittedResourceIds(const std::set<int64>& ids);
116
117   // Deletes uncommitted resource ids specified by |ids| from the database.
118   // Returns true on success. Otherwise deletes nothing and returns false.
119   bool ClearUncommittedResourceIds(const std::set<int64>& ids);
120
121   // Reads purgeable resource ids from the database. Returns true on success.
122   // Otherwise clears |ids| and returns false.
123   bool GetPurgeableResourceIds(std::set<int64>* ids);
124
125   // Writes |ids| into the database as purgeable resources. Returns true on
126   // success. Otherwise writes nothing and returns false.
127   bool WritePurgeableResourceIds(const std::set<int64>& ids);
128
129   // Deletes purgeable resource ids specified by |ids| from the database.
130   // Returns true on success. Otherwise deletes nothing and returns false.
131   bool ClearPurgeableResourceIds(const std::set<int64>& ids);
132
133   // Delete all data for |origin|, namely, unique origin, registrations and
134   // resource records. Resources are moved to the purgeable list.
135   bool DeleteAllDataForOrigin(const GURL& origin);
136
137   bool is_disabled() const { return is_disabled_; }
138   bool was_corruption_detected() const { return was_corruption_detected_; }
139
140  private:
141   // Opens the database at the |path_|. This is lazily called when the first
142   // database API is called. Returns true if the database was opened. Returns
143   // false if the opening failed or was not neccessary, that is, the database
144   // does not exist and |create_if_needed| is false.
145   bool LazyOpen(bool create_if_needed);
146
147   bool ReadNextAvailableId(const char* id_key,
148                            int64* next_avail_id);
149   bool ReadRegistrationData(int64 registration_id,
150                             const GURL& origin,
151                             RegistrationData* registration);
152   bool ReadResourceRecords(int64 version_id,
153                            std::vector<ResourceRecord>* resources);
154   bool DeleteResourceRecords(int64 version_id,
155                              leveldb::WriteBatch* batch);
156   bool ReadResourceIds(const char* id_key_prefix,
157                        std::set<int64>* ids);
158   bool WriteResourceIds(const char* id_key_prefix,
159                         const std::set<int64>& ids);
160   bool DeleteResourceIds(const char* id_key_prefix,
161                          const std::set<int64>& ids);
162
163   // Reads the current schema version from the database. If the database hasn't
164   // been written anything yet, sets |db_version| to 0 and returns true.
165   bool ReadDatabaseVersion(int64* db_version);
166
167   // Write a batch into the database.
168   // NOTE: You must call this when you want to put something into the database
169   // because this initializes the database if needed.
170   bool WriteBatch(leveldb::WriteBatch* batch);
171
172   // Bumps the next available id if |used_id| is greater than or equal to the
173   // cached one.
174   void BumpNextRegistrationIdIfNeeded(int64 used_id,
175                                       leveldb::WriteBatch* batch);
176   void BumpNextVersionIdIfNeeded(int64 used_id,
177                                  leveldb::WriteBatch* batch);
178
179   bool IsOpen();
180
181   void HandleError(const tracked_objects::Location& from_here,
182                    const leveldb::Status& status);
183
184   base::FilePath path_;
185   scoped_ptr<leveldb::Env> env_;
186   scoped_ptr<leveldb::DB> db_;
187
188   int64 next_avail_registration_id_;
189   int64 next_avail_resource_id_;
190   int64 next_avail_version_id_;
191
192   // True if a database error has occurred (e.g. cannot read data).
193   // If true, all database accesses will fail.
194   bool is_disabled_;
195
196   // True if a database corruption was detected.
197   bool was_corruption_detected_;
198
199   // True if a database was initialized, that is, the schema version was written
200   // in the database.
201   bool is_initialized_;
202
203   base::SequenceChecker sequence_checker_;
204
205   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase);
206   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, OpenDatabase_InMemory);
207   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DatabaseVersion);
208   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, GetNextAvailableIds);
209   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, Registration_Basic);
210   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, Registration_Overwrite);
211   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, Registration_Multiple);
212
213   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase);
214 };
215
216 }  // namespace content
217
218 #endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_H_