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
content / browser / first_party_sets / first_party_sets_handler_impl_instance.h [blame]
// Copyright 2023 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_FIRST_PARTY_SETS_FIRST_PARTY_SETS_HANDLER_IMPL_INSTANCE_H_
#define CONTENT_BROWSER_FIRST_PARTY_SETS_FIRST_PARTY_SETS_HANDLER_IMPL_INSTANCE_H_
#include <optional>
#include <string>
#include <utility>
#include "base/containers/circular_deque.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "base/threading/sequence_bound.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
#include "base/version.h"
#include "content/browser/first_party_sets/first_party_sets_handler_database_helper.h"
#include "content/browser/first_party_sets/first_party_sets_handler_impl.h"
#include "content/browser/first_party_sets/first_party_sets_loader.h"
#include "content/common/content_export.h"
#include "net/first_party_sets/first_party_sets_cache_filter.h"
#include "net/first_party_sets/first_party_sets_context_config.h"
#include "net/first_party_sets/global_first_party_sets.h"
#include "net/first_party_sets/local_set_declaration.h"
namespace net {
class FirstPartySetEntry;
class SchemefulSite;
} // namespace net
namespace content {
class BrowserContext;
// Class FirstPartySetsHandlerImplInstance is a singleton, it allows an embedder
// to provide First-Party Sets inputs from custom sources, then parses/merges
// the inputs to form the current First-Party Sets data, compares them with the
// persisted First-Party Sets data used during the last browser session to get
// a list of sites that changed the First-Party Set they are part of, invokes
// the provided callback with the current First-Party Sets data, and writes
// the current First-Party Sets data to disk.
class CONTENT_EXPORT FirstPartySetsHandlerImplInstance
: public FirstPartySetsHandlerImpl {
public:
~FirstPartySetsHandlerImplInstance() override;
FirstPartySetsHandlerImplInstance(const FirstPartySetsHandlerImplInstance&) =
delete;
FirstPartySetsHandlerImplInstance& operator=(
const FirstPartySetsHandlerImplInstance&) = delete;
// Factory method that exposes the ctor for testing.
static FirstPartySetsHandlerImplInstance CreateForTesting(
bool enabled,
bool embedder_will_provide_public_sets);
// FirstPartySetsHandlerImpl:
void Init(const base::FilePath& user_data_dir,
const net::LocalSetDeclaration& local_set) override;
[[nodiscard]] std::optional<net::GlobalFirstPartySets> GetSets(
base::OnceCallback<void(net::GlobalFirstPartySets)> callback) override;
// FirstPartySetsHandler:
bool IsEnabled() const override;
void SetPublicFirstPartySets(const base::Version& version,
base::File sets_file) override;
std::optional<net::FirstPartySetEntry> FindEntry(
const net::SchemefulSite& site,
const net::FirstPartySetsContextConfig& config) const override;
void GetContextConfigForPolicy(
const base::Value::Dict* policy,
base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback)
override;
void ClearSiteDataOnChangedSetsForContext(
base::RepeatingCallback<BrowserContext*()> browser_context_getter,
const std::string& browser_context_id,
net::FirstPartySetsContextConfig context_config,
base::OnceCallback<void(net::FirstPartySetsContextConfig,
net::FirstPartySetsCacheFilter)> callback)
override;
void ComputeFirstPartySetMetadata(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const net::FirstPartySetsContextConfig& config,
base::OnceCallback<void(net::FirstPartySetMetadata)> callback) override;
bool ForEachEffectiveSetEntry(
const net::FirstPartySetsContextConfig& config,
base::FunctionRef<bool(const net::SchemefulSite&,
const net::FirstPartySetEntry&)> f) const override;
void GetPersistedSetsForTesting(
const std::string& browser_context_id,
base::OnceCallback<
void(std::optional<std::pair<net::GlobalFirstPartySets,
net::FirstPartySetsContextConfig>>)>
callback);
void HasBrowserContextClearedForTesting(
const std::string& browser_context_id,
base::OnceCallback<void(std::optional<bool>)> callback);
void SynchronouslyResetDBHelperForTesting() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
db_helper_.SynchronouslyResetForTest(); // IN-TEST
}
private:
friend class base::NoDestructor<FirstPartySetsHandlerImplInstance>;
FirstPartySetsHandlerImplInstance(bool enabled,
bool embedder_will_provide_public_sets);
// Sets the global First-Party Sets data. Must be called exactly once.
void SetCompleteSets(net::GlobalFirstPartySets sets);
// Sets `db_helper_`, which will initialize the underlying First-Party Sets
// database under `user_data_dir`. Must be called exactly once.
void SetDatabase(const base::FilePath& user_data_dir);
// Enqueues a task to be performed once initialization is complete.
void EnqueuePendingTask(base::OnceClosure run_task);
// Invokes any pending queries.
void InvokePendingQueries();
// Returns the global First-Party Sets. This clones the underlying
// data.
//
// Must be called after the list has been initialized.
net::GlobalFirstPartySets GetGlobalSetsSync() const;
// Performs the actual state clearing for the given context. Must not be
// called until initialization is complete.
void ClearSiteDataOnChangedSetsForContextInternal(
base::RepeatingCallback<BrowserContext*()> browser_context_getter,
const std::string& browser_context_id,
net::FirstPartySetsContextConfig context_config,
base::OnceCallback<void(net::FirstPartySetsContextConfig,
net::FirstPartySetsCacheFilter)> callback);
// Like ComputeFirstPartySetMetadata, but passes the result into the provided
// callback. Must not be called before `global_sets_` has been set.
void ComputeFirstPartySetMetadataInternal(
const net::SchemefulSite& site,
const std::optional<net::SchemefulSite>& top_frame_site,
const net::FirstPartySetsContextConfig& config,
const base::ElapsedTimer& timer,
base::OnceCallback<void(net::FirstPartySetMetadata)> callback) const;
// Parses the policy and computes the config that represents the changes
// needed to apply `policy` to `global_sets_`.
net::FirstPartySetsContextConfig GetContextConfigForPolicyInternal(
const base::Value::Dict& policy,
const std::optional<base::ElapsedTimer>& timer) const;
void OnGetSitesToClear(
base::RepeatingCallback<BrowserContext*()> browser_context_getter,
const std::string& browser_context_id,
net::FirstPartySetsContextConfig context_config,
base::OnceCallback<void(net::FirstPartySetsContextConfig,
net::FirstPartySetsCacheFilter)> callback,
std::optional<std::pair<std::vector<net::SchemefulSite>,
net::FirstPartySetsCacheFilter>> sites_to_clear)
const;
// `failed_data_types` is a bitmask used to indicate data types from
// BrowsingDataRemover::DataType enum that were failed to remove. 0 indicates
// success.
void DidClearSiteDataOnChangedSetsForContext(
const std::string& browser_context_id,
net::FirstPartySetsContextConfig context_config,
net::FirstPartySetsCacheFilter cache_filter,
base::OnceCallback<void(net::FirstPartySetsContextConfig,
net::FirstPartySetsCacheFilter)> callback,
uint64_t failed_data_types) const;
// Whether Init has been called already or not.
bool initialized_ = false;
// The global First-Party Sets, after parsing and validation.
//
// This is nullopt until all of the required inputs have been received.
std::optional<net::GlobalFirstPartySets> global_sets_
GUARDED_BY_CONTEXT(sequence_checker_);
// Whether the First-Party Sets feature should behave as "enabled" or not,
// according to the embedder.
const bool enabled_ GUARDED_BY_CONTEXT(sequence_checker_);
// A queue of tasks waiting to run once this instance has the full
// GlobalFirstPartySets instance. If `enabled_` is true, then this queue is
// non-null until `global_sets_` is non-nullopt. Otherwise, it is always
// nullptr.
std::unique_ptr<base::circular_deque<base::OnceClosure>>
on_sets_ready_callbacks_ GUARDED_BY_CONTEXT(sequence_checker_);
// A helper object to handle loading and combining First-Party Sets from
// different sources (i.e. the command-line flag and the list provided by the
// embedder). This is nullptr if `enabled_` is false; and it is nullptr after
// `global_sets_` has been set.
std::unique_ptr<FirstPartySetsLoader> sets_loader_
GUARDED_BY_CONTEXT(sequence_checker_);
// Timer starting when the first async task was enqueued, if any. Used for
// metrics.
std::optional<base::ElapsedTimer> first_async_task_timer_
GUARDED_BY_CONTEXT(sequence_checker_);
// Access the underlying DB on a database sequence to make sure none of DB
// operations that support blocking are called directly on the main thread.
base::SequenceBound<FirstPartySetsHandlerDatabaseHelper> db_helper_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace content
#endif // CONTENT_BROWSER_FIRST_PARTY_SETS_FIRST_PARTY_SETS_HANDLER_IMPL_INSTANCE_H_