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
content / browser / interest_group / interest_group_k_anonymity_manager.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_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_set.h"
#include "base/memory/raw_ptr.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,
GetKAnonymityServiceDelegateCallback k_anonymity_service_callback);
~InterestGroupKAnonymityManager();
// 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:
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 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_;
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_