1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.h"
6
7 #include <list>
8 #include <map>
9 #include <memory>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/feature_list.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/functional/bind.h"
18 #include "base/functional/callback_helpers.h"
19 #include "base/json/json_reader.h"
20 #include "base/json/json_string_value_serializer.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/task/sequenced_task_runner.h"
23 #include "base/task/task_traits.h"
24 #include "base/thread_annotations.h"
25 #include "net/base/features.h"
26 #include "net/base/network_anonymization_key.h"
27 #include "net/extras/sqlite/sqlite_persistent_store_backend_base.h"
28 #include "net/reporting/reporting_endpoint.h"
29 #include "sql/database.h"
30 #include "sql/meta_table.h"
31 #include "sql/statement.h"
32 #include "sql/transaction.h"
33 #include "url/origin.h"
34
35 namespace net {
36
37 namespace {
38 // Version 1 - 2019/03 - crrev.com/c/1504493, crrev.com/c/1560456
39 //
40 // Version 1 adds tables for NEL policies, Reporting endpoints, and Reporting
41 // endpoint groups.
42 //
43 // Version 2 - 2020/10 - https://crrev.com/c/2485253
44 //
45 // Version 2 adds NetworkAnonymizationKey fields to all entries. When migrating,
46 // existing entries get an empty NetworkAnonymizationKey value.
47 const int kCurrentVersionNumber = 2;
48 const int kCompatibleVersionNumber = 2;
49
50 // Histogram names
51 const char kNumberOfLoadedNelPoliciesHistogramName[] =
52 "ReportingAndNEL.NumberOfLoadedNELPolicies";
53 const char kNumberOfLoadedNelPolicies2HistogramName[] =
54 "ReportingAndNEL.NumberOfLoadedNELPolicies2";
55 const char kNumberOfLoadedReportingEndpoints2HistogramName[] =
56 "ReportingAndNEL.NumberOfLoadedReportingEndpoints2";
57 const char kNumberOfLoadedReportingEndpointGroups2HistogramName[] =
58 "ReportingAndNEL.NumberOfLoadedReportingEndpointGroups2";
59 } // namespace
60
GetReportingAndNelStoreBackgroundSequencePriority()61 base::TaskPriority GetReportingAndNelStoreBackgroundSequencePriority() {
62 return base::TaskPriority::USER_BLOCKING;
63 }
64
65 // Converts a NetworkAnonymizationKey to a string for serializing to disk.
66 // Returns false on failure, which happens for transient keys that should not be
67 // serialized to disk.
NetworkAnonymizationKeyToString(const NetworkAnonymizationKey & network_anonymization_key,std::string * out_string)68 [[nodiscard]] bool NetworkAnonymizationKeyToString(
69 const NetworkAnonymizationKey& network_anonymization_key,
70 std::string* out_string) {
71 base::Value value;
72 if (!network_anonymization_key.ToValue(&value))
73 return false;
74 return JSONStringValueSerializer(out_string).Serialize(value);
75 }
76
77 // Attempts to convert a string returned by NetworkAnonymizationKeyToString() to
78 // a NetworkAnonymizationKey. Returns false on failure.
NetworkAnonymizationKeyFromString(const std::string & string,NetworkAnonymizationKey * out_network_anonymization_key)79 [[nodiscard]] bool NetworkAnonymizationKeyFromString(
80 const std::string& string,
81 NetworkAnonymizationKey* out_network_anonymization_key) {
82 std::optional<base::Value> value = base::JSONReader::Read(string);
83 if (!value)
84 return false;
85
86 if (!NetworkAnonymizationKey::FromValue(*value,
87 out_network_anonymization_key))
88 return false;
89
90 // If network state partitionining is disabled, but the
91 // NetworkAnonymizationKeys is non-empty, ignore the entry. The entry will
92 // still be in the on-disk database, in case NAKs are re-enabled, it just
93 // won't be loaded into memory. The entry could still be loaded with an empty
94 // NetworkAnonymizationKey, but that would require logic to resolve conflicts.
95 if (!out_network_anonymization_key->IsEmpty() &&
96 !NetworkAnonymizationKey::IsPartitioningEnabled()) {
97 *out_network_anonymization_key = NetworkAnonymizationKey();
98 return false;
99 }
100
101 return true;
102 }
103
104 class SQLitePersistentReportingAndNelStore::Backend
105 : public SQLitePersistentStoreBackendBase {
106 public:
Backend(const base::FilePath & path,const scoped_refptr<base::SequencedTaskRunner> & client_task_runner,const scoped_refptr<base::SequencedTaskRunner> & background_task_runner)107 Backend(
108 const base::FilePath& path,
109 const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
110 const scoped_refptr<base::SequencedTaskRunner>& background_task_runner)
111 : SQLitePersistentStoreBackendBase(
112 path,
113 /* histogram_tag = */ "ReportingAndNEL",
114 kCurrentVersionNumber,
115 kCompatibleVersionNumber,
116 background_task_runner,
117 client_task_runner,
118 /*enable_exclusive_access=*/false) {}
119
120 Backend(const Backend&) = delete;
121 Backend& operator=(const Backend&) = delete;
122
123 void LoadNelPolicies(NelPoliciesLoadedCallback loaded_callback);
124 void AddNelPolicy(const NetworkErrorLoggingService::NelPolicy& policy);
125 void UpdateNelPolicyAccessTime(
126 const NetworkErrorLoggingService::NelPolicy& policy);
127 void DeleteNelPolicy(const NetworkErrorLoggingService::NelPolicy& policy);
128
129 void LoadReportingClients(ReportingClientsLoadedCallback loaded_callback);
130 void AddReportingEndpoint(const ReportingEndpoint& endpoint);
131 void AddReportingEndpointGroup(const CachedReportingEndpointGroup& group);
132 void UpdateReportingEndpointGroupAccessTime(
133 const CachedReportingEndpointGroup& group);
134 void UpdateReportingEndpointDetails(const ReportingEndpoint& endpoint);
135 void UpdateReportingEndpointGroupDetails(
136 const CachedReportingEndpointGroup& group);
137 void DeleteReportingEndpoint(const ReportingEndpoint& endpoint);
138 void DeleteReportingEndpointGroup(const CachedReportingEndpointGroup& group);
139
140 // Gets the number of queued operations.
141 size_t GetQueueLengthForTesting() const;
142
143 private:
~Backend()144 ~Backend() override {
145 DCHECK(nel_policy_pending_ops_.empty());
146 DCHECK(reporting_endpoint_pending_ops_.empty());
147 DCHECK(reporting_endpoint_group_pending_ops_.empty());
148 DCHECK_EQ(0u, num_pending_);
149 }
150
151 // Represents a mutating operation to the database, specified by a type (add,
152 // update access time, update data, or delete) and data representing the entry
153 // in the database to be added/updated/deleted.
154 template <typename DataType>
155 class PendingOperation;
156
157 // Types of PendingOperation. Here to avoid templatizing the enum.
158 enum class PendingOperationType {
159 ADD,
160 UPDATE_ACCESS_TIME,
161 UPDATE_DETAILS,
162 DELETE
163 };
164
165 // List of pending operations for a particular entry in the database.
166 template <typename DataType>
167 using PendingOperationsVector =
168 std::vector<std::unique_ptr<PendingOperation<DataType>>>;
169
170 // A copy of the information relevant to a NEL policy.
171 struct NelPolicyInfo;
172 // A copy of the information relevant to a Reporting endpoint.
173 struct ReportingEndpointInfo;
174 // A copy of the information relevant to a Reporting endpoint group.
175 struct ReportingEndpointGroupInfo;
176 // TODO(chlily): add ReportingReportInfo.
177
178 // Uniquely identifies an endpoint in the store.
179 using ReportingEndpointKey = std::pair<ReportingEndpointGroupKey, GURL>;
180
181 // Map of pending operations for each entry in the database.
182 // Key types are: - url::Origin for NEL policies,
183 // - ReportingEndpointKey for Reporting endpoints,
184 // - ReportingEndpointGroupKey for Reporting endpoint groups
185 // (defined in //net/reporting/reporting_endpoint.h).
186 template <typename KeyType, typename DataType>
187 using QueueType = std::map<KeyType, PendingOperationsVector<DataType>>;
188
189 // SQLitePersistentStoreBackendBase implementation
190 bool CreateDatabaseSchema() override;
191 std::optional<int> DoMigrateDatabaseSchema() override;
192 void DoCommit() override;
193
194 // Commit a pending operation pertaining to a NEL policy.
195 // Returns true on success.
196 bool CommitNelPolicyOperation(PendingOperation<NelPolicyInfo>* op);
197 // Commit a pending operation pertaining to a Reporting endpoint.
198 // Returns true on success.
199 bool CommitReportingEndpointOperation(
200 PendingOperation<ReportingEndpointInfo>* op);
201 // Commit a pending operation pertaining to a Reporting endpoint group.
202 // Returns true on success.
203 bool CommitReportingEndpointGroupOperation(
204 PendingOperation<ReportingEndpointGroupInfo>* op);
205
206 // Add a pending operation to the appropriate queue.
207 template <typename KeyType, typename DataType>
208 void BatchOperation(KeyType key,
209 std::unique_ptr<PendingOperation<DataType>> po,
210 QueueType<KeyType, DataType>* queue);
211
212 // If there are existing pending operations for a given key, potentially
213 // remove some of the existing operations before adding |new_op|.
214 // In particular, if |new_op| is a deletion, then all the previous pending
215 // operations are made irrelevant and can be deleted. If |new_op| is an
216 // update-access-time, and the last operation in |ops_for_key| is also an
217 // update-access-time, then it can be discarded because |new_op| is about to
218 // overwrite the access time with a new value anyway. Similarly for
219 // update-details.
220 template <typename DataType>
221 void MaybeCoalesceOperations(PendingOperationsVector<DataType>* ops_for_key,
222 PendingOperation<DataType>* new_op)
223 EXCLUSIVE_LOCKS_REQUIRED(lock_);
224
225 // After adding a pending operation to one of the pending operations queues,
226 // this method posts a task to commit all pending operations if we reached the
227 // batch size, or starts a timer to commit after a time interval if we just
228 // started a new batch. |num_pending| is the total number of pending
229 // operations after the one we just added.
230 void OnOperationBatched(size_t num_pending);
231
232 // Loads NEL policies into a vector in the background, then posts a
233 // task to the client task runner to call |loaded_callback| with the loaded
234 // NEL policies.
235 void LoadNelPoliciesAndNotifyInBackground(
236 NelPoliciesLoadedCallback loaded_callback);
237
238 // Calls |loaded_callback| with the loaded NEL policies (which may be empty if
239 // loading was unsuccessful). If loading was successful, also report metrics.
240 void CompleteLoadNelPoliciesAndNotifyInForeground(
241 NelPoliciesLoadedCallback loaded_callback,
242 std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies,
243 bool load_success);
244
245 // Loads Reporting endpoints and endpoint groups into two vectors in the
246 // background, then posts a task to the client task runner to call
247 // |loaded_callback| with the loaded endpoints and endpoint groups.
248 void LoadReportingClientsAndNotifyInBackground(
249 ReportingClientsLoadedCallback loaded_callback);
250
251 // Calls |loaded_callback| with the loaded endpoints and endpoint groups
252 // (which may be empty if loading was unsuccessful). If loading was
253 // successful, also report metrics.
254 void CompleteLoadReportingClientsAndNotifyInForeground(
255 ReportingClientsLoadedCallback loaded_callback,
256 std::vector<ReportingEndpoint> loaded_endpoints,
257 std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups,
258 bool load_success);
259
260 void RecordNumberOfLoadedNelPolicies(size_t count);
261 void RecordNumberOfLoadedReportingEndpoints(size_t count);
262 void RecordNumberOfLoadedReportingEndpointGroups(size_t count);
263
264 // Total number of pending operations (may not match the sum of the number of
265 // elements in the pending operations queues, due to operation coalescing).
266 size_t num_pending_ GUARDED_BY(lock_) = 0;
267
268 // Queue of pending operations pertaining to NEL policies, keyed on origin.
269 QueueType<NetworkErrorLoggingService::NelPolicyKey, NelPolicyInfo>
270 nel_policy_pending_ops_ GUARDED_BY(lock_);
271 // Queue of pending operations pertaining to Reporting endpoints, keyed on
272 // origin, group name, and url.
273 QueueType<ReportingEndpointKey, ReportingEndpointInfo>
274 reporting_endpoint_pending_ops_ GUARDED_BY(lock_);
275 // Queue of pending operations pertaining to Reporting endpoint groups, keyed
276 // on origin and group name.
277 QueueType<ReportingEndpointGroupKey, ReportingEndpointGroupInfo>
278 reporting_endpoint_group_pending_ops_ GUARDED_BY(lock_);
279
280 // TODO(chlily): add reporting_report_pending_ops_ for Reporting reports.
281
282 // Protects |num_pending_|, and all the pending operations queues.
283 mutable base::Lock lock_;
284 };
285
286 namespace {
287
CreateV2NelPoliciesSchema(sql::Database * db)288 bool CreateV2NelPoliciesSchema(sql::Database* db) {
289 DCHECK(!db->DoesTableExist("nel_policies"));
290
291 std::string stmt =
292 "CREATE TABLE nel_policies ("
293 " nik TEXT NOT NULL,"
294 " origin_scheme TEXT NOT NULL,"
295 " origin_host TEXT NOT NULL,"
296 " origin_port INTEGER NOT NULL,"
297 " received_ip_address TEXT NOT NULL,"
298 " group_name TEXT NOT NULL,"
299 " expires_us_since_epoch INTEGER NOT NULL,"
300 " success_fraction REAL NOT NULL,"
301 " failure_fraction REAL NOT NULL,"
302 " is_include_subdomains INTEGER NOT NULL,"
303 " last_access_us_since_epoch INTEGER NOT NULL,"
304 // Each (origin, nik) specifies at most one NEL policy.
305 " UNIQUE (origin_scheme, origin_host, origin_port, nik)"
306 ")";
307
308 return db->Execute(stmt.c_str());
309 }
310
CreateV2ReportingEndpointsSchema(sql::Database * db)311 bool CreateV2ReportingEndpointsSchema(sql::Database* db) {
312 DCHECK(!db->DoesTableExist("reporting_endpoints"));
313
314 std::string stmt =
315 "CREATE TABLE reporting_endpoints ("
316 " nik TEXT NOT NULL,"
317 " origin_scheme TEXT NOT NULL,"
318 " origin_host TEXT NOT NULL,"
319 " origin_port INTEGER NOT NULL,"
320 " group_name TEXT NOT NULL,"
321 " url TEXT NOT NULL,"
322 " priority INTEGER NOT NULL,"
323 " weight INTEGER NOT NULL,"
324 // Each (origin, group, url, nik) tuple specifies at most one endpoint.
325 " UNIQUE (origin_scheme, origin_host, origin_port, group_name, url, nik)"
326 ")";
327
328 return db->Execute(stmt.c_str());
329 }
330
CreateV2ReportingEndpointGroupsSchema(sql::Database * db)331 bool CreateV2ReportingEndpointGroupsSchema(sql::Database* db) {
332 DCHECK(!db->DoesTableExist("reporting_endpoint_groups"));
333
334 std::string stmt =
335 "CREATE TABLE reporting_endpoint_groups ("
336 " nik TEXT NOT NULL,"
337 " origin_scheme TEXT NOT NULL,"
338 " origin_host TEXT NOT NULL,"
339 " origin_port INTEGER NOT NULL,"
340 " group_name TEXT NOT NULL,"
341 " is_include_subdomains INTEGER NOT NULL,"
342 " expires_us_since_epoch INTEGER NOT NULL,"
343 " last_access_us_since_epoch INTEGER NOT NULL,"
344 // Each (origin, group, nik) tuple specifies at most one endpoint group.
345 " UNIQUE (origin_scheme, origin_host, origin_port, group_name, nik)"
346 ")";
347
348 return db->Execute(stmt.c_str());
349 }
350
351 } // namespace
352
353 template <typename DataType>
354 class SQLitePersistentReportingAndNelStore::Backend::PendingOperation {
355 public:
PendingOperation(PendingOperationType type,DataType data)356 PendingOperation(PendingOperationType type, DataType data)
357 : type_(type), data_(std::move(data)) {}
358
type() const359 PendingOperationType type() const { return type_; }
data() const360 const DataType& data() const { return data_; }
361
362 private:
363 const PendingOperationType type_;
364 const DataType data_;
365 };
366
367 // Makes a copy of the relevant information about a NelPolicy, stored in a
368 // form suitable for adding to the database.
369 // TODO(chlily): Add NIK.
370 struct SQLitePersistentReportingAndNelStore::Backend::NelPolicyInfo {
371 // This should only be invoked through CreatePendingOperation().
NelPolicyInfonet::SQLitePersistentReportingAndNelStore::Backend::NelPolicyInfo372 NelPolicyInfo(const NetworkErrorLoggingService::NelPolicy& nel_policy,
373 std::string network_anonymization_key_string)
374 : network_anonymization_key_string(
375 std::move(network_anonymization_key_string)),
376 origin_scheme(nel_policy.key.origin.scheme()),
377 origin_host(nel_policy.key.origin.host()),
378 origin_port(nel_policy.key.origin.port()),
379 received_ip_address(nel_policy.received_ip_address.ToString()),
380 report_to(nel_policy.report_to),
381 expires_us_since_epoch(
382 nel_policy.expires.ToDeltaSinceWindowsEpoch().InMicroseconds()),
383 success_fraction(nel_policy.success_fraction),
384 failure_fraction(nel_policy.failure_fraction),
385 is_include_subdomains(nel_policy.include_subdomains),
386 last_access_us_since_epoch(
387 nel_policy.last_used.ToDeltaSinceWindowsEpoch().InMicroseconds()) {}
388
389 // Creates the specified operation for the given policy. Returns nullptr for
390 // endpoints with transient NetworkAnonymizationKeys.
391 static std::unique_ptr<PendingOperation<NelPolicyInfo>>
CreatePendingOperationnet::SQLitePersistentReportingAndNelStore::Backend::NelPolicyInfo392 CreatePendingOperation(
393 PendingOperationType type,
394 const NetworkErrorLoggingService::NelPolicy& nel_policy) {
395 std::string network_anonymization_key_string;
396 if (!NetworkAnonymizationKeyToString(
397 nel_policy.key.network_anonymization_key,
398 &network_anonymization_key_string)) {
399 return nullptr;
400 }
401
402 return std::make_unique<PendingOperation<NelPolicyInfo>>(
403 type,
404 NelPolicyInfo(nel_policy, std::move(network_anonymization_key_string)));
405 }
406
407 // NetworkAnonymizationKey associated with the request that received the
408 // policy, converted to a string via NetworkAnonymizationKeyToString().
409 std::string network_anonymization_key_string;
410
411 // Origin the policy was received from.
412 std::string origin_scheme;
413 std::string origin_host;
414 int origin_port = 0;
415
416 // IP address of the server that the policy was received from.
417 std::string received_ip_address;
418 // The Reporting group which the policy specifies.
419 std::string report_to;
420 // When the policy expires, in microseconds since the Windows epoch.
421 int64_t expires_us_since_epoch = 0;
422 // Sampling fractions.
423 double success_fraction = 0.0;
424 double failure_fraction = 1.0;
425 // Whether the policy applies to subdomains of the origin.
426 bool is_include_subdomains = false;
427 // Last time the policy was updated or used, in microseconds since the
428 // Windows epoch.
429 int64_t last_access_us_since_epoch = 0;
430 };
431
432 // Makes a copy of the relevant information about a ReportingEndpoint, stored in
433 // a form suitable for adding to the database.
434 struct SQLitePersistentReportingAndNelStore::Backend::ReportingEndpointInfo {
435 // This should only be invoked through CreatePendingOperation().
ReportingEndpointInfonet::SQLitePersistentReportingAndNelStore::Backend::ReportingEndpointInfo436 ReportingEndpointInfo(const ReportingEndpoint& endpoint,
437 std::string network_anonymization_key_string)
438 : network_anonymization_key_string(
439 std::move(network_anonymization_key_string)),
440 origin_scheme(endpoint.group_key.origin.scheme()),
441 origin_host(endpoint.group_key.origin.host()),
442 origin_port(endpoint.group_key.origin.port()),
443 group_name(endpoint.group_key.group_name),
444 url(endpoint.info.url.spec()),
445 priority(endpoint.info.priority),
446 weight(endpoint.info.weight) {}
447
448 // Creates the specified operation for the given endpoint. Returns nullptr for
449 // endpoints with transient NetworkAnonymizationKeys.
450 static std::unique_ptr<PendingOperation<ReportingEndpointInfo>>
CreatePendingOperationnet::SQLitePersistentReportingAndNelStore::Backend::ReportingEndpointInfo451 CreatePendingOperation(PendingOperationType type,
452 const ReportingEndpoint& endpoint) {
453 std::string network_anonymization_key_string;
454 if (!NetworkAnonymizationKeyToString(
455 endpoint.group_key.network_anonymization_key,
456 &network_anonymization_key_string)) {
457 return nullptr;
458 }
459
460 return std::make_unique<PendingOperation<ReportingEndpointInfo>>(
461 type, ReportingEndpointInfo(
462 endpoint, std::move(network_anonymization_key_string)));
463 }
464
465 // NetworkAnonymizationKey associated with the endpoint, converted to a string
466 // via NetworkAnonymizationKeyString().
467 std::string network_anonymization_key_string;
468
469 // Origin the endpoint was received from.
470 std::string origin_scheme;
471 std::string origin_host;
472 int origin_port = 0;
473
474 // Name of the group the endpoint belongs to.
475 std::string group_name;
476 // URL of the endpoint.
477 std::string url;
478 // Priority of the endpoint.
479 int priority = ReportingEndpoint::EndpointInfo::kDefaultPriority;
480 // Weight of the endpoint.
481 int weight = ReportingEndpoint::EndpointInfo::kDefaultWeight;
482 };
483
484 struct SQLitePersistentReportingAndNelStore::Backend::
485 ReportingEndpointGroupInfo {
ReportingEndpointGroupInfonet::SQLitePersistentReportingAndNelStore::Backend::ReportingEndpointGroupInfo486 ReportingEndpointGroupInfo(const CachedReportingEndpointGroup& group,
487 std::string network_anonymization_key_string)
488 : network_anonymization_key_string(
489 std::move(network_anonymization_key_string)),
490 origin_scheme(group.group_key.origin.scheme()),
491 origin_host(group.group_key.origin.host()),
492 origin_port(group.group_key.origin.port()),
493 group_name(group.group_key.group_name),
494 is_include_subdomains(group.include_subdomains ==
495 OriginSubdomains::INCLUDE),
496 expires_us_since_epoch(
497 group.expires.ToDeltaSinceWindowsEpoch().InMicroseconds()),
498 last_access_us_since_epoch(
499 group.last_used.ToDeltaSinceWindowsEpoch().InMicroseconds()) {}
500
501 // Creates the specified operation for the given endpoint reporting group.
502 // Returns nullptr for groups with transient NetworkAnonymizationKeys.
503 static std::unique_ptr<PendingOperation<ReportingEndpointGroupInfo>>
CreatePendingOperationnet::SQLitePersistentReportingAndNelStore::Backend::ReportingEndpointGroupInfo504 CreatePendingOperation(PendingOperationType type,
505 const CachedReportingEndpointGroup& group) {
506 std::string network_anonymization_key_string;
507 if (!NetworkAnonymizationKeyToString(
508 group.group_key.network_anonymization_key,
509 &network_anonymization_key_string)) {
510 return nullptr;
511 }
512
513 return std::make_unique<PendingOperation<ReportingEndpointGroupInfo>>(
514 type, ReportingEndpointGroupInfo(
515 group, std::move(network_anonymization_key_string)));
516 }
517
518 // NetworkAnonymizationKey associated with the endpoint group, converted to a
519 // string via NetworkAnonymizationKeyToString().
520 std::string network_anonymization_key_string;
521
522 // Origin the endpoint group was received from.
523 std::string origin_scheme;
524 std::string origin_host;
525 int origin_port = 0;
526
527 // Name of the group.
528 std::string group_name;
529 // Whether the group applies to subdomains of the origin.
530 bool is_include_subdomains = false;
531 // When the group expires, in microseconds since the Windows epoch.
532 int64_t expires_us_since_epoch = 0;
533 // Last time the group was updated or used, in microseconds since the Windows
534 // epoch.
535 int64_t last_access_us_since_epoch = 0;
536 };
537
LoadNelPolicies(NelPoliciesLoadedCallback loaded_callback)538 void SQLitePersistentReportingAndNelStore::Backend::LoadNelPolicies(
539 NelPoliciesLoadedCallback loaded_callback) {
540 PostBackgroundTask(
541 FROM_HERE, base::BindOnce(&Backend::LoadNelPoliciesAndNotifyInBackground,
542 this, std::move(loaded_callback)));
543 }
544
AddNelPolicy(const NetworkErrorLoggingService::NelPolicy & policy)545 void SQLitePersistentReportingAndNelStore::Backend::AddNelPolicy(
546 const NetworkErrorLoggingService::NelPolicy& policy) {
547 auto po =
548 NelPolicyInfo::CreatePendingOperation(PendingOperationType::ADD, policy);
549 if (!po)
550 return;
551 BatchOperation(policy.key, std::move(po), &nel_policy_pending_ops_);
552 }
553
UpdateNelPolicyAccessTime(const NetworkErrorLoggingService::NelPolicy & policy)554 void SQLitePersistentReportingAndNelStore::Backend::UpdateNelPolicyAccessTime(
555 const NetworkErrorLoggingService::NelPolicy& policy) {
556 auto po = NelPolicyInfo::CreatePendingOperation(
557 PendingOperationType::UPDATE_ACCESS_TIME, policy);
558 if (!po)
559 return;
560 BatchOperation(policy.key, std::move(po), &nel_policy_pending_ops_);
561 }
562
DeleteNelPolicy(const NetworkErrorLoggingService::NelPolicy & policy)563 void SQLitePersistentReportingAndNelStore::Backend::DeleteNelPolicy(
564 const NetworkErrorLoggingService::NelPolicy& policy) {
565 auto po = NelPolicyInfo::CreatePendingOperation(PendingOperationType::DELETE,
566 policy);
567 if (!po)
568 return;
569 BatchOperation(policy.key, std::move(po), &nel_policy_pending_ops_);
570 }
571
LoadReportingClients(ReportingClientsLoadedCallback loaded_callback)572 void SQLitePersistentReportingAndNelStore::Backend::LoadReportingClients(
573 ReportingClientsLoadedCallback loaded_callback) {
574 PostBackgroundTask(
575 FROM_HERE,
576 base::BindOnce(&Backend::LoadReportingClientsAndNotifyInBackground, this,
577 std::move(loaded_callback)));
578 }
579
AddReportingEndpoint(const ReportingEndpoint & endpoint)580 void SQLitePersistentReportingAndNelStore::Backend::AddReportingEndpoint(
581 const ReportingEndpoint& endpoint) {
582 auto po = ReportingEndpointInfo::CreatePendingOperation(
583 PendingOperationType::ADD, endpoint);
584 if (!po)
585 return;
586 ReportingEndpointKey key = std::pair(endpoint.group_key, endpoint.info.url);
587 BatchOperation(std::move(key), std::move(po),
588 &reporting_endpoint_pending_ops_);
589 }
590
AddReportingEndpointGroup(const CachedReportingEndpointGroup & group)591 void SQLitePersistentReportingAndNelStore::Backend::AddReportingEndpointGroup(
592 const CachedReportingEndpointGroup& group) {
593 auto po = ReportingEndpointGroupInfo::CreatePendingOperation(
594 PendingOperationType::ADD, group);
595 if (!po)
596 return;
597 BatchOperation(group.group_key, std::move(po),
598 &reporting_endpoint_group_pending_ops_);
599 }
600
601 void SQLitePersistentReportingAndNelStore::Backend::
UpdateReportingEndpointGroupAccessTime(const CachedReportingEndpointGroup & group)602 UpdateReportingEndpointGroupAccessTime(
603 const CachedReportingEndpointGroup& group) {
604 auto po = ReportingEndpointGroupInfo::CreatePendingOperation(
605 PendingOperationType::UPDATE_ACCESS_TIME, group);
606 if (!po)
607 return;
608 BatchOperation(group.group_key, std::move(po),
609 &reporting_endpoint_group_pending_ops_);
610 }
611
612 void SQLitePersistentReportingAndNelStore::Backend::
UpdateReportingEndpointDetails(const ReportingEndpoint & endpoint)613 UpdateReportingEndpointDetails(const ReportingEndpoint& endpoint) {
614 auto po = ReportingEndpointInfo::CreatePendingOperation(
615 PendingOperationType::UPDATE_DETAILS, endpoint);
616 if (!po)
617 return;
618 ReportingEndpointKey key = std::pair(endpoint.group_key, endpoint.info.url);
619 BatchOperation(std::move(key), std::move(po),
620 &reporting_endpoint_pending_ops_);
621 }
622
623 void SQLitePersistentReportingAndNelStore::Backend::
UpdateReportingEndpointGroupDetails(const CachedReportingEndpointGroup & group)624 UpdateReportingEndpointGroupDetails(
625 const CachedReportingEndpointGroup& group) {
626 auto po = ReportingEndpointGroupInfo::CreatePendingOperation(
627 PendingOperationType::UPDATE_DETAILS, group);
628 if (!po)
629 return;
630 BatchOperation(group.group_key, std::move(po),
631 &reporting_endpoint_group_pending_ops_);
632 }
633
DeleteReportingEndpoint(const ReportingEndpoint & endpoint)634 void SQLitePersistentReportingAndNelStore::Backend::DeleteReportingEndpoint(
635 const ReportingEndpoint& endpoint) {
636 auto po = ReportingEndpointInfo::CreatePendingOperation(
637 PendingOperationType::DELETE, endpoint);
638 if (!po)
639 return;
640 ReportingEndpointKey key = std::pair(endpoint.group_key, endpoint.info.url);
641 BatchOperation(std::move(key), std::move(po),
642 &reporting_endpoint_pending_ops_);
643 }
644
645 void SQLitePersistentReportingAndNelStore::Backend::
DeleteReportingEndpointGroup(const CachedReportingEndpointGroup & group)646 DeleteReportingEndpointGroup(const CachedReportingEndpointGroup& group) {
647 auto po = ReportingEndpointGroupInfo::CreatePendingOperation(
648 PendingOperationType::DELETE, group);
649 if (!po)
650 return;
651 BatchOperation(group.group_key, std::move(po),
652 &reporting_endpoint_group_pending_ops_);
653 }
654
GetQueueLengthForTesting() const655 size_t SQLitePersistentReportingAndNelStore::Backend::GetQueueLengthForTesting()
656 const {
657 size_t count = 0;
658 {
659 base::AutoLock locked(lock_);
660 for (auto& key_and_pending_ops : nel_policy_pending_ops_) {
661 count += key_and_pending_ops.second.size();
662 }
663 for (auto& key_and_pending_ops : reporting_endpoint_pending_ops_) {
664 count += key_and_pending_ops.second.size();
665 }
666 for (auto& key_and_pending_ops : reporting_endpoint_group_pending_ops_) {
667 count += key_and_pending_ops.second.size();
668 }
669 }
670 return count;
671 }
672
CreateDatabaseSchema()673 bool SQLitePersistentReportingAndNelStore::Backend::CreateDatabaseSchema() {
674 if (!db()->DoesTableExist("nel_policies") &&
675 !CreateV2NelPoliciesSchema(db())) {
676 return false;
677 }
678
679 if (!db()->DoesTableExist("reporting_endpoints") &&
680 !CreateV2ReportingEndpointsSchema(db())) {
681 return false;
682 }
683
684 if (!db()->DoesTableExist("reporting_endpoint_groups") &&
685 !CreateV2ReportingEndpointGroupsSchema(db())) {
686 return false;
687 }
688
689 // TODO(chlily): Initialize tables for Reporting reports.
690
691 return true;
692 }
693
694 std::optional<int>
DoMigrateDatabaseSchema()695 SQLitePersistentReportingAndNelStore::Backend::DoMigrateDatabaseSchema() {
696 int cur_version = meta_table()->GetVersionNumber();
697
698 // Migrate from version 1 to version 2.
699 //
700 // For migration purposes, the NetworkAnonymizationKey field of the stored
701 // policies will be populated with an empty list, which corresponds to an
702 // empty NAK. This matches the behavior when NAKs are disabled. This will
703 // result in effectively clearing all policies once NAKs are enabled, at
704 // which point the the migration code should just be switched to deleting
705 // the old tables instead.
706 if (cur_version == 1) {
707 sql::Transaction transaction(db());
708 if (!transaction.Begin())
709 return std::nullopt;
710
711 // Migrate NEL policies table.
712 if (!db()->Execute("DROP TABLE IF EXISTS nel_policies_old; "
713 "ALTER TABLE nel_policies RENAME TO nel_policies_old")) {
714 return std::nullopt;
715 }
716 if (!CreateV2NelPoliciesSchema(db()))
717 return std::nullopt;
718 // clang-format off
719 // The "report_to" field is renamed to "group_name" for consistency with
720 // the other tables.
721 std::string nel_policies_migrate_stmt =
722 "INSERT INTO nel_policies (nik, origin_scheme, origin_host, "
723 " origin_port, group_name, received_ip_address, expires_us_since_epoch, "
724 " success_fraction, failure_fraction, is_include_subdomains, "
725 " last_access_us_since_epoch) "
726 "SELECT '[]', origin_scheme, origin_host, origin_port, "
727 " report_to, received_ip_address, expires_us_since_epoch, "
728 " success_fraction, failure_fraction, is_include_subdomains, "
729 " last_access_us_since_epoch "
730 "FROM nel_policies_old" ;
731 // clang-format on
732 if (!db()->Execute(nel_policies_migrate_stmt.c_str()))
733 return std::nullopt;
734 if (!db()->Execute("DROP TABLE nel_policies_old"))
735 return std::nullopt;
736
737 // Migrate Reporting endpoints table.
738 if (!db()->Execute("DROP TABLE IF EXISTS reporting_endpoints_old; "
739 "ALTER TABLE reporting_endpoints RENAME TO "
740 "reporting_endpoints_old")) {
741 return std::nullopt;
742 }
743 if (!CreateV2ReportingEndpointsSchema(db()))
744 return std::nullopt;
745 // clang-format off
746 std::string reporting_endpoints_migrate_stmt =
747 "INSERT INTO reporting_endpoints (nik, origin_scheme, origin_host, "
748 " origin_port, group_name, url, priority, weight) "
749 "SELECT '[]', origin_scheme, origin_host, origin_port, group_name, "
750 " url, priority, weight "
751 "FROM reporting_endpoints_old" ;
752 // clang-format on
753 if (!db()->Execute(reporting_endpoints_migrate_stmt.c_str()))
754 return std::nullopt;
755 if (!db()->Execute("DROP TABLE reporting_endpoints_old"))
756 return std::nullopt;
757
758 // Migrate Reporting endpoint groups table.
759 if (!db()->Execute("DROP TABLE IF EXISTS reporting_endpoint_groups_old; "
760 "ALTER TABLE reporting_endpoint_groups RENAME TO "
761 "reporting_endpoint_groups_old")) {
762 return std::nullopt;
763 }
764 if (!CreateV2ReportingEndpointGroupsSchema(db()))
765 return std::nullopt;
766 // clang-format off
767 std::string reporting_endpoint_groups_migrate_stmt =
768 "INSERT INTO reporting_endpoint_groups (nik, origin_scheme, "
769 " origin_host, origin_port, group_name, is_include_subdomains, "
770 " expires_us_since_epoch, last_access_us_since_epoch) "
771 "SELECT '[]', origin_scheme, origin_host, origin_port, "
772 " group_name, is_include_subdomains, expires_us_since_epoch, "
773 " last_access_us_since_epoch "
774 "FROM reporting_endpoint_groups_old" ;
775 // clang-format on
776 if (!db()->Execute(reporting_endpoint_groups_migrate_stmt.c_str()))
777 return std::nullopt;
778 if (!db()->Execute("DROP TABLE reporting_endpoint_groups_old"))
779 return std::nullopt;
780
781 ++cur_version;
782 if (!meta_table()->SetVersionNumber(cur_version) ||
783 !meta_table()->SetCompatibleVersionNumber(
784 std::min(cur_version, kCompatibleVersionNumber)) ||
785 !transaction.Commit()) {
786 return std::nullopt;
787 }
788 }
789
790 // Future database upgrade statements go here.
791
792 return std::make_optional(cur_version);
793 }
794
DoCommit()795 void SQLitePersistentReportingAndNelStore::Backend::DoCommit() {
796 QueueType<NetworkErrorLoggingService::NelPolicyKey, NelPolicyInfo>
797 nel_policy_ops;
798 QueueType<ReportingEndpointKey, ReportingEndpointInfo> reporting_endpoint_ops;
799 QueueType<ReportingEndpointGroupKey, ReportingEndpointGroupInfo>
800 reporting_endpoint_group_ops;
801 size_t op_count = 0;
802 {
803 base::AutoLock locked(lock_);
804 nel_policy_pending_ops_.swap(nel_policy_ops);
805 reporting_endpoint_pending_ops_.swap(reporting_endpoint_ops);
806 reporting_endpoint_group_pending_ops_.swap(reporting_endpoint_group_ops);
807 // TODO(chlily): swap out pending operations queue for Reporting reports.
808 op_count = num_pending_;
809 num_pending_ = 0;
810 }
811 if (!db() || op_count == 0)
812 return;
813
814 sql::Transaction transaction(db());
815 if (!transaction.Begin())
816 return;
817
818 // Commit all the NEL policy operations.
819 for (const auto& origin_and_nel_policy_ops : nel_policy_ops) {
820 const PendingOperationsVector<NelPolicyInfo>& ops_for_origin =
821 origin_and_nel_policy_ops.second;
822 for (const std::unique_ptr<PendingOperation<NelPolicyInfo>>& nel_policy_op :
823 ops_for_origin) {
824 CommitNelPolicyOperation(nel_policy_op.get());
825 }
826 }
827
828 // Commit all the Reporting endpoint operations.
829 for (const auto& key_and_reporting_endpoint_ops : reporting_endpoint_ops) {
830 const PendingOperationsVector<ReportingEndpointInfo>& ops_for_key =
831 key_and_reporting_endpoint_ops.second;
832 for (const std::unique_ptr<PendingOperation<ReportingEndpointInfo>>&
833 reporting_endpoint_op : ops_for_key) {
834 CommitReportingEndpointOperation(reporting_endpoint_op.get());
835 }
836 }
837
838 // Commit all the Reporting endpoint group operations.
839 for (const auto& key_and_reporting_endpoint_group_ops :
840 reporting_endpoint_group_ops) {
841 const PendingOperationsVector<ReportingEndpointGroupInfo>& ops_for_key =
842 key_and_reporting_endpoint_group_ops.second;
843 for (const std::unique_ptr<PendingOperation<ReportingEndpointGroupInfo>>&
844 reporting_endpoint_group_op : ops_for_key) {
845 CommitReportingEndpointGroupOperation(reporting_endpoint_group_op.get());
846 }
847 }
848
849 // TODO(chlily): Commit operations pertaining to Reporting reports.
850
851 transaction.Commit();
852 }
853
CommitNelPolicyOperation(PendingOperation<NelPolicyInfo> * op)854 bool SQLitePersistentReportingAndNelStore::Backend::CommitNelPolicyOperation(
855 PendingOperation<NelPolicyInfo>* op) {
856 DCHECK_EQ(1, db()->transaction_nesting());
857
858 sql::Statement add_statement(db()->GetCachedStatement(
859 SQL_FROM_HERE,
860 "INSERT INTO nel_policies (nik, origin_scheme, origin_host, origin_port, "
861 "received_ip_address, group_name, expires_us_since_epoch, "
862 "success_fraction, failure_fraction, is_include_subdomains, "
863 "last_access_us_since_epoch) VALUES (?,?,?,?,?,?,?,?,?,?,?)"));
864 if (!add_statement.is_valid())
865 return false;
866
867 sql::Statement update_access_statement(db()->GetCachedStatement(
868 SQL_FROM_HERE,
869 "UPDATE nel_policies SET last_access_us_since_epoch=? WHERE "
870 "nik=? AND origin_scheme=? AND origin_host=? AND origin_port=?"));
871 if (!update_access_statement.is_valid())
872 return false;
873
874 sql::Statement del_statement(db()->GetCachedStatement(
875 SQL_FROM_HERE,
876 "DELETE FROM nel_policies WHERE "
877 "nik=? AND origin_scheme=? AND origin_host=? AND origin_port=?"));
878 if (!del_statement.is_valid())
879 return false;
880
881 const NelPolicyInfo& nel_policy_info = op->data();
882
883 switch (op->type()) {
884 case PendingOperationType::ADD:
885 add_statement.Reset(true);
886 add_statement.BindString(
887 0, nel_policy_info.network_anonymization_key_string);
888 add_statement.BindString(1, nel_policy_info.origin_scheme);
889 add_statement.BindString(2, nel_policy_info.origin_host);
890 add_statement.BindInt(3, nel_policy_info.origin_port);
891 add_statement.BindString(4, nel_policy_info.received_ip_address);
892 add_statement.BindString(5, nel_policy_info.report_to);
893 add_statement.BindInt64(6, nel_policy_info.expires_us_since_epoch);
894 add_statement.BindDouble(7, nel_policy_info.success_fraction);
895 add_statement.BindDouble(8, nel_policy_info.failure_fraction);
896 add_statement.BindBool(9, nel_policy_info.is_include_subdomains);
897 add_statement.BindInt64(10, nel_policy_info.last_access_us_since_epoch);
898 if (!add_statement.Run()) {
899 DLOG(WARNING) << "Could not add a NEL policy to the DB.";
900 return false;
901 }
902 break;
903
904 case PendingOperationType::UPDATE_ACCESS_TIME:
905 update_access_statement.Reset(true);
906 update_access_statement.BindInt64(
907 0, nel_policy_info.last_access_us_since_epoch);
908 update_access_statement.BindString(
909 1, nel_policy_info.network_anonymization_key_string);
910 update_access_statement.BindString(2, nel_policy_info.origin_scheme);
911 update_access_statement.BindString(3, nel_policy_info.origin_host);
912 update_access_statement.BindInt(4, nel_policy_info.origin_port);
913 if (!update_access_statement.Run()) {
914 DLOG(WARNING)
915 << "Could not update NEL policy last access time in the DB.";
916 return false;
917 }
918 break;
919
920 case PendingOperationType::DELETE:
921 del_statement.Reset(true);
922 del_statement.BindString(
923 0, nel_policy_info.network_anonymization_key_string);
924 del_statement.BindString(1, nel_policy_info.origin_scheme);
925 del_statement.BindString(2, nel_policy_info.origin_host);
926 del_statement.BindInt(3, nel_policy_info.origin_port);
927 if (!del_statement.Run()) {
928 DLOG(WARNING) << "Could not delete a NEL policy from the DB.";
929 return false;
930 }
931 break;
932
933 default:
934 // There are no UPDATE_DETAILS operations for NEL policies.
935 // TODO(chlily): Maybe add the ability to update details as opposed to
936 // removing and re-adding every time; it might be slightly more efficient.
937 NOTREACHED();
938 break;
939 }
940
941 return true;
942 }
943
944 bool SQLitePersistentReportingAndNelStore::Backend::
CommitReportingEndpointOperation(PendingOperation<ReportingEndpointInfo> * op)945 CommitReportingEndpointOperation(
946 PendingOperation<ReportingEndpointInfo>* op) {
947 DCHECK_EQ(1, db()->transaction_nesting());
948
949 sql::Statement add_statement(db()->GetCachedStatement(
950 SQL_FROM_HERE,
951 "INSERT INTO reporting_endpoints (nik, origin_scheme, origin_host, "
952 "origin_port, group_name, url, priority, weight) "
953 "VALUES (?,?,?,?,?,?,?,?)"));
954 if (!add_statement.is_valid())
955 return false;
956
957 sql::Statement update_details_statement(db()->GetCachedStatement(
958 SQL_FROM_HERE,
959 "UPDATE reporting_endpoints SET priority=?, weight=? WHERE "
960 "nik=? AND origin_scheme=? AND origin_host=? AND origin_port=? "
961 "AND group_name=? AND url=?"));
962 if (!update_details_statement.is_valid())
963 return false;
964
965 sql::Statement del_statement(db()->GetCachedStatement(
966 SQL_FROM_HERE,
967 "DELETE FROM reporting_endpoints WHERE "
968 "nik=? AND origin_scheme=? AND origin_host=? AND origin_port=? "
969 "AND group_name=? AND url=?"));
970 if (!del_statement.is_valid())
971 return false;
972
973 const ReportingEndpointInfo& reporting_endpoint_info = op->data();
974
975 switch (op->type()) {
976 case PendingOperationType::ADD:
977 add_statement.Reset(true);
978 add_statement.BindString(
979 0, reporting_endpoint_info.network_anonymization_key_string);
980 add_statement.BindString(1, reporting_endpoint_info.origin_scheme);
981 add_statement.BindString(2, reporting_endpoint_info.origin_host);
982 add_statement.BindInt(3, reporting_endpoint_info.origin_port);
983 add_statement.BindString(4, reporting_endpoint_info.group_name);
984 add_statement.BindString(5, reporting_endpoint_info.url);
985 add_statement.BindInt(6, reporting_endpoint_info.priority);
986 add_statement.BindInt(7, reporting_endpoint_info.weight);
987 if (!add_statement.Run()) {
988 DLOG(WARNING) << "Could not add a Reporting endpoint to the DB.";
989 return false;
990 }
991 break;
992
993 case PendingOperationType::UPDATE_DETAILS:
994 update_details_statement.Reset(true);
995 update_details_statement.BindInt(0, reporting_endpoint_info.priority);
996 update_details_statement.BindInt(1, reporting_endpoint_info.weight);
997 update_details_statement.BindString(
998 2, reporting_endpoint_info.network_anonymization_key_string);
999 update_details_statement.BindString(
1000 3, reporting_endpoint_info.origin_scheme);
1001 update_details_statement.BindString(4,
1002 reporting_endpoint_info.origin_host);
1003 update_details_statement.BindInt(5, reporting_endpoint_info.origin_port);
1004 update_details_statement.BindString(6,
1005 reporting_endpoint_info.group_name);
1006 update_details_statement.BindString(7, reporting_endpoint_info.url);
1007 if (!update_details_statement.Run()) {
1008 DLOG(WARNING)
1009 << "Could not update Reporting endpoint details in the DB.";
1010 return false;
1011 }
1012 break;
1013
1014 case PendingOperationType::DELETE:
1015 del_statement.Reset(true);
1016 del_statement.BindString(
1017 0, reporting_endpoint_info.network_anonymization_key_string);
1018 del_statement.BindString(1, reporting_endpoint_info.origin_scheme);
1019 del_statement.BindString(2, reporting_endpoint_info.origin_host);
1020 del_statement.BindInt(3, reporting_endpoint_info.origin_port);
1021 del_statement.BindString(4, reporting_endpoint_info.group_name);
1022 del_statement.BindString(5, reporting_endpoint_info.url);
1023 if (!del_statement.Run()) {
1024 DLOG(WARNING) << "Could not delete a Reporting endpoint from the DB.";
1025 return false;
1026 }
1027 break;
1028
1029 default:
1030 // There are no UPDATE_ACCESS_TIME operations for Reporting endpoints
1031 // because their access times are not tracked.
1032 NOTREACHED();
1033 break;
1034 }
1035
1036 return true;
1037 }
1038
1039 bool SQLitePersistentReportingAndNelStore::Backend::
CommitReportingEndpointGroupOperation(PendingOperation<ReportingEndpointGroupInfo> * op)1040 CommitReportingEndpointGroupOperation(
1041 PendingOperation<ReportingEndpointGroupInfo>* op) {
1042 DCHECK_EQ(1, db()->transaction_nesting());
1043
1044 sql::Statement add_statement(db()->GetCachedStatement(
1045 SQL_FROM_HERE,
1046 "INSERT INTO reporting_endpoint_groups (nik, origin_scheme, origin_host, "
1047 "origin_port, group_name, is_include_subdomains, expires_us_since_epoch, "
1048 "last_access_us_since_epoch) VALUES (?,?,?,?,?,?,?,?)"));
1049 if (!add_statement.is_valid())
1050 return false;
1051
1052 sql::Statement update_access_statement(db()->GetCachedStatement(
1053 SQL_FROM_HERE,
1054 "UPDATE reporting_endpoint_groups SET last_access_us_since_epoch=? WHERE "
1055 "nik=? AND origin_scheme=? AND origin_host=? AND origin_port=? AND "
1056 "group_name=?"));
1057 if (!update_access_statement.is_valid())
1058 return false;
1059
1060 sql::Statement update_details_statement(db()->GetCachedStatement(
1061 SQL_FROM_HERE,
1062 "UPDATE reporting_endpoint_groups SET is_include_subdomains=?, "
1063 "expires_us_since_epoch=?, last_access_us_since_epoch=? WHERE "
1064 "nik=? AND origin_scheme=? AND origin_host=? AND origin_port=? AND "
1065 "group_name=?"));
1066 if (!update_details_statement.is_valid())
1067 return false;
1068
1069 sql::Statement del_statement(
1070 db()->GetCachedStatement(SQL_FROM_HERE,
1071 "DELETE FROM reporting_endpoint_groups WHERE "
1072 "nik=? AND origin_scheme=? AND origin_host=? "
1073 "AND origin_port=? AND group_name=?"));
1074 if (!del_statement.is_valid())
1075 return false;
1076
1077 const ReportingEndpointGroupInfo& reporting_endpoint_group_info = op->data();
1078
1079 switch (op->type()) {
1080 case PendingOperationType::ADD:
1081 add_statement.Reset(true);
1082 add_statement.BindString(
1083 0, reporting_endpoint_group_info.network_anonymization_key_string);
1084 add_statement.BindString(1, reporting_endpoint_group_info.origin_scheme);
1085 add_statement.BindString(2, reporting_endpoint_group_info.origin_host);
1086 add_statement.BindInt(3, reporting_endpoint_group_info.origin_port);
1087 add_statement.BindString(4, reporting_endpoint_group_info.group_name);
1088 add_statement.BindBool(
1089 5, reporting_endpoint_group_info.is_include_subdomains);
1090 add_statement.BindInt64(
1091 6, reporting_endpoint_group_info.expires_us_since_epoch);
1092 add_statement.BindInt64(
1093 7, reporting_endpoint_group_info.last_access_us_since_epoch);
1094 if (!add_statement.Run()) {
1095 DLOG(WARNING) << "Could not add a Reporting endpoint group to the DB.";
1096 return false;
1097 }
1098 break;
1099
1100 case PendingOperationType::UPDATE_ACCESS_TIME:
1101 update_access_statement.Reset(true);
1102 update_access_statement.BindInt64(
1103 0, reporting_endpoint_group_info.last_access_us_since_epoch);
1104 update_access_statement.BindString(
1105 1, reporting_endpoint_group_info.network_anonymization_key_string);
1106 update_access_statement.BindString(
1107 2, reporting_endpoint_group_info.origin_scheme);
1108 update_access_statement.BindString(
1109 3, reporting_endpoint_group_info.origin_host);
1110 update_access_statement.BindInt(
1111 4, reporting_endpoint_group_info.origin_port);
1112 update_access_statement.BindString(
1113 5, reporting_endpoint_group_info.group_name);
1114 if (!update_access_statement.Run()) {
1115 DLOG(WARNING)
1116 << "Could not update Reporting endpoint group last access "
1117 "time in the DB.";
1118 return false;
1119 }
1120 break;
1121
1122 case PendingOperationType::UPDATE_DETAILS:
1123 update_details_statement.Reset(true);
1124 update_details_statement.BindBool(
1125 0, reporting_endpoint_group_info.is_include_subdomains);
1126 update_details_statement.BindInt64(
1127 1, reporting_endpoint_group_info.expires_us_since_epoch);
1128 update_details_statement.BindInt64(
1129 2, reporting_endpoint_group_info.last_access_us_since_epoch);
1130 update_details_statement.BindString(
1131 3, reporting_endpoint_group_info.network_anonymization_key_string);
1132 update_details_statement.BindString(
1133 4, reporting_endpoint_group_info.origin_scheme);
1134 update_details_statement.BindString(
1135 5, reporting_endpoint_group_info.origin_host);
1136 update_details_statement.BindInt(
1137 6, reporting_endpoint_group_info.origin_port);
1138 update_details_statement.BindString(
1139 7, reporting_endpoint_group_info.group_name);
1140 if (!update_details_statement.Run()) {
1141 DLOG(WARNING)
1142 << "Could not update Reporting endpoint group details in the DB.";
1143 return false;
1144 }
1145 break;
1146
1147 case PendingOperationType::DELETE:
1148 del_statement.Reset(true);
1149 del_statement.BindString(
1150 0, reporting_endpoint_group_info.network_anonymization_key_string);
1151 del_statement.BindString(1, reporting_endpoint_group_info.origin_scheme);
1152 del_statement.BindString(2, reporting_endpoint_group_info.origin_host);
1153 del_statement.BindInt(3, reporting_endpoint_group_info.origin_port);
1154 del_statement.BindString(4, reporting_endpoint_group_info.group_name);
1155 if (!del_statement.Run()) {
1156 DLOG(WARNING)
1157 << "Could not delete a Reporting endpoint group from the DB.";
1158 return false;
1159 }
1160 break;
1161 }
1162
1163 return true;
1164 }
1165
1166 template <typename KeyType, typename DataType>
BatchOperation(KeyType key,std::unique_ptr<PendingOperation<DataType>> po,QueueType<KeyType,DataType> * queue)1167 void SQLitePersistentReportingAndNelStore::Backend::BatchOperation(
1168 KeyType key,
1169 std::unique_ptr<PendingOperation<DataType>> po,
1170 QueueType<KeyType, DataType>* queue) {
1171 DCHECK(!background_task_runner()->RunsTasksInCurrentSequence());
1172
1173 size_t num_pending;
1174 {
1175 base::AutoLock locked(lock_);
1176
1177 std::pair<typename QueueType<KeyType, DataType>::iterator, bool>
1178 iter_and_result =
1179 queue->emplace(std::move(key), PendingOperationsVector<DataType>());
1180 PendingOperationsVector<DataType>* ops_for_key =
1181 &iter_and_result.first->second;
1182 // If the insert failed, then we already have operations for this
1183 // key, so we try to coalesce the new operation with the existing ones.
1184 if (!iter_and_result.second)
1185 MaybeCoalesceOperations(ops_for_key, po.get());
1186 ops_for_key->push_back(std::move(po));
1187 // Note that num_pending_ counts number of calls to Batch*Operation(), not
1188 // the current length of the queue; this is intentional to guarantee
1189 // progress, as the length of the queue may decrease in some cases.
1190 num_pending = ++num_pending_;
1191 }
1192
1193 OnOperationBatched(num_pending);
1194 }
1195
1196 template <typename DataType>
MaybeCoalesceOperations(PendingOperationsVector<DataType> * ops_for_key,PendingOperation<DataType> * new_op)1197 void SQLitePersistentReportingAndNelStore::Backend::MaybeCoalesceOperations(
1198 PendingOperationsVector<DataType>* ops_for_key,
1199 PendingOperation<DataType>* new_op) {
1200 DCHECK(!ops_for_key->empty());
1201
1202 switch (new_op->type()) {
1203 case PendingOperationType::DELETE:
1204 // A delete makes all previous operations irrelevant.
1205 ops_for_key->clear();
1206 break;
1207
1208 case PendingOperationType::UPDATE_ACCESS_TIME:
1209 if (ops_for_key->back()->type() ==
1210 PendingOperationType::UPDATE_ACCESS_TIME) {
1211 // Updating the access time twice in a row is equivalent to just the
1212 // latter update.
1213 ops_for_key->pop_back();
1214 }
1215 break;
1216
1217 case PendingOperationType::UPDATE_DETAILS:
1218 while (!ops_for_key->empty() &&
1219 // Updating the details twice in a row is equivalent to just the
1220 // latter update.
1221 (ops_for_key->back()->type() ==
1222 PendingOperationType::UPDATE_DETAILS ||
1223 // UPDATE_DETAILS also updates the access time, so either type of
1224 // update operation can be discarded.
1225 ops_for_key->back()->type() ==
1226 PendingOperationType::UPDATE_ACCESS_TIME)) {
1227 ops_for_key->pop_back();
1228 }
1229 break;
1230
1231 case PendingOperationType::ADD:
1232 // Nothing special is done for an add operation. If it is overwriting an
1233 // existing entry, it will be preceded by at most one delete.
1234 DCHECK_LE(ops_for_key->size(), 1u);
1235 break;
1236 }
1237 }
1238
OnOperationBatched(size_t num_pending)1239 void SQLitePersistentReportingAndNelStore::Backend::OnOperationBatched(
1240 size_t num_pending) {
1241 DCHECK(!background_task_runner()->RunsTasksInCurrentSequence());
1242 // Commit every 30 seconds.
1243 static const int kCommitIntervalMs = 30 * 1000;
1244 // Commit right away if we have more than 512 outstanding operations.
1245 static const size_t kCommitAfterBatchSize = 512;
1246
1247 if (num_pending == 1) {
1248 // We've gotten our first entry for this batch, fire off the timer.
1249 if (!background_task_runner()->PostDelayedTask(
1250 FROM_HERE, base::BindOnce(&Backend::Commit, this),
1251 base::Milliseconds(kCommitIntervalMs))) {
1252 NOTREACHED() << "background_task_runner_ is not running.";
1253 }
1254 } else if (num_pending >= kCommitAfterBatchSize) {
1255 // We've reached a big enough batch, fire off a commit now.
1256 PostBackgroundTask(FROM_HERE, base::BindOnce(&Backend::Commit, this));
1257 }
1258 }
1259
1260 // TODO(chlily): Discard expired policies when loading, discard and record
1261 // problem if loaded policy is malformed.
1262 void SQLitePersistentReportingAndNelStore::Backend::
LoadNelPoliciesAndNotifyInBackground(NelPoliciesLoadedCallback loaded_callback)1263 LoadNelPoliciesAndNotifyInBackground(
1264 NelPoliciesLoadedCallback loaded_callback) {
1265 DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
1266
1267 std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies;
1268 if (!InitializeDatabase()) {
1269 PostClientTask(
1270 FROM_HERE,
1271 base::BindOnce(&Backend::CompleteLoadNelPoliciesAndNotifyInForeground,
1272 this, std::move(loaded_callback),
1273 std::move(loaded_policies), false /* load_success */));
1274 return;
1275 }
1276
1277 sql::Statement smt(db()->GetUniqueStatement(
1278 "SELECT nik, origin_scheme, origin_host, origin_port, "
1279 "received_ip_address, group_name, expires_us_since_epoch, "
1280 "success_fraction, failure_fraction, is_include_subdomains, "
1281 "last_access_us_since_epoch FROM nel_policies"));
1282 if (!smt.is_valid()) {
1283 Reset();
1284 PostClientTask(
1285 FROM_HERE,
1286 base::BindOnce(&Backend::CompleteLoadNelPoliciesAndNotifyInForeground,
1287 this, std::move(loaded_callback),
1288 std::move(loaded_policies), false /* load_success */));
1289 return;
1290 }
1291
1292 while (smt.Step()) {
1293 // Attempt to reconstitute a NEL policy from the fields stored in the
1294 // database.
1295 NetworkAnonymizationKey network_anonymization_key;
1296 if (!NetworkAnonymizationKeyFromString(smt.ColumnString(0),
1297 &network_anonymization_key))
1298 continue;
1299 NetworkErrorLoggingService::NelPolicy policy;
1300 policy.key = NetworkErrorLoggingService::NelPolicyKey(
1301 network_anonymization_key,
1302 url::Origin::CreateFromNormalizedTuple(
1303 /* origin_scheme = */ smt.ColumnString(1),
1304 /* origin_host = */ smt.ColumnString(2),
1305 /* origin_port = */ smt.ColumnInt(3)));
1306 if (!policy.received_ip_address.AssignFromIPLiteral(smt.ColumnString(4)))
1307 policy.received_ip_address = IPAddress();
1308 policy.report_to = smt.ColumnString(5);
1309 policy.expires = base::Time::FromDeltaSinceWindowsEpoch(
1310 base::Microseconds(smt.ColumnInt64(6)));
1311 policy.success_fraction = smt.ColumnDouble(7);
1312 policy.failure_fraction = smt.ColumnDouble(8);
1313 policy.include_subdomains = smt.ColumnBool(9);
1314 policy.last_used = base::Time::FromDeltaSinceWindowsEpoch(
1315 base::Microseconds(smt.ColumnInt64(10)));
1316
1317 loaded_policies.push_back(std::move(policy));
1318 }
1319
1320 PostClientTask(
1321 FROM_HERE,
1322 base::BindOnce(&Backend::CompleteLoadNelPoliciesAndNotifyInForeground,
1323 this, std::move(loaded_callback),
1324 std::move(loaded_policies), true /* load_success */));
1325 }
1326
1327 void SQLitePersistentReportingAndNelStore::Backend::
CompleteLoadNelPoliciesAndNotifyInForeground(NelPoliciesLoadedCallback loaded_callback,std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies,bool load_success)1328 CompleteLoadNelPoliciesAndNotifyInForeground(
1329 NelPoliciesLoadedCallback loaded_callback,
1330 std::vector<NetworkErrorLoggingService::NelPolicy> loaded_policies,
1331 bool load_success) {
1332 DCHECK(client_task_runner()->RunsTasksInCurrentSequence());
1333
1334 if (load_success) {
1335 RecordNumberOfLoadedNelPolicies(loaded_policies.size());
1336 } else {
1337 DCHECK(loaded_policies.empty());
1338 }
1339
1340 std::move(loaded_callback).Run(std::move(loaded_policies));
1341 }
1342
1343 void SQLitePersistentReportingAndNelStore::Backend::
LoadReportingClientsAndNotifyInBackground(ReportingClientsLoadedCallback loaded_callback)1344 LoadReportingClientsAndNotifyInBackground(
1345 ReportingClientsLoadedCallback loaded_callback) {
1346 DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
1347
1348 std::vector<ReportingEndpoint> loaded_endpoints;
1349 std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups;
1350 if (!InitializeDatabase()) {
1351 PostClientTask(
1352 FROM_HERE,
1353 base::BindOnce(
1354 &Backend::CompleteLoadReportingClientsAndNotifyInForeground, this,
1355 std::move(loaded_callback), std::move(loaded_endpoints),
1356 std::move(loaded_endpoint_groups), false /* load_success */));
1357 return;
1358 }
1359
1360 sql::Statement endpoints_statement(db()->GetUniqueStatement(
1361 "SELECT nik, origin_scheme, origin_host, origin_port, group_name, "
1362 "url, priority, weight FROM reporting_endpoints"));
1363 sql::Statement endpoint_groups_statement(db()->GetUniqueStatement(
1364 "SELECT nik, origin_scheme, origin_host, origin_port, group_name, "
1365 "is_include_subdomains, expires_us_since_epoch, "
1366 "last_access_us_since_epoch FROM reporting_endpoint_groups"));
1367 if (!endpoints_statement.is_valid() ||
1368 !endpoint_groups_statement.is_valid()) {
1369 Reset();
1370 PostClientTask(
1371 FROM_HERE,
1372 base::BindOnce(
1373 &Backend::CompleteLoadReportingClientsAndNotifyInForeground, this,
1374 std::move(loaded_callback), std::move(loaded_endpoints),
1375 std::move(loaded_endpoint_groups), false /* load_success */));
1376 return;
1377 }
1378
1379 while (endpoints_statement.Step()) {
1380 // Attempt to reconstitute a ReportingEndpoint from the fields stored in the
1381 // database.
1382 NetworkAnonymizationKey network_anonymization_key;
1383 if (!NetworkAnonymizationKeyFromString(endpoints_statement.ColumnString(0),
1384 &network_anonymization_key))
1385 continue;
1386 ReportingEndpointGroupKey group_key(
1387 network_anonymization_key,
1388 /* origin = */
1389 url::Origin::CreateFromNormalizedTuple(
1390 /* origin_scheme = */ endpoints_statement.ColumnString(1),
1391 /* origin_host = */ endpoints_statement.ColumnString(2),
1392 /* origin_port = */ endpoints_statement.ColumnInt(3)),
1393 /* group_name = */ endpoints_statement.ColumnString(4));
1394 ReportingEndpoint::EndpointInfo endpoint_info;
1395 endpoint_info.url = GURL(endpoints_statement.ColumnString(5));
1396 endpoint_info.priority = endpoints_statement.ColumnInt(6);
1397 endpoint_info.weight = endpoints_statement.ColumnInt(7);
1398
1399 loaded_endpoints.emplace_back(std::move(group_key),
1400 std::move(endpoint_info));
1401 }
1402
1403 while (endpoint_groups_statement.Step()) {
1404 // Attempt to reconstitute a CachedReportingEndpointGroup from the fields
1405 // stored in the database.
1406 NetworkAnonymizationKey network_anonymization_key;
1407 if (!NetworkAnonymizationKeyFromString(
1408 endpoint_groups_statement.ColumnString(0),
1409 &network_anonymization_key))
1410 continue;
1411 ReportingEndpointGroupKey group_key(
1412 network_anonymization_key,
1413 /* origin = */
1414 url::Origin::CreateFromNormalizedTuple(
1415 /* origin_scheme = */ endpoint_groups_statement.ColumnString(1),
1416 /* origin_host = */ endpoint_groups_statement.ColumnString(2),
1417 /* origin_port = */ endpoint_groups_statement.ColumnInt(3)),
1418 /* group_name = */ endpoint_groups_statement.ColumnString(4));
1419 OriginSubdomains include_subdomains =
1420 endpoint_groups_statement.ColumnBool(5) ? OriginSubdomains::INCLUDE
1421 : OriginSubdomains::EXCLUDE;
1422 base::Time expires = base::Time::FromDeltaSinceWindowsEpoch(
1423 base::Microseconds(endpoint_groups_statement.ColumnInt64(6)));
1424 base::Time last_used = base::Time::FromDeltaSinceWindowsEpoch(
1425 base::Microseconds(endpoint_groups_statement.ColumnInt64(7)));
1426
1427 loaded_endpoint_groups.emplace_back(std::move(group_key),
1428 include_subdomains, expires, last_used);
1429 }
1430
1431 PostClientTask(
1432 FROM_HERE,
1433 base::BindOnce(
1434 &Backend::CompleteLoadReportingClientsAndNotifyInForeground, this,
1435 std::move(loaded_callback), std::move(loaded_endpoints),
1436 std::move(loaded_endpoint_groups), true /* load_success */));
1437 }
1438
1439 void SQLitePersistentReportingAndNelStore::Backend::
CompleteLoadReportingClientsAndNotifyInForeground(ReportingClientsLoadedCallback loaded_callback,std::vector<ReportingEndpoint> loaded_endpoints,std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups,bool load_success)1440 CompleteLoadReportingClientsAndNotifyInForeground(
1441 ReportingClientsLoadedCallback loaded_callback,
1442 std::vector<ReportingEndpoint> loaded_endpoints,
1443 std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups,
1444 bool load_success) {
1445 DCHECK(client_task_runner()->RunsTasksInCurrentSequence());
1446
1447 if (load_success) {
1448 RecordNumberOfLoadedReportingEndpoints(loaded_endpoints.size());
1449 RecordNumberOfLoadedReportingEndpointGroups(loaded_endpoint_groups.size());
1450 } else {
1451 DCHECK(loaded_endpoints.empty());
1452 DCHECK(loaded_endpoint_groups.empty());
1453 }
1454
1455 std::move(loaded_callback)
1456 .Run(std::move(loaded_endpoints), std::move(loaded_endpoint_groups));
1457 }
1458
1459 void SQLitePersistentReportingAndNelStore::Backend::
RecordNumberOfLoadedNelPolicies(size_t count)1460 RecordNumberOfLoadedNelPolicies(size_t count) {
1461 // The NetworkErrorLoggingService stores up to 1000 policies.
1462 UMA_HISTOGRAM_COUNTS_1000(kNumberOfLoadedNelPoliciesHistogramName, count);
1463 // TODO(crbug.com/1165308): Remove this metric once the investigation is done.
1464 UMA_HISTOGRAM_COUNTS_10000(kNumberOfLoadedNelPolicies2HistogramName, count);
1465 }
1466
1467 void SQLitePersistentReportingAndNelStore::Backend::
RecordNumberOfLoadedReportingEndpoints(size_t count)1468 RecordNumberOfLoadedReportingEndpoints(size_t count) {
1469 // TODO(crbug.com/1165308): Remove this metric once the investigation is done.
1470 UMA_HISTOGRAM_COUNTS_10000(kNumberOfLoadedReportingEndpoints2HistogramName,
1471 count);
1472 }
1473
1474 void SQLitePersistentReportingAndNelStore::Backend::
RecordNumberOfLoadedReportingEndpointGroups(size_t count)1475 RecordNumberOfLoadedReportingEndpointGroups(size_t count) {
1476 // TODO(crbug.com/1165308): Remove this metric once the investigation is done.
1477 UMA_HISTOGRAM_COUNTS_10000(
1478 kNumberOfLoadedReportingEndpointGroups2HistogramName, count);
1479 }
1480
SQLitePersistentReportingAndNelStore(const base::FilePath & path,const scoped_refptr<base::SequencedTaskRunner> & client_task_runner,const scoped_refptr<base::SequencedTaskRunner> & background_task_runner)1481 SQLitePersistentReportingAndNelStore::SQLitePersistentReportingAndNelStore(
1482 const base::FilePath& path,
1483 const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
1484 const scoped_refptr<base::SequencedTaskRunner>& background_task_runner)
1485 : backend_(base::MakeRefCounted<Backend>(path,
1486 client_task_runner,
1487 background_task_runner)) {}
1488
~SQLitePersistentReportingAndNelStore()1489 SQLitePersistentReportingAndNelStore::~SQLitePersistentReportingAndNelStore() {
1490 backend_->Close();
1491 }
1492
LoadNelPolicies(NelPoliciesLoadedCallback loaded_callback)1493 void SQLitePersistentReportingAndNelStore::LoadNelPolicies(
1494 NelPoliciesLoadedCallback loaded_callback) {
1495 DCHECK(!loaded_callback.is_null());
1496 backend_->LoadNelPolicies(base::BindOnce(
1497 &SQLitePersistentReportingAndNelStore::CompleteLoadNelPolicies,
1498 weak_factory_.GetWeakPtr(), std::move(loaded_callback)));
1499 }
1500
AddNelPolicy(const NetworkErrorLoggingService::NelPolicy & policy)1501 void SQLitePersistentReportingAndNelStore::AddNelPolicy(
1502 const NetworkErrorLoggingService::NelPolicy& policy) {
1503 backend_->AddNelPolicy(policy);
1504 }
1505
UpdateNelPolicyAccessTime(const NetworkErrorLoggingService::NelPolicy & policy)1506 void SQLitePersistentReportingAndNelStore::UpdateNelPolicyAccessTime(
1507 const NetworkErrorLoggingService::NelPolicy& policy) {
1508 backend_->UpdateNelPolicyAccessTime(policy);
1509 }
1510
DeleteNelPolicy(const NetworkErrorLoggingService::NelPolicy & policy)1511 void SQLitePersistentReportingAndNelStore::DeleteNelPolicy(
1512 const NetworkErrorLoggingService::NelPolicy& policy) {
1513 backend_->DeleteNelPolicy(policy);
1514 }
1515
LoadReportingClients(ReportingClientsLoadedCallback loaded_callback)1516 void SQLitePersistentReportingAndNelStore::LoadReportingClients(
1517 ReportingClientsLoadedCallback loaded_callback) {
1518 DCHECK(!loaded_callback.is_null());
1519 backend_->LoadReportingClients(base::BindOnce(
1520 &SQLitePersistentReportingAndNelStore::CompleteLoadReportingClients,
1521 weak_factory_.GetWeakPtr(), std::move(loaded_callback)));
1522 }
1523
AddReportingEndpoint(const ReportingEndpoint & endpoint)1524 void SQLitePersistentReportingAndNelStore::AddReportingEndpoint(
1525 const ReportingEndpoint& endpoint) {
1526 backend_->AddReportingEndpoint(endpoint);
1527 }
1528
AddReportingEndpointGroup(const CachedReportingEndpointGroup & group)1529 void SQLitePersistentReportingAndNelStore::AddReportingEndpointGroup(
1530 const CachedReportingEndpointGroup& group) {
1531 backend_->AddReportingEndpointGroup(group);
1532 }
1533
1534 void SQLitePersistentReportingAndNelStore::
UpdateReportingEndpointGroupAccessTime(const CachedReportingEndpointGroup & group)1535 UpdateReportingEndpointGroupAccessTime(
1536 const CachedReportingEndpointGroup& group) {
1537 backend_->UpdateReportingEndpointGroupAccessTime(group);
1538 }
1539
UpdateReportingEndpointDetails(const ReportingEndpoint & endpoint)1540 void SQLitePersistentReportingAndNelStore::UpdateReportingEndpointDetails(
1541 const ReportingEndpoint& endpoint) {
1542 backend_->UpdateReportingEndpointDetails(endpoint);
1543 }
1544
UpdateReportingEndpointGroupDetails(const CachedReportingEndpointGroup & group)1545 void SQLitePersistentReportingAndNelStore::UpdateReportingEndpointGroupDetails(
1546 const CachedReportingEndpointGroup& group) {
1547 backend_->UpdateReportingEndpointGroupDetails(group);
1548 }
1549
DeleteReportingEndpoint(const ReportingEndpoint & endpoint)1550 void SQLitePersistentReportingAndNelStore::DeleteReportingEndpoint(
1551 const ReportingEndpoint& endpoint) {
1552 backend_->DeleteReportingEndpoint(endpoint);
1553 }
1554
DeleteReportingEndpointGroup(const CachedReportingEndpointGroup & group)1555 void SQLitePersistentReportingAndNelStore::DeleteReportingEndpointGroup(
1556 const CachedReportingEndpointGroup& group) {
1557 backend_->DeleteReportingEndpointGroup(group);
1558 }
1559
Flush()1560 void SQLitePersistentReportingAndNelStore::Flush() {
1561 backend_->Flush(base::DoNothing());
1562 }
1563
GetQueueLengthForTesting() const1564 size_t SQLitePersistentReportingAndNelStore::GetQueueLengthForTesting() const {
1565 return backend_->GetQueueLengthForTesting();
1566 }
1567
CompleteLoadNelPolicies(NelPoliciesLoadedCallback callback,std::vector<NetworkErrorLoggingService::NelPolicy> policies)1568 void SQLitePersistentReportingAndNelStore::CompleteLoadNelPolicies(
1569 NelPoliciesLoadedCallback callback,
1570 std::vector<NetworkErrorLoggingService::NelPolicy> policies) {
1571 std::move(callback).Run(std::move(policies));
1572 }
1573
CompleteLoadReportingClients(ReportingClientsLoadedCallback callback,std::vector<ReportingEndpoint> endpoints,std::vector<CachedReportingEndpointGroup> endpoint_groups)1574 void SQLitePersistentReportingAndNelStore::CompleteLoadReportingClients(
1575 ReportingClientsLoadedCallback callback,
1576 std::vector<ReportingEndpoint> endpoints,
1577 std::vector<CachedReportingEndpointGroup> endpoint_groups) {
1578 std::move(callback).Run(std::move(endpoints), std::move(endpoint_groups));
1579 }
1580
1581 } // namespace net
1582