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
|
// Copyright 2021 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_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_SQL_H_
#define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_SQL_H_
#include <stdint.h>
#include <optional>
#include <set>
#include <string_view>
#include <vector>
#include "base/files/file_path.h"
#include "base/memory/raw_ref.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "content/browser/aggregation_service/aggregation_service.h"
#include "content/browser/aggregation_service/aggregation_service_storage.h"
#include "content/common/content_export.h"
#include "content/public/browser/storage_partition.h"
#include "sql/database.h"
#include "sql/meta_table.h"
class GURL;
namespace base {
class Clock;
} // namespace base
namespace sql {
class Statement;
} // namespace sql
namespace url {
class Origin;
} // namespace url
namespace content {
class AggregatableReportRequest;
struct PublicKey;
struct PublicKeyset;
// AggregationServiceStorage implementation backed by a SQLite database.
// Instances may be constructed on any sequence but must be accessed and
// destroyed on the same sequence.
// TODO(crbug.com/40191198): Support public key protocol versioning.
class CONTENT_EXPORT AggregationServiceStorageSql
: public AggregationServiceStorage {
public:
// Exposed for testing.
static const int kCurrentVersionNumber;
static const int kCompatibleVersionNumber;
static const int kDeprecatedVersionNumber;
// `clock` must be a non-null pointer that is valid as long as this object.
AggregationServiceStorageSql(
bool run_in_memory,
const base::FilePath& path_to_database,
const base::Clock* clock,
int max_stored_requests_per_reporting_origin =
AggregationService::kMaxStoredReportsPerReportingOrigin);
AggregationServiceStorageSql(const AggregationServiceStorageSql& other) =
delete;
AggregationServiceStorageSql& operator=(
const AggregationServiceStorageSql& other) = delete;
~AggregationServiceStorageSql() override;
// AggregationServiceStorage:
std::vector<PublicKey> GetPublicKeys(const GURL& url) override;
void SetPublicKeys(const GURL& url, const PublicKeyset& keyset) override;
void ClearPublicKeys(const GURL& url) override;
void ClearPublicKeysExpiredBy(base::Time delete_end) override;
void StoreRequest(AggregatableReportRequest request) override;
void DeleteRequest(AggregationServiceStorage::RequestId request_id) override;
void UpdateReportForSendFailure(
AggregationServiceStorage::RequestId request_id,
base::Time new_report_time) override;
std::optional<base::Time> NextReportTimeAfter(
base::Time strictly_after_time) override;
std::vector<AggregationServiceStorage::RequestAndId>
GetRequestsReportingOnOrBefore(base::Time not_after_time,
std::optional<int> limit) override;
std::vector<AggregationServiceStorage::RequestAndId> GetRequests(
const std::vector<AggregationServiceStorage::RequestId>& ids) override;
std::optional<base::Time> AdjustOfflineReportTimes(
base::Time now,
base::TimeDelta min_delay,
base::TimeDelta max_delay) override;
void ClearDataBetween(
base::Time delete_begin,
base::Time delete_end,
StoragePartition::StorageKeyMatcherFunction filter) override;
std::set<url::Origin> GetReportRequestReportingOrigins() override;
void set_ignore_errors_for_testing(bool ignore_for_testing)
VALID_CONTEXT_REQUIRED(sequence_checker_) {
ignore_errors_for_testing_ = ignore_for_testing;
}
// 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,
kFailedToInitializeSchema = 4,
kMaxValue = kFailedToInitializeSchema,
};
private:
enum class DbStatus {
kOpen,
// The database has never been created, i.e. there is no database file at
// all.
kDeferringCreation,
// The database exists but is not open yet.
kDeferringOpen,
// The database initialization failed, or the db suffered from an
// unrecoverable, but potentially transient, error.
kClosed,
// The database initialization failed, or the db suffered from a
// catastrophic failure.
kClosedDueToCatastrophicError,
};
enum class DbCreationPolicy {
// Create the db if it does not exist.
kCreateIfAbsent,
// Do not create the db if it does not exist.
kFailIfAbsent,
};
// Inserts public keys to database.
bool InsertPublicKeysImpl(const GURL& url, const PublicKeyset& keyset)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Deletes all stored public keys for `url` from database.
bool ClearPublicKeysImpl(const GURL& url)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Deletes all stored public keys for `url_id` from database.
bool ClearPublicKeysByUrlId(int64_t url_id)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Clears the stored public keys that were fetched between `delete_begin` and
// `delete_end` time (inclusive). Null times are treated as unbounded lower or
// upper range.
void ClearPublicKeysFetchedBetween(base::Time delete_begin,
base::Time delete_end)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Clears all stored public keys.
void ClearAllPublicKeys() VALID_CONTEXT_REQUIRED(sequence_checker_);
// Deletes the stored request with the given report ID.
bool DeleteRequestImpl(RequestId request_id)
VALID_CONTEXT_REQUIRED(sequence_checker_);
std::optional<base::Time> NextReportTimeAfterImpl(
base::Time strictly_after_time) VALID_CONTEXT_REQUIRED(sequence_checker_);
// Clears the report requests that were stored between `delete_begin` and
// `delete_end` time (inclusive). Null times are treated as unbounded lower or
// upper range. If `!filter.is_null()`, only requests with reporting origins
// matching the `filter` are cleared.
void ClearRequestsStoredBetween(
base::Time delete_begin,
base::Time delete_end,
StoragePartition::StorageKeyMatcherFunction filter)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Clears all stored report requests;
void ClearAllRequests() VALID_CONTEXT_REQUIRED(sequence_checker_);
// Whether the reporting origin has space for an extra report to be stored,
// i.e. has not reached the `max_stored_requests_per_reporting_origin_` limit.
bool ReportingOriginHasCapacity(std::string_view serialized_reporting_origin)
VALID_CONTEXT_REQUIRED(sequence_checker_);
// Initializes the database if necessary, and returns whether the database is
// open. `creation_policy` indicates whether the database should be created if
// it is not already.
[[nodiscard]] bool EnsureDatabaseOpen(DbCreationPolicy creation_policy)
VALID_CONTEXT_REQUIRED(sequence_checker_);
[[nodiscard]] bool InitializeSchema(bool db_empty)
VALID_CONTEXT_REQUIRED(sequence_checker_);
[[nodiscard]] bool CreateSchema() VALID_CONTEXT_REQUIRED(sequence_checker_);
void HandleInitializationFailure(InitStatus status)
VALID_CONTEXT_REQUIRED(sequence_checker_);
void DatabaseErrorCallback(int extended_error, sql::Statement* stmt);
// If set, database errors will not crash the client when run in debug mode.
bool ignore_errors_for_testing_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
const bool run_in_memory_;
// This is an empty FilePath if the database is being stored in-memory.
const base::FilePath path_to_database_;
const raw_ref<const base::Clock> clock_;
// No more report requests with the same reporting origin can be stored in the
// database than this. Any additional requests attempted to be stored will
// silently be dropped until there is more capacity.
int max_stored_requests_per_reporting_origin_;
// The current state of `db_`. Lazy-initialized by `EnsureDatabaseOpen()` to
// avoid touching the filesystem in the constructor. Watch out: any time we
// use the database, its value may be updated by `DatabaseErrorCallback()`.
std::optional<DbStatus> db_status_ GUARDED_BY_CONTEXT(sequence_checker_);
sql::Database db_ GUARDED_BY_CONTEXT(sequence_checker_);
sql::MetaTable meta_table_ GUARDED_BY_CONTEXT(sequence_checker_);
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace content
#endif // CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_SQL_H_
|