| // 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_INTEREST_GROUP_INTEREST_GROUP_STORAGE_H_ |
| #define CONTENT_BROWSER_INTEREST_GROUP_INTEREST_GROUP_STORAGE_H_ |
| |
| #include <vector> |
| |
| #include "base/containers/flat_map.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 "content/browser/interest_group/interest_group_update.h" |
| #include "content/browser/interest_group/storage_interest_group.h" |
| #include "content/common/content_export.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/services/auction_worklet/public/mojom/auction_worklet_service.mojom.h" |
| #include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom-forward.h" |
| #include "sql/database.h" |
| #include "sql/statement.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| |
| namespace blink { |
| struct InterestGroup; |
| } |
| |
| namespace content { |
| |
| // InterestGroupStorage controls access to the Interest Group Database. All |
| // public functions perform operations on the database and may block. This |
| // implementation is not thread-safe so all functions should be called from |
| // within the same sequence. |
| class CONTENT_EXPORT InterestGroupStorage { |
| public: |
| static constexpr base::TimeDelta kHistoryLength = base::Days(30); |
| static constexpr base::TimeDelta kMaintenanceInterval = base::Hours(1); |
| static constexpr base::TimeDelta kIdlePeriod = base::Seconds(30); |
| // Store a KAnon key after its corresponding interest group or ad is |
| // no longer present for this amount longer. |
| static constexpr base::TimeDelta kAdditionalKAnonStoragePeriod = |
| base::Days(1); |
| // After a successful interest group update, delay the next update until |
| // kUpdateSucceededBackoffPeriod time has passed. |
| static constexpr base::TimeDelta kUpdateSucceededBackoffPeriod = |
| base::Days(1); |
| // After a failed interest group update, delay the next update until |
| // kUpdateFailedBackoffPeriod time has passed. |
| static constexpr base::TimeDelta kUpdateFailedBackoffPeriod = base::Hours(1); |
| |
| // Constructs an interest group storage based on a SQLite database in the |
| // `path`/InterestGroups file. If the path passed in is empty, then the |
| // database is instead stored in memory and not persisted to disk. |
| explicit InterestGroupStorage(const base::FilePath& path); |
| InterestGroupStorage(const InterestGroupStorage& other) = delete; |
| InterestGroupStorage& operator=(const InterestGroupStorage& other) = delete; |
| ~InterestGroupStorage(); |
| |
| // Joins an interest group. If the interest group does not exist, a new one |
| // is created based on the provided group information. If the interest group |
| // exists, the existing interest group is overwritten. In either case a join |
| // record for this interest group is created. |
| void JoinInterestGroup(const blink::InterestGroup& group, |
| const GURL& main_frame_joining_url); |
| // Remove the interest group if it exists. |
| void LeaveInterestGroup(const blink::InterestGroupKey& group_key, |
| const url::Origin& main_frame); |
| |
| // Removes all interest groups owned by `owner` joined from |
| // `main_frame_origin` except `interest_groups_to_keep`, if they exist. |
| // Returns a (possibly empty) list of all interest groups that were cleared. |
| std::vector<std::string> ClearOriginJoinedInterestGroups( |
| const url::Origin& owner, |
| const std::set<std::string>& interest_groups_to_keep, |
| const url::Origin& main_frame_origin); |
| |
| // Updates the interest group `name` of `owner` with the populated fields of |
| // `update`. |
| // |
| // If it fails for any reason (e.g., the interest group does not exist, or the |
| // data in `update` is not valid), returns false. |
| bool UpdateInterestGroup(const blink::InterestGroupKey& group_key, |
| InterestGroupUpdate update); |
| // Report that updating of the interest group with owner `owner` and name |
| // `name` failed. With the exception of parse failures, the rate limit |
| // duration for failed updates is shorter than for those that succeed -- for |
| // successes, UpdateInterestGroup() automatically updates the rate limit |
| // duration. |
| void ReportUpdateFailed(const blink::InterestGroupKey& group_key, |
| bool parse_failure); |
| // Adds an entry to the bidding history for these interest groups. |
| void RecordInterestGroupBids(const blink::InterestGroupSet& group); |
| // Adds an entry to the win history for this interest group. `ad_json` is a |
| // piece of opaque data to identify the winning ad. |
| void RecordInterestGroupWin(const blink::InterestGroupKey& group_key, |
| const std::string& ad_json); |
| // Records K-anonymity. |
| void UpdateKAnonymity(const StorageInterestGroup::KAnonymityData& data); |
| |
| // Gets the last time that the key was reported to the k-anonymity server. |
| absl::optional<base::Time> GetLastKAnonymityReported(const std::string& key); |
| // Updates the last time that the key was reported to the k-anonymity server. |
| void UpdateLastKAnonymityReported(const std::string& key); |
| |
| // Gets a single interest group. |
| absl::optional<StorageInterestGroup> GetInterestGroup( |
| const blink::InterestGroupKey& group_key); |
| // Gets a list of all interest group owners. Each owner will only appear |
| // once. |
| std::vector<url::Origin> GetAllInterestGroupOwners(); |
| // Gets a list of all interest groups with their bidding information |
| // associated with the provided owner. |
| std::vector<StorageInterestGroup> GetInterestGroupsForOwner( |
| const url::Origin& owner); |
| // For a given owner, gets interest group keys along with their update URLs |
| // and joining origin. |
| // `groups_limit` sets a limit on the maximum number of interest group keys |
| // that may be returned. |
| std::vector<InterestGroupUpdateParameter> GetInterestGroupsForUpdate( |
| const url::Origin& owner, |
| size_t groups_limit); |
| |
| // Gets all KAnonymityData for ads part of the interest group specified by |
| // `interest_group_key`. |
| std::vector<StorageInterestGroup::KAnonymityData> GetKAnonymityDataForUpdate( |
| blink::InterestGroupKey interest_group_key); |
| |
| // Gets a list of all interest group joining origins. Each joining origin |
| // will only appear once. |
| std::vector<url::Origin> GetAllInterestGroupJoiningOrigins(); |
| |
| std::vector<std::pair<url::Origin, url::Origin>> |
| GetAllInterestGroupOwnerJoinerPairs(); |
| void RemoveInterestGroupsMatchingOwnerAndJoiner(url::Origin owner, |
| url::Origin joining_origin); |
| |
| // Clear out storage for the matching owning storage key. |
| void DeleteInterestGroupData( |
| StoragePartition::StorageKeyMatcherFunction storage_key_matcher); |
| // Clear out all interest group storage including k-anonymity store. |
| void DeleteAllInterestGroupData(); |
| // Update the interest group priority. |
| void SetInterestGroupPriority(const blink::InterestGroupKey& group_key, |
| double priority); |
| |
| // Merges `update_priority_signals_overrides` with the currently stored |
| // priority signals of `group`. Doesn't take the cached overrides from the |
| // caller, which may already have them, in favor of reading them from the |
| // database, as the values may have been updated on disk since they were read |
| // by the caller. |
| void UpdateInterestGroupPriorityOverrides( |
| const blink::InterestGroupKey& group_key, |
| base::flat_map<std::string, |
| auction_worklet::mojom::PrioritySignalsDoublePtr> |
| update_priority_signals_overrides); |
| |
| std::vector<StorageInterestGroup> GetAllInterestGroupsUnfilteredForTesting(); |
| |
| base::Time GetLastMaintenanceTimeForTesting() const; |
| |
| private: |
| bool EnsureDBInitialized(); |
| bool InitializeDB(); |
| bool InitializeSchema(); |
| void PerformDBMaintenance(); |
| void DatabaseErrorCallback(int extended_error, sql::Statement* stmt); |
| |
| const base::FilePath path_to_database_; |
| // Maximum number of interest groups, or interest group owners to keep in the |
| // database. |
| // Set by the related blink::feature parameters |
| // kInterestGroupStorageMaxOwners, |
| // kInterestGroupStorageMaxGroupsPerOwner, and |
| // kInterestGroupStorageMaxNegativeGroupsPerOwner. |
| const size_t max_owners_; |
| const size_t max_owner_regular_interest_groups_; |
| const size_t max_owner_negative_interest_groups_; |
| const size_t max_owner_storage_size_; |
| |
| // Maximum number of operations allowed between maintenance calls. |
| // Set by the related blink::feature parameter |
| // kInterestGroupStorageMaxOpsBeforeMaintenance. |
| const size_t max_ops_before_maintenance_; |
| |
| std::unique_ptr<sql::Database> db_ GUARDED_BY_CONTEXT(sequence_checker_); |
| base::DelayTimer db_maintenance_timer_ GUARDED_BY_CONTEXT(sequence_checker_); |
| base::Time last_access_time_ GUARDED_BY_CONTEXT(sequence_checker_) = |
| base::Time::Min(); |
| base::Time last_maintenance_time_ GUARDED_BY_CONTEXT(sequence_checker_) = |
| base::Time::Min(); |
| unsigned int ops_since_last_maintenance_ |
| GUARDED_BY_CONTEXT(sequence_checker_) = 0; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_INTEREST_GROUP_INTEREST_GROUP_STORAGE_H_ |