forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquota_database.h
324 lines (267 loc) · 13 KB
/
quota_database.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef STORAGE_BROWSER_QUOTA_QUOTA_DATABASE_H_
#define STORAGE_BROWSER_QUOTA_QUOTA_DATABASE_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <set>
#include <string>
#include "base/callback.h"
#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/types/id_type.h"
#include "components/services/storage/public/cpp/buckets/bucket_id.h"
#include "components/services/storage/public/cpp/buckets/bucket_info.h"
#include "components/services/storage/public/cpp/buckets/bucket_init_params.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/cpp/buckets/constants.h"
#include "components/services/storage/public/cpp/quota_error_or.h"
#include "storage/browser/quota/quota_internals.mojom-forward.h"
#include "storage/browser/quota/storage_directory.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
namespace base {
class Clock;
}
namespace sql {
class Database;
class MetaTable;
} // namespace sql
namespace storage {
class SpecialStoragePolicy;
// These values are logged to UMA. Entries should not be renumbered and numeric
// values should never be reused. Please keep in sync with "DatabaseResetReason"
// in tools/metrics/histograms/enums.xml.
enum class DatabaseResetReason {
kOpenDatabase = 0,
kOpenInMemoryDatabase = 1,
kCreateSchema = 2,
kDatabaseMigration = 3,
kDatabaseVersionTooNew = 4,
kInitMetaTable = 5,
kCreateDirectory = 6,
kMaxValue = kCreateDirectory
};
// Stores all quota managed origin bucket data and metadata.
//
// Instances are owned by QuotaManagerImpl. There is one instance per
// QuotaManagerImpl instance. All the methods of this class, except the
// constructor, must called on the DB thread.
class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDatabase {
public:
static constexpr char kDatabaseName[] = "QuotaManager";
// If `profile_path` is empty, an in-memory database will be used.
explicit QuotaDatabase(const base::FilePath& profile_path);
QuotaDatabase(const QuotaDatabase&) = delete;
QuotaDatabase& operator=(const QuotaDatabase&) = delete;
~QuotaDatabase();
// Returns quota if entry is found. Returns QuotaError::kNotFound no entry if
// found.
QuotaErrorOr<int64_t> GetHostQuota(const std::string& host,
blink::mojom::StorageType type);
// Returns whether the operation succeeded.
QuotaError SetHostQuota(const std::string& host,
blink::mojom::StorageType type,
int64_t quota);
QuotaError DeleteHostQuota(const std::string& host,
blink::mojom::StorageType type);
// Gets the bucket described by `params.storage_key` and `params.name`
// for StorageType kTemporary and returns the BucketInfo. If a bucket fitting
// the params doesn't exist, it creates a new bucket with the policies in
// `params`. If the bucket exists but policies don't match what's provided in
// `params`, the existing bucket will be updated and returned (for those
// policies that are possible to modify --- expiration and persistence).
// Returns a QuotaError if the operation has failed.
QuotaErrorOr<BucketInfo> UpdateOrCreateBucket(const BucketInitParams& params);
// Same as UpdateOrCreateBucket but takes in StorageType. This should only
// be used by FileSystem, and is expected to be removed when
// StorageType::kSyncable and StorageType::kPersistent are deprecated.
// (crbug.com/1233525, crbug.com/1286964).
QuotaErrorOr<BucketInfo> GetOrCreateBucketDeprecated(
const BucketInitParams& params,
blink::mojom::StorageType type);
// TODO(crbug.com/1208141): Remove `storage_type` when the only supported
// StorageType is kTemporary.
QuotaErrorOr<BucketInfo> CreateBucketForTesting(
const blink::StorageKey& storage_key,
const std::string& bucket_name,
blink::mojom::StorageType storage_type);
// Retrieves BucketInfo of the bucket with `bucket_name` for `storage_key`.
// Returns a QuotaError::kEntryNotFound if the bucket does not exist, or
// a QuotaError::kDatabaseError if the operation has failed.
QuotaErrorOr<BucketInfo> GetBucket(const blink::StorageKey& storage_key,
const std::string& bucket_name,
blink::mojom::StorageType storage_type);
// Retrieves BucketInfo of the bucket with `bucket_id`.
// Returns a QuotaError::kEntryNotFound if the bucket does not exist, or
// a QuotaError::kDatabaseError if the operation has failed.
QuotaErrorOr<BucketInfo> GetBucketById(BucketId bucket_id);
// Returns all buckets for `type` in the buckets table. Returns a QuotaError
// if the operation has failed.
QuotaErrorOr<std::set<BucketInfo>> GetBucketsForType(
blink::mojom::StorageType type);
// Retrieves all buckets for `host` and `type`. Returns a QuotaError if the
// operation has failed.
QuotaErrorOr<std::set<BucketInfo>> GetBucketsForHost(
const std::string& host,
blink::mojom::StorageType type);
// Returns all buckets for `storage_key` in the buckets table. Returns a
// QuotaError if the operation has failed.
QuotaErrorOr<std::set<BucketInfo>> GetBucketsForStorageKey(
const blink::StorageKey& storage_key,
blink::mojom::StorageType type);
// Updates the expiration for the designated bucket.
QuotaErrorOr<BucketInfo> UpdateBucketExpiration(BucketId bucket,
const base::Time& expiration);
// Updates the persistence bit for the designated bucket.
QuotaErrorOr<BucketInfo> UpdateBucketPersistence(BucketId bucket,
bool persistent);
// TODO(crbug.com/1202167): Remove once all usages have updated to use
// SetBucketLastAccessTime.
[[nodiscard]] QuotaError SetStorageKeyLastAccessTime(
const blink::StorageKey& storage_key,
blink::mojom::StorageType type,
base::Time last_accessed);
// Called by QuotaClient implementers to update when the bucket was last
// accessed. If `bucket_id` refers to a bucket with an opaque StorageKey, the
// bucket's last access time will not be updated and the function will return
// QuotaError::kNotFound. Returns QuotaError::kNone on a successful update.
[[nodiscard]] QuotaError SetBucketLastAccessTime(BucketId bucket_id,
base::Time last_accessed);
// Called by QuotaClient implementers to update when the bucket was last
// modified. Returns QuotaError::kNone on a successful update.
[[nodiscard]] QuotaError SetBucketLastModifiedTime(BucketId bucket_id,
base::Time last_modified);
// Register initial `storage_keys_by_type` into the database.
// This method is assumed to be called only after the installation or
// the database schema reset.
QuotaError RegisterInitialStorageKeyInfo(
base::flat_map<blink::mojom::StorageType, std::set<blink::StorageKey>>
storage_keys_by_type);
// Returns the BucketTableEntry for `bucket` if one exists. Returns a
// QuotaError if not found or the operation has failed.
QuotaErrorOr<mojom::BucketTableEntryPtr> GetBucketInfo(BucketId bucket_id);
// Deletes the bucket from the database as well as the bucket directory in the
// storage directory.
QuotaError DeleteBucketData(const BucketLocator& bucket);
// Returns the BucketLocator for the least recently used bucket. Will exclude
// buckets with ids in `bucket_exceptions`, buckets marked persistent, and
// origins that have the special unlimited storage policy. Returns a
// QuotaError if the operation has failed.
QuotaErrorOr<BucketLocator> GetLruEvictableBucket(
blink::mojom::StorageType type,
const std::set<BucketId>& bucket_exceptions,
SpecialStoragePolicy* special_storage_policy);
// Returns all storage keys for `type` in the buckets table.
QuotaErrorOr<std::set<blink::StorageKey>> GetStorageKeysForType(
blink::mojom::StorageType type);
// Returns a set of buckets that have been modified since the `begin` and
// until the `end`. Returns a QuotaError if the operations has failed.
QuotaErrorOr<std::set<BucketLocator>> GetBucketsModifiedBetween(
blink::mojom::StorageType type,
base::Time begin,
base::Time end);
base::FilePath GetStoragePath() const { return storage_directory_->path(); }
// Returns false if SetIsBootstrapped() has never been called before, which
// means existing storage keys may not have been registered. Bootstrapping
// ensures that there is a bucket entry in the buckets table for all storage
// keys that have stored data by quota managed Storage APIs.
bool IsBootstrapped();
QuotaError SetIsBootstrapped(bool bootstrap_flag);
// Razes and re-opens the database. Will try to open a database again if
// one doesn't exist.
QuotaError RazeAndReopen();
// Flushes previously scheduled commits.
void CommitNow();
// Testing support for database corruption handling.
//
// Runs `corrupter` on the same sequence used to do database I/O,
// guaranteeing that no other database operation is performed at the same
// time. `corrupter` receives the path to the underlying SQLite database as an
// argument. The underlying SQLite database is closed while `corrupter` runs,
// and reopened afterwards.
// Returns QuotaError::kNone if the database was successfully reopened after
// `corrupter` was run, or QuotaError::kDatabaseError otherwise.
QuotaError CorruptForTesting(
base::OnceCallback<void(const base::FilePath&)> corrupter);
// Manually disable database to test database error scenarios for testing.
void SetDisabledForTesting(bool disable);
static base::Time GetNow();
static void SetClockForTesting(base::Clock* clock);
private:
struct COMPONENT_EXPORT(STORAGE_BROWSER) QuotaTableEntry {
std::string host;
blink::mojom::StorageType type = blink::mojom::StorageType::kUnknown;
int64_t quota = 0;
};
friend COMPONENT_EXPORT(STORAGE_BROWSER) bool operator==(
const QuotaTableEntry& lhs,
const QuotaTableEntry& rhs);
friend COMPONENT_EXPORT(STORAGE_BROWSER) bool operator<(
const QuotaTableEntry& lhs,
const QuotaTableEntry& rhs);
// Structures used for CreateSchema.
struct TableSchema {
const char* table_name;
const char* columns;
};
struct IndexSchema {
const char* index_name;
const char* table_name;
const char* columns;
bool unique;
};
using QuotaTableCallback =
base::RepeatingCallback<bool(const QuotaTableEntry&)>;
using BucketTableCallback =
base::RepeatingCallback<bool(mojom::BucketTableEntryPtr)>;
// For long-running transactions support. We always keep a transaction open
// so that multiple transactions can be batched. They are flushed
// with a delay after a modification has been made. We support neither
// nested transactions nor rollback (as we don't need them for now).
void Commit();
void ScheduleCommit();
QuotaError EnsureOpened();
bool MoveLegacyDatabase();
bool OpenDatabase();
bool EnsureDatabaseVersion();
bool ResetStorage();
bool CreateSchema();
bool CreateTable(const TableSchema& table);
bool CreateIndex(const IndexSchema& index);
// Dumps table entries for chrome://quota-internals page.
// `callback` may return false to stop reading data.
QuotaError DumpQuotaTable(const QuotaTableCallback& callback);
QuotaError DumpBucketTable(const BucketTableCallback& callback);
// Adds a new bucket entry in the buckets table. Will return a
// QuotaError::kDatabaseError if the query fails.
QuotaErrorOr<BucketInfo> CreateBucketInternal(const BucketInitParams& params,
blink::mojom::StorageType type);
SEQUENCE_CHECKER(sequence_checker_);
const std::unique_ptr<StorageDirectory> storage_directory_;
const base::FilePath db_file_path_;
const base::FilePath legacy_db_file_path_;
std::unique_ptr<sql::Database> db_ GUARDED_BY_CONTEXT(sequence_checker_);
std::unique_ptr<sql::MetaTable> meta_table_
GUARDED_BY_CONTEXT(sequence_checker_);
bool is_recreating_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
bool is_disabled_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
base::OneShotTimer timer_ GUARDED_BY_CONTEXT(sequence_checker_);
friend class QuotaDatabaseTest;
friend class QuotaDatabaseMigrations;
friend class QuotaDatabaseMigrationsTest;
friend class QuotaManagerImpl;
static const TableSchema kTables[];
static const size_t kTableCount;
static const IndexSchema kIndexes[];
static const size_t kIndexCount;
};
} // namespace storage
#endif // STORAGE_BROWSER_QUOTA_QUOTA_DATABASE_H_