#include "content/browser/interest_group/interest_group_storage.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/json/json_string_value_serializer.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/sequence_checker.h"
#include "base/strings/escape.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/typed_macros.h"
#include "base/types/pass_key.h"
#include "content/browser/interest_group/bidding_and_auction_server_key_fetcher.h"
#include "content/browser/interest_group/for_debugging_only_report_util.h"
#include "content/browser/interest_group/interest_group_features.h"
#include "content/browser/interest_group/interest_group_k_anonymity_manager.h"
#include "content/browser/interest_group/interest_group_storage.pb.h"
#include "content/browser/interest_group/interest_group_update.h"
#include "content/browser/interest_group/storage_interest_group.h"
#include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom.h"
#include "crypto/sha2.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "sql/database.h"
#include "sql/error_delegate_util.h"
#include "sql/meta_table.h"
#include "sql/recovery.h"
#include "sql/statement.h"
#include "sql/transaction.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/interest_group/interest_group.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/boringssl/src/include/openssl/curve25519.h"
#include "third_party/snappy/src/snappy.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/origin.h"
namespace content {
namespace {
PassKey;
BiddingBrowserSignalsPtr;
PreviousWinPtr;
SellerCapabilitiesType;
enum class AdProtoDecompressionOutcome { … };
enum class InterestGroupStorageInitializationResult { … };
enum class InterestGroupStorageJSONDeserializationResult { … };
enum class InterestGroupStorageJSONSerializationResult { … };
enum class InterestGroupStorageProtoDeserializationResult { … };
enum class InterestGroupStorageProtoSerializationResult { … };
enum class InterestGroupStorageVacuumResult { … };
const base::FilePath::CharType kDatabasePath[] = …);
const int kCurrentVersionNumber = …;
const int kCompatibleVersionNumber = …;
const int kDeprecatedVersionNumber = …;
std::string Serialize(base::ValueView value_view) { … }
std::unique_ptr<base::Value> DeserializeValue(
const std::string& serialized_value) { … }
std::string Serialize(const url::Origin& origin) { … }
url::Origin DeserializeOrigin(const std::string& serialized_origin) { … }
std::string Serialize(const std::optional<GURL>& url) { … }
std::optional<GURL> DeserializeURL(const std::string& serialized_url) { … }
blink::InterestGroup::Ad FromInterestGroupAdValue(const PassKey& passkey,
const base::Value::Dict& dict,
bool for_components) { … }
std::string Serialize(
const std::optional<base::flat_map<std::string, double>>& flat_map) { … }
std::optional<base::flat_map<std::string, double>> DeserializeStringDoubleMap(
const std::string& serialized_flat_map) { … }
AdProtos GetAdProtosFromAds(std::vector<blink::InterestGroup::Ad> ads) { … }
std::string SerializeUncompressed(
const std::optional<std::vector<blink::InterestGroup::Ad>>& ads) { … }
std::string Serialize(
const std::optional<std::vector<blink::InterestGroup::Ad>>& ads) { … }
std::optional<std::vector<blink::InterestGroup::Ad>>
DeserializeInterestGroupAdVectorJson(const PassKey& passkey,
const std::string& serialized_ads,
bool for_components) { … }
std::optional<std::vector<blink::InterestGroup::Ad>>
DeserializeInterestGroupAdVectorProto(const PassKey& passkey,
const std::string& serialized_ads) { … }
std::optional<std::vector<blink::InterestGroup::Ad>>
DecompressAndDeserializeInterestGroupAdVectorProto(
const PassKey& passkey,
const std::string& compressed) { … }
std::string Serialize(
const std::optional<base::flat_map<std::string, blink::AdSize>>& ad_sizes) { … }
std::optional<base::flat_map<std::string, blink::AdSize>>
DeserializeStringSizeMap(const std::string& serialized_sizes) { … }
std::string Serialize(
const std::optional<base::flat_map<std::string, std::vector<std::string>>>&
size_groups) { … }
std::optional<base::flat_map<std::string, std::vector<std::string>>>
DeserializeStringStringVectorMap(const std::string& serialized_groups) { … }
std::string Serialize(const std::optional<std::vector<std::string>>& strings) { … }
std::optional<std::vector<std::string>> DeserializeStringVector(
const std::string& serialized_vector) { … }
int64_t Serialize(SellerCapabilitiesType capabilities) { … }
SellerCapabilitiesType DeserializeSellerCapabilities(int64_t serialized) { … }
std::string Serialize(
const std::optional<base::flat_map<url::Origin, SellerCapabilitiesType>>&
flat_map) { … }
std::optional<base::flat_map<url::Origin, SellerCapabilitiesType>>
DeserializeSellerCapabilitiesMap(const std::string& serialized) { … }
int64_t Serialize(blink::AuctionServerRequestFlags flags) { … }
blink::AuctionServerRequestFlags DeserializeAuctionServerRequestFlags(
int64_t serialized) { … }
std::vector<uint8_t> Serialize(
std::optional<blink::InterestGroup::AdditionalBidKey> key) { … }
std::optional<blink::InterestGroup::AdditionalBidKey>
DeserializeAdditionalBidKey(const base::span<const uint8_t>& serialized) { … }
void MergePrioritySignalsOverrides(
const base::flat_map<std::string, std::optional<double>>& update_data,
std::optional<base::flat_map<std::string, double>>&
priority_signals_overrides) { … }
void MergePrioritySignalsOverrides(
const base::flat_map<std::string,
auction_worklet::mojom::PrioritySignalsDoublePtr>&
update_data,
std::optional<base::flat_map<std::string, double>>&
priority_signals_overrides) { … }
enum KAnonKeyType { … };
KAnonKeyType GetKAnonType(const std::string& unhashed_key) { … }
std::set<std::string> GetAllKanonKeys(
const blink::InterestGroup& interest_group) { … }
bool CreateInterestGroupIndices(sql::Database& db) { … }
bool CreateKAnonIndices(sql::Database& db) { … }
bool MaybeCreateKAnonEntryForV17DatabaseUpgrade(
sql::Database& db,
const blink::InterestGroupKey& interest_group_key,
const std::string& key,
const base::Time& now) { … }
bool CreateV29Schema(sql::Database& db) { … }
bool VacuumDB(sql::Database& db) { … }
bool UpgradeV29SchemaToV30(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV27SchemaToV28(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV26SchemaToV27(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV24SchemaToV25(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV23SchemaToV24(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV22SchemaToV23(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV21SchemaToV22(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV20SchemaToV21(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV19SchemaToV20(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV18SchemaToV19(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV17SchemaToV18(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV16SchemaToV17(sql::Database& db,
sql::MetaTable& meta_table,
const PassKey& passkey) { … }
bool UpgradeV15SchemaToV16(sql::Database& db,
sql::MetaTable& meta_table,
const PassKey& passkey) { … }
bool UpgradeV14SchemaToV15(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV13SchemaToV14(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV12SchemaToV13(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV11SchemaToV12(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV10SchemaToV11(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV9SchemaToV10(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV8SchemaToV9(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV7SchemaToV8(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeV6SchemaToV7(sql::Database& db, sql::MetaTable& meta_table) { … }
bool UpgradeDB(sql::Database& db,
const int db_version,
sql::MetaTable& meta_table,
const PassKey& pass_key) { … }
bool RemoveJoinHistory(sql::Database& db,
const blink::InterestGroupKey& group_key) { … }
bool RemoveBidHistory(sql::Database& db,
const blink::InterestGroupKey& group_key) { … }
bool RemoveWinHistory(sql::Database& db,
const blink::InterestGroupKey& group_key) { … }
bool DoRemoveInterestGroup(sql::Database& db,
const blink::InterestGroupKey& group_key) { … }
bool DoClearClusteredBiddingGroups(sql::Database& db,
const url::Origin owner,
const url::Origin main_frame) { … }
std::optional<std::vector<std::string>> DoClearOriginJoinedInterestGroups(
sql::Database& db,
const url::Origin owner,
const std::set<std::string>& interest_groups_to_keep,
const url::Origin joining_origin) { … }
#define COMMON_INTEREST_GROUPS_QUERY_FIELDS …
void PopulateInterestGroupFromQueryResult(sql::Statement& load,
const PassKey& passkey,
StorageInterestGroup& group) { … }
bool DoLoadInterestGroup(sql::Database& db,
const PassKey& passkey,
const blink::InterestGroupKey& group_key,
StorageInterestGroup& group) { … }
bool DoRecordInterestGroupJoin(sql::Database& db,
const url::Origin& owner,
const std::string& name,
base::Time join_time) { … }
std::optional<InterestGroupKanonUpdateParameter> DoJoinInterestGroup(
sql::Database& db,
const PassKey& passkey,
const blink::InterestGroup& data,
const GURL& joining_url,
base::Time exact_join_time,
base::Time last_updated,
base::Time next_update_after) { … }
bool DoStoreInterestGroupUpdate(
sql::Database& db,
const blink::InterestGroup& group,
base::Time now,
base::flat_set<std::string>& positive_kanon_keys) { … }
std::optional<InterestGroupKanonUpdateParameter> DoUpdateInterestGroup(
sql::Database& db,
const PassKey& passkey,
const blink::InterestGroupKey& group_key,
InterestGroupUpdate update,
base::Time now) { … }
bool DoAllowUpdateIfOlderThan(sql::Database& db,
const PassKey& passkey,
const blink::InterestGroupKey& group_key,
base::TimeDelta update_if_older_than,
base::Time now) { … }
bool DoReportUpdateFailed(sql::Database& db,
const blink::InterestGroupKey& group_key,
bool parse_failure,
base::Time now) { … }
bool DoRecordInterestGroupBid(sql::Database& db,
const blink::InterestGroupKey& group_key,
base::Time bid_time) { … }
bool DoRecordInterestGroupBids(sql::Database& db,
const blink::InterestGroupSet& group_keys,
base::Time bid_time) { … }
bool DoRecordInterestGroupWin(sql::Database& db,
const blink::InterestGroupKey& group_key,
const std::string& ad_json,
base::Time win_time) { … }
bool DoRecordDebugReportLockout(sql::Database& db,
base::Time last_debug_report_sent_time) { … }
bool DoRecordDebugReportCooldown(sql::Database& db,
const url::Origin& origin,
base::Time cooldown_start,
DebugReportCooldownType cooldown_type) { … }
bool DoUpdateKAnonymity(sql::Database& db,
const blink::InterestGroupKey& interest_group_key,
const std::vector<std::string>& positive_hashed_keys,
const base::Time update_time,
bool replace_existing_values,
base::Time now) { … }
std::optional<base::Time> DoGetLastKAnonymityReported(
sql::Database& db,
const std::string& hashed_key) { … }
void DoUpdateLastKAnonymityReported(sql::Database& db,
const std::string& hashed_key,
base::Time now) { … }
std::optional<std::vector<url::Origin>> DoGetAllInterestGroupOwners(
sql::Database& db,
base::Time expiring_after) { … }
std::optional<std::vector<url::Origin>> DoGetAllInterestGroupJoiningOrigins(
sql::Database& db,
base::Time expiring_after) { … }
bool DoRemoveInterestGroupsMatchingOwnerAndJoiner(sql::Database& db,
url::Origin owner,
url::Origin joining_origin,
base::Time expiring_after) { … }
std::optional<std::vector<std::pair<url::Origin, url::Origin>>>
DoGetAllInterestGroupOwnerJoinerPairs(sql::Database& db,
base::Time expiring_after) { … }
bool GetPreviousWins(sql::Database& db,
const blink::InterestGroupKey& group_key,
base::Time win_time_after,
BiddingBrowserSignalsPtr& output) { … }
bool GetJoinCount(sql::Database& db,
const blink::InterestGroupKey& group_key,
base::Time joined_after,
BiddingBrowserSignalsPtr& output) { … }
bool GetBidCount(sql::Database& db,
const blink::InterestGroupKey& group_key,
base::Time now,
BiddingBrowserSignalsPtr& output) { … }
std::optional<base::Time> DoGetDebugReportLockout(
sql::Database& db,
std::optional<base::Time> ignore_before) { … }
std::optional<DebugReportCooldown> DoGetDebugReportCooldownForOrigin(
sql::Database& db,
const url::Origin& origin,
std::optional<base::Time> ignore_before) { … }
void DoGetDebugReportCooldowns(
sql::Database& db,
const base::flat_set<url::Origin>& origins,
std::optional<base::Time> ignore_before,
DebugReportLockoutAndCooldowns& debug_report_lockout_and_cooldowns) { … }
std::optional<std::vector<std::string>> DoGetInterestGroupNamesForOwner(
sql::Database& db,
const url::Origin& owner,
base::Time now) { … }
std::optional<std::vector<std::string>>
DoGetAllRegularInterestGroupNamesForOwner(sql::Database& db,
const url::Origin& owner) { … }
std::optional<std::vector<std::string>>
DoGetAllNegativeInterestGroupNamesForOwner(sql::Database& db,
const url::Origin& owner) { … }
bool DoGetStoredInterestGroup(sql::Database& db,
StorageInterestGroup& db_interest_group,
const PassKey& passkey,
const blink::InterestGroupKey& group_key,
base::Time now) { … }
std::optional<std::vector<InterestGroupUpdateParameter>>
DoGetInterestGroupsForUpdate(sql::Database& db,
const url::Origin& owner,
base::Time now,
size_t groups_limit) { … }
std::optional<std::vector<StorageInterestGroup>> DoGetInterestGroupsForOwner(
sql::Database& db,
const PassKey& passkey,
const url::Origin& owner,
base::Time now) { … }
std::optional<std::vector<blink::InterestGroupKey>>
DoGetInterestGroupNamesForJoiningOrigin(sql::Database& db,
const url::Origin& joining_origin,
base::Time now) { … }
bool DoDeleteInterestGroupData(
sql::Database& db,
StoragePartition::StorageKeyMatcherFunction storage_key_matcher) { … }
bool DoSetInterestGroupPriority(sql::Database& db,
const blink::InterestGroupKey& group_key,
double priority) { … }
bool DoSetInterestGroupPrioritySignalsOverrides(
sql::Database& db,
const blink::InterestGroupKey& group_key,
const std::optional<base::flat_map<std::string, double>>&
priority_signals_overrides) { … }
bool DeleteOldJoins(sql::Database& db, base::Time cutoff) { … }
bool DeleteOldBids(sql::Database& db, base::Time cutoff) { … }
bool DeleteOldWins(sql::Database& db, base::Time cutoff) { … }
bool DoClearExcessInterestGroups(
sql::Database& db,
const url::Origin& affected_origin,
const std::optional<std::vector<std::string>> maybe_interest_groups,
size_t max_owner_interest_groups) { … }
bool ClearExcessInterestGroups(sql::Database& db,
size_t max_owners,
size_t max_owner_regular_interest_groups,
size_t max_owner_negative_interest_groups) { … }
bool ClearExpiredInterestGroups(sql::Database& db,
base::Time expiration_before) { … }
bool ClearExcessiveStorage(sql::Database& db, size_t max_owner_storage_size) { … }
bool ClearExpiredKAnon(sql::Database& db, base::Time cutoff) { … }
bool DeleteExpiredDebugReportCooldown(sql::Database& db, base::Time now) { … }
bool ClearExpiredBiddingAndAuctionKeys(sql::Database& db, base::Time now) { … }
bool DoSetBiddingAndAuctionServerKeys(
sql::Database& db,
const url::Origin& coordinator,
const std::vector<BiddingAndAuctionServerKey>& keys,
base::Time expiration) { … }
std::pair<base::Time, std::vector<BiddingAndAuctionServerKey>>
DoGetBiddingAndAuctionServerKeys(sql::Database& db,
const url::Origin& coordinator) { … }
bool DoPerformDatabaseMaintenance(sql::Database& db,
base::Time now,
size_t max_owners,
size_t max_owner_storage_size,
size_t max_owner_regular_interest_groups,
size_t max_owner_negative_interest_groups) { … }
base::FilePath DBPath(const base::FilePath& base) { … }
sql::DatabaseOptions GetDatabaseOptions() { … }
void ReportCreateSchemaResult(
bool create_schema_result,
sql::RazeIfIncompatibleResult raze_if_incompatible_result,
bool missing_metatable_razed) { … }
void ReportUpgradeDBResult(bool upgrade_succeeded, int db_version) { … }
}
constexpr base::TimeDelta InterestGroupStorage::kHistoryLength;
constexpr base::TimeDelta InterestGroupStorage::kMaintenanceInterval;
constexpr base::TimeDelta InterestGroupStorage::kIdlePeriod;
constexpr base::TimeDelta InterestGroupStorage::kUpdateSucceededBackoffPeriod;
constexpr base::TimeDelta InterestGroupStorage::kUpdateFailedBackoffPeriod;
InterestGroupStorage::InterestGroupStorage(const base::FilePath& path)
: … { … }
InterestGroupStorage::~InterestGroupStorage() { … }
bool InterestGroupStorage::EnsureDBInitialized() { … }
bool InterestGroupStorage::InitializeDB() { … }
bool InterestGroupStorage::InitializeSchema() { … }
std::optional<InterestGroupKanonUpdateParameter>
InterestGroupStorage::JoinInterestGroup(const blink::InterestGroup& group,
const GURL& main_frame_joining_url) { … }
void InterestGroupStorage::LeaveInterestGroup(
const blink::InterestGroupKey& group_key,
const url::Origin& main_frame) { … }
std::vector<std::string> InterestGroupStorage::ClearOriginJoinedInterestGroups(
const url::Origin& owner,
const std::set<std::string>& interest_groups_to_keep,
const url::Origin& main_frame_origin) { … }
std::optional<base::Time> InterestGroupStorage::GetDebugReportLockout() { … }
std::optional<DebugReportLockoutAndCooldowns>
InterestGroupStorage::GetDebugReportLockoutAndCooldowns(
base::flat_set<url::Origin> origins) { … }
std::optional<InterestGroupKanonUpdateParameter>
InterestGroupStorage::UpdateInterestGroup(
const blink::InterestGroupKey& group_key,
InterestGroupUpdate update) { … }
void InterestGroupStorage::AllowUpdateIfOlderThan(
const blink::InterestGroupKey& group_key,
base::TimeDelta update_if_older_than) { … }
void InterestGroupStorage::ReportUpdateFailed(
const blink::InterestGroupKey& group_key,
bool parse_failure) { … }
void InterestGroupStorage::RecordInterestGroupBids(
const blink::InterestGroupSet& group_keys) { … }
void InterestGroupStorage::RecordInterestGroupWin(
const blink::InterestGroupKey& group_key,
const std::string& ad_json) { … }
void InterestGroupStorage::RecordDebugReportLockout(
base::Time last_report_sent_time) { … }
void InterestGroupStorage::RecordDebugReportCooldown(
const url::Origin& origin,
base::Time cooldown_start,
DebugReportCooldownType cooldown_type) { … }
void InterestGroupStorage::UpdateKAnonymity(
const blink::InterestGroupKey& interest_group_key,
const std::vector<std::string>& positive_hashed_keys,
const base::Time update_time,
bool replace_existing_values) { … }
std::optional<base::Time> InterestGroupStorage::GetLastKAnonymityReported(
const std::string& hashed_key) { … }
void InterestGroupStorage::UpdateLastKAnonymityReported(
const std::string& hashed_key) { … }
std::optional<StorageInterestGroup> InterestGroupStorage::GetInterestGroup(
const blink::InterestGroupKey& group_key) { … }
std::vector<url::Origin> InterestGroupStorage::GetAllInterestGroupOwners() { … }
std::vector<StorageInterestGroup>
InterestGroupStorage::GetInterestGroupsForOwner(const url::Origin& owner) { … }
std::vector<InterestGroupUpdateParameter>
InterestGroupStorage::GetInterestGroupsForUpdate(const url::Origin& owner,
size_t groups_limit) { … }
std::vector<url::Origin>
InterestGroupStorage::GetAllInterestGroupJoiningOrigins() { … }
std::vector<std::pair<url::Origin, url::Origin>>
InterestGroupStorage::GetAllInterestGroupOwnerJoinerPairs() { … }
void InterestGroupStorage::RemoveInterestGroupsMatchingOwnerAndJoiner(
url::Origin owner,
url::Origin joining_origin) { … }
void InterestGroupStorage::DeleteInterestGroupData(
StoragePartition::StorageKeyMatcherFunction storage_key_matcher) { … }
void InterestGroupStorage::DeleteAllInterestGroupData() { … }
void InterestGroupStorage::SetInterestGroupPriority(
const blink::InterestGroupKey& group_key,
double priority) { … }
void InterestGroupStorage::UpdateInterestGroupPriorityOverrides(
const blink::InterestGroupKey& group_key,
base::flat_map<std::string,
auction_worklet::mojom::PrioritySignalsDoublePtr>
update_priority_signals_overrides) { … }
void InterestGroupStorage::PerformDBMaintenance() { … }
std::vector<StorageInterestGroup>
InterestGroupStorage::GetAllInterestGroupsUnfilteredForTesting() { … }
void InterestGroupStorage::SetBiddingAndAuctionServerKeys(
const url::Origin& coordinator,
const std::vector<BiddingAndAuctionServerKey>& keys,
base::Time expiration) { … }
std::pair<base::Time, std::vector<BiddingAndAuctionServerKey>>
InterestGroupStorage::GetBiddingAndAuctionServerKeys(
const url::Origin& coordinator) { … }
base::Time InterestGroupStorage::GetLastMaintenanceTimeForTesting() const { … }
int InterestGroupStorage::GetCurrentVersionNumberForTesting() { … }
void InterestGroupStorage::DatabaseErrorCallback(int extended_error,
sql::Statement* stmt) { … }
}