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
|
// 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_INTEREST_GROUP_INTEREST_GROUP_K_ANONYMITY_MANAGER_H_
#define CONTENT_BROWSER_INTEREST_GROUP_INTEREST_GROUP_K_ANONYMITY_MANAGER_H_
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "content/browser/interest_group/interest_group_caching_storage.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/k_anonymity_service_delegate.h"
#include "third_party/blink/public/common/interest_group/interest_group.h"
namespace content {
class InterestGroupManagerImpl;
// Maximum number of IDs to send in a single query call. Public for testing.
constexpr size_t kQueryBatchSizeLimit = 1000;
// Returns whether `last_updated` is less than 7 days ago.
bool CONTENT_EXPORT IsKAnonDataExpired(const base::Time last_updated,
const base::Time now);
// Manages k-anonymity updates. Checks last updated times in the database
// to limit updates (joins and queries) to once per day. Called by the
// InterestGroupManagerImpl for interest group k-anonymity updates. Calls
// The InterestGroupManagerImpl to access interest group storage to perform
// interest group updates.
class CONTENT_EXPORT InterestGroupKAnonymityManager {
public:
using GetKAnonymityServiceDelegateCallback =
base::RepeatingCallback<KAnonymityServiceDelegate*()>;
InterestGroupKAnonymityManager(
InterestGroupManagerImpl* interest_group_manager,
InterestGroupCachingStorage* caching_storage,
GetKAnonymityServiceDelegateCallback k_anonymity_service_callback);
~InterestGroupKAnonymityManager();
// Requests k-anonymity updates for all interest groups owned by `owners` that
// haven't been updated in 24 hours or more. Results are passed to
// interest_group_manager_->UpdateKAnonymity.
void QueryKAnonymityOfOwners(base::span<const url::Origin> owners);
// Requests the k-anonymity status of elements of `k_anon_data` that
// haven't been updated in 24 hours or more. Results are passed to
// interest_group_manager_->UpdateKAnonymity.
void QueryKAnonymityData(
const blink::InterestGroupKey& interest_group_key,
const InterestGroupKanonUpdateParameter& k_anon_data);
// Notify the k-anonymity service that these ad keys won an auction.
// Internally this calls RegisterIDAsJoined().
void RegisterAdKeysAsJoined(base::flat_set<std::string> hashed_keys);
private:
friend class InterestGroupKAnonymityManagerTestPeer;
struct InProgressQueryState {
InProgressQueryState(base::Time update_time, bool replace_existing_values);
InProgressQueryState(const InProgressQueryState&);
~InProgressQueryState();
base::Time update_time;
bool replace_existing_values;
size_t remaining_responses{0};
std::vector<std::string> positive_hashed_keys_from_received_responses;
};
// Callback from QueryKAnonymityOfOwners
void OnGotInterestGroupsOfOwner(scoped_refptr<StorageInterestGroups> groups);
// Callback from LoadPositiveHashedKAnonymityKeysFromCache
void FetchUncachedKAnonymityData(
base::Time update_time,
const blink::InterestGroupKey& interest_group_key,
InterestGroupStorage::KAnonymityCacheResponse cache_response);
// Callback from k-anonymity service QuerySets().
void QuerySetsCallback(std::vector<std::string> query,
base::Time update_time,
const blink::InterestGroupKey& interest_group_key,
std::vector<bool> status);
// Starts fetching the LastKAnonymityReported time for `url` from the
// database.
void RegisterIDAsJoined(const std::string& hashed_key);
// Called by the database when the update time for `url` has been retrieved.
// If the last reported time is too long ago, calls JoinSet() on the
// k-anonymity service.
void OnGotLastReportedTime(std::string hashed_key,
std::optional<base::Time> last_update_time);
// Callback from k-anonymity service JoinSet(). Updates the LastReported time
// for key in the database, regardless of status (fail close).
void JoinSetCallback(std::string hashed_key, bool status);
// An unowned pointer to the InterestGroupManagerImpl that owns this
// InterestGroupUpdateManager. Used as an intermediary to talk to the
// database.
raw_ptr<InterestGroupManagerImpl> interest_group_manager_;
// An unowned pointer to the interest_group_manager_'s
// InterestGroupCachingStorage. Used to talk to the database directly for
// fetching and storing cached hashed keys only.
raw_ptr<InterestGroupCachingStorage> caching_storage_;
GetKAnonymityServiceDelegateCallback k_anonymity_service_callback_;
// We keep track of joins in progress because the joins that haven't completed
// are still marked as eligible but it would be incorrect to join them
// multiple times. We don't do this for query because the
// size of the request could expose membership in overlapping groups through
// traffic analysis.
base::flat_set<std::string> joins_in_progress_;
// Keep track of updates for which we have not yet written values back to the
// database. When we receive a new QueryKAnonymityData for an interest group
// while there's an outstanding query for the same interest group, we may
// choose to replace the query in progress or add more k-anonymity keys onto
// it.
base::flat_map<blink::InterestGroupKey, InProgressQueryState>
queries_in_progress_;
base::WeakPtrFactory<InterestGroupKAnonymityManager> weak_ptr_factory_;
};
} // namespace content
#endif // CONTENT_BROWSER_INTEREST_GROUP_INTEREST_GROUP_K_ANONYMITY_MANAGER_H_
|