xref: /aosp_15_r20/external/cronet/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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