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
content / browser / private_aggregation / private_aggregation_budget_storage.h [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_BUDGET_STORAGE_H_
#define CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_BUDGET_STORAGE_H_
#include <memory>
#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/sqlite_proto/key_value_data.h"
#include "components/sqlite_proto/key_value_table.h"
#include "content/common/content_export.h"
namespace base {
class ElapsedTimer;
class FilePath;
class SequencedTaskRunner;
} // namespace base
namespace sql {
class Database;
} // namespace sql
namespace sqlite_proto {
class ProtoTableManager;
} // namespace sqlite_proto
namespace content {
namespace proto {
class PrivateAggregationBudgets;
} // namespace proto
// UI thread class that provides an interface for storing the budget used by
// each key, i.e. the sum of contributions, and persisting that to an on-disk
// database (unless run exclusively in memory). This class is responsible for
// owning and initializing the database and sqlite_proto classes. Note that
// callbacks are used for storage return values to allow switching the
// underlying storage in the future in case the cache uses too much memory.
// Writes are buffered for `kFlushDelay` and then persisted to disk. The
// `Create()` factory method ensures that this class stays alive through
// initialization; after that point, it has no specific lifetime requirements.
class CONTENT_EXPORT PrivateAggregationBudgetStorage {
public:
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class InitStatus {
kSuccess = 0,
kFailedToOpenDbInMemory = 1,
kFailedToOpenDbFile = 2,
kFailedToCreateDir = 3,
kMaxValue = kFailedToCreateDir,
};
// Constructs and asynchronously initializes a new
// `PrivateAggregationBudgetStorage`, including posting a task to
// `db_task_runner` to initialize the underlying database on its sequence.
// Calls `on_done_initializing` once initialization is complete, passing an
// owning pointer if initialization was successful and nullptr otherwise. If
// `exclusively_run_in_memory` is `true`, the database will not be persisted
// to disk. Returns a closure that shuts down the storage before it is
// finished initializing. This is necessary to avoid posting tasks after
// shutdown if initialization finishes too late.
static base::OnceClosure CreateAsync(
scoped_refptr<base::SequencedTaskRunner> db_task_runner,
bool exclusively_run_in_memory,
base::FilePath path_to_db_dir,
base::OnceCallback<void(std::unique_ptr<PrivateAggregationBudgetStorage>)>
on_done_initializing);
PrivateAggregationBudgetStorage(
const PrivateAggregationBudgetStorage& other) = delete;
PrivateAggregationBudgetStorage& operator=(
const PrivateAggregationBudgetStorage& other) = delete;
~PrivateAggregationBudgetStorage();
// The maximum time writes will be buffered before being committed to disk.
// Note that `Shutdown()` will flush pending writes to disk without delay.
// This value was chosen to match TrustTokenDatabaseOwner.
static constexpr base::TimeDelta kFlushDelay = base::Seconds(2);
// TODO(crbug.com/40226450): Support data deletion.
sqlite_proto::KeyValueData<proto::PrivateAggregationBudgets>* budgets_data() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return &budgets_data_;
}
// Asynchronously tears down the budget storage database. Can be called before
// initialization is complete. This is necessary to avoid posting tasks after
// shutdown if initialization finishes too late.
void Shutdown();
private:
explicit PrivateAggregationBudgetStorage(
scoped_refptr<base::SequencedTaskRunner> db_task_runner);
// Creates and opens the database and then calls into ProtoTableManager's and
// KeyValueData's initialization methods. If `exclusively_run_in_memory` is
// true, the underlying database will be in-memory and not be persisted to
// disk. Otherwise, a copy of the data is kept in-memory, but regularly
// flushed to disk. Takes a raw pointer to the database in case `db_` is
// released before or while this is running.
[[nodiscard]] bool InitializeOnDbSequence(sql::Database* db,
bool exclusively_run_in_memory,
base::FilePath path_to_db_dir);
void FinishInitializationOnMainSequence(
std::unique_ptr<PrivateAggregationBudgetStorage> owned_this,
base::OnceCallback<void(std::unique_ptr<PrivateAggregationBudgetStorage>)>
on_done_initializing,
base::ElapsedTimer elapsed_timer,
bool was_successful);
scoped_refptr<sqlite_proto::ProtoTableManager> table_manager_;
std::unique_ptr<sqlite_proto::KeyValueTable<proto::PrivateAggregationBudgets>>
budgets_table_;
sqlite_proto::KeyValueData<proto::PrivateAggregationBudgets> budgets_data_;
// Keep a handle on the DB task runner so that the destructor can use the DB
// sequence to clean up the DB.
scoped_refptr<base::SequencedTaskRunner> db_task_runner_;
// Created on the main sequence, but otherwise should only be accessed on the
// `db_task_runner_` sequence. It is also released (but not deleted) on the
// main sequence.
std::unique_ptr<sql::Database> db_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<PrivateAggregationBudgetStorage> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_BUDGET_STORAGE_H_