blob: 388e9c993edea9eeaa77cf14d90dc60db9f6bae2 [file] [log] [blame]
[email protected]7f07db62014-05-15 01:12:451// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Yue Ru Sun227e27bb2019-05-10 23:53:055#ifndef COMPONENTS_METRICS_UNSENT_LOG_STORE_H_
6#define COMPONENTS_METRICS_UNSENT_LOG_STORE_H_
[email protected]7f07db62014-05-15 01:12:457
avi26062922015-12-26 00:14:188#include <stddef.h>
9
holte961fa392016-12-28 20:57:0610#include <memory>
[email protected]7f07db62014-05-15 01:12:4511#include <string>
12#include <vector>
13
Tao Baiafdf8dfd402020-06-06 03:38:0114#include "base/gtest_prod_util.h"
[email protected]7f07db62014-05-15 01:12:4515#include "base/logging.h"
avi26062922015-12-26 00:14:1816#include "base/macros.h"
Tao Baiafdf8dfd402020-06-06 03:38:0117#include "base/metrics/histogram_base.h"
18#include "base/optional.h"
[email protected]7f07db62014-05-15 01:12:4519#include "base/values.h"
holteade6fdf2017-02-23 02:42:3920#include "components/metrics/log_store.h"
[email protected]7f07db62014-05-15 01:12:4521
22class PrefService;
23
24namespace metrics {
25
Yue Ru Sun227e27bb2019-05-10 23:53:0526class UnsentLogStoreMetrics;
holte961fa392016-12-28 20:57:0627
[email protected]7f07db62014-05-15 01:12:4528// Maintains a list of unsent logs that are written and restored from disk.
Yue Ru Sun227e27bb2019-05-10 23:53:0529class UnsentLogStore : public LogStore {
[email protected]7f07db62014-05-15 01:12:4530 public:
Yue Ru Sun227e27bb2019-05-10 23:53:0531 // Constructs an UnsentLogStore that stores data in |local_state| under the
Tao Baiafdf8dfd402020-06-06 03:38:0132 // preference |log_data_pref_name|.
[email protected]9706e1b2014-06-11 16:31:2433 // Calling code is responsible for ensuring that the lifetime of |local_state|
Yue Ru Sun227e27bb2019-05-10 23:53:0534 // is longer than the lifetime of UnsentLogStore.
[email protected]9706e1b2014-06-11 16:31:2435 //
Tao Baiafdf8dfd402020-06-06 03:38:0136 // The optional |metadata_pref_name| is the preference that is used to store
37 // the unsent logs info while the unset logs are persisted. That info will be
38 // recorded as UMA metrics in next browser startup.
39 //
[email protected]9706e1b2014-06-11 16:31:2440 // When saving logs to disk, stores either the first |min_log_count| logs, or
41 // at least |min_log_bytes| bytes of logs, whichever is greater.
42 //
43 // If the optional |max_log_size| parameter is non-zero, all logs larger than
[email protected]17e820d2014-07-23 01:39:3944 // that limit will be skipped when writing to disk.
Jesse Dohertybf020162018-12-11 15:40:0145 //
46 // |signing_key| is used to produce an HMAC-SHA256 signature of the logged
47 // data, which will be uploaded with the log and used to validate data
48 // integrity.
Yue Ru Sun227e27bb2019-05-10 23:53:0549 UnsentLogStore(std::unique_ptr<UnsentLogStoreMetrics> metrics,
Tao Baiafdf8dfd402020-06-06 03:38:0150 PrefService* local_state,
51 const char* log_data_pref_name,
52 const char* metadata_pref_name,
53 size_t min_log_count,
54 size_t min_log_bytes,
55 size_t max_log_size,
56 const std::string& signing_key);
Yue Ru Sun227e27bb2019-05-10 23:53:0557 ~UnsentLogStore();
[email protected]7f07db62014-05-15 01:12:4558
holteade6fdf2017-02-23 02:42:3959 // LogStore:
60 bool has_unsent_logs() const override;
61 bool has_staged_log() const override;
62 const std::string& staged_log() const override;
63 const std::string& staged_log_hash() const override;
Jesse Dohertye1c81482018-11-27 22:12:5764 const std::string& staged_log_signature() const override;
holteade6fdf2017-02-23 02:42:3965 void StageNextLog() override;
66 void DiscardStagedLog() override;
Tao Baiafdf8dfd402020-06-06 03:38:0167 void MarkStagedLogAsSent() override;
Robert Kaplow96ecc0a2020-07-16 15:29:0968 void TrimAndPersistUnsentLogs() override;
holteade6fdf2017-02-23 02:42:3969 void LoadPersistedUnsentLogs() override;
[email protected]7f07db62014-05-15 01:12:4570
Tao Baiafdf8dfd402020-06-06 03:38:0171 // Adds a UMA log to the list, |samples_count| is the total number of samples
72 // in the log (if available).
73 void StoreLog(const std::string& log_data,
74 base::Optional<base::HistogramBase::Count> samples_count);
[email protected]7f07db62014-05-15 01:12:4575
Yue Ru Sun39255c612019-10-21 16:31:5976 // Gets log data at the given index in the list.
77 const std::string& GetLogAtIndex(size_t index);
78
79 // Replaces the compressed log at |index| in the store with given log data
80 // reusing the same timestamp from the original log, and returns old log data.
Tao Baiafdf8dfd402020-06-06 03:38:0181 std::string ReplaceLogAtIndex(
82 size_t index,
83 const std::string& new_log_data,
84 base::Optional<base::HistogramBase::Count> samples_count);
Yue Ru Sun39255c612019-10-21 16:31:5985
86 // Deletes all logs, in memory and on disk.
holte7b74c622017-01-23 23:13:0787 void Purge();
88
gayane8b523b872016-09-30 21:43:5989 // Returns the timestamp of the element in the front of the list.
holteade6fdf2017-02-23 02:42:3990 const std::string& staged_log_timestamp() const;
gayane8b523b872016-09-30 21:43:5991
[email protected]7f07db62014-05-15 01:12:4592 // The number of elements currently stored.
93 size_t size() const { return list_.size(); }
94
Weilun Shif6c84fe2021-04-07 20:04:4595 // Computes the HMAC for |log_data| using the |signing_key| and returns a bool
96 // indicating whether the signing succeeded. The returned HMAC is written to
97 // the |signature|.
98 static bool ComputeHMACForLog(const std::string& log_data,
99 const std::string& signing_key,
100 std::string* signature);
101
[email protected]7f07db62014-05-15 01:12:45102 private:
Tao Baiafdf8dfd402020-06-06 03:38:01103 FRIEND_TEST_ALL_PREFIXES(UnsentLogStoreTest, UnsentLogMetadataMetrics);
104
Robert Kaplow96ecc0a2020-07-16 15:29:09105 // Keep the most recent logs which are smaller than |max_log_size_|.
106 // We keep at least |min_log_bytes_| and |min_log_count_| of logs before
107 // discarding older logs.
108 void TrimLogs();
109
110 // Writes the list of logs to |list|.
[email protected]17e820d2014-07-23 01:39:39111 void WriteLogsToPrefList(base::ListValue* list) const;
[email protected]7f07db62014-05-15 01:12:45112
Robert Kaplow96ecc0a2020-07-16 15:29:09113 // Reads the list of logs from |list|.
holteade6fdf2017-02-23 02:42:39114 void ReadLogsFromPrefList(const base::ListValue& list);
[email protected]7f07db62014-05-15 01:12:45115
Tao Baiafdf8dfd402020-06-06 03:38:01116 // Writes the unsent log info to the |metadata_pref_name_| preference.
117 void WriteToMetricsPref(base::HistogramBase::Count unsent_samples_count,
118 base::HistogramBase::Count sent_samples_count,
119 size_t persisted_size) const;
120
121 // Records the info in |metadata_pref_name_| as UMA metrics.
122 void RecordMetaDataMertics();
123
holte961fa392016-12-28 20:57:06124 // An object for recording UMA metrics.
Yue Ru Sun227e27bb2019-05-10 23:53:05125 std::unique_ptr<UnsentLogStoreMetrics> metrics_;
holte961fa392016-12-28 20:57:06126
[email protected]7f07db62014-05-15 01:12:45127 // A weak pointer to the PrefService object to read and write the preference
128 // from. Calling code should ensure this object continues to exist for the
Yue Ru Sun227e27bb2019-05-10 23:53:05129 // lifetime of the UnsentLogStore object.
[email protected]7f07db62014-05-15 01:12:45130 PrefService* local_state_;
131
[email protected]9706e1b2014-06-11 16:31:24132 // The name of the preference to serialize logs to/from.
Tao Baiafdf8dfd402020-06-06 03:38:01133 const char* log_data_pref_name_;
134
135 // The name of the preference to store the unsent logs info, it could be
136 // nullptr if the metadata isn't desired.
137 const char* metadata_pref_name_;
[email protected]7f07db62014-05-15 01:12:45138
139 // We will keep at least this |min_log_count_| logs or |min_log_bytes_| bytes
Robert Kaplow96ecc0a2020-07-16 15:29:09140 // of logs, whichever is greater, when trimming logs. These apply after
[email protected]7f07db62014-05-15 01:12:45141 // skipping logs greater than |max_log_size_|.
142 const size_t min_log_count_;
143 const size_t min_log_bytes_;
144
145 // Logs greater than this size will not be written to disk.
146 const size_t max_log_size_;
147
Jesse Dohertybf020162018-12-11 15:40:01148 // Used to create a signature of log data, in order to verify reported data is
149 // authentic.
150 const std::string signing_key_;
151
gayane8b523b872016-09-30 21:43:59152 struct LogInfo {
Jesse Dohertye1c81482018-11-27 22:12:57153 LogInfo();
154 LogInfo(const LogInfo& other);
155 ~LogInfo();
156
Jesse Dohertybf020162018-12-11 15:40:01157 // Initializes the members based on uncompressed |log_data|,
158 // |log_timestamp|, and |signing_key|. |log_data| is the uncompressed
159 // serialized log protobuf. A hash and a signature are computed from
160 // |log_data|. The signature is produced using |signing_key|. |log_data|
Yue Ru Sun227e27bb2019-05-10 23:53:05161 // will be compressed and stored in |compressed_log_data|. |log_timestamp|
Jesse Dohertybf020162018-12-11 15:40:01162 // is stored as is.
holte961fa392016-12-28 20:57:06163 // |metrics| is the parent's metrics_ object, and should not be held.
Yue Ru Sun227e27bb2019-05-10 23:53:05164 void Init(UnsentLogStoreMetrics* metrics,
holte961fa392016-12-28 20:57:06165 const std::string& log_data,
Jesse Dohertybf020162018-12-11 15:40:01166 const std::string& log_timestamp,
Tao Baiafdf8dfd402020-06-06 03:38:01167 const std::string& signing_key,
168 base::Optional<base::HistogramBase::Count> samples_count);
[email protected]9706e1b2014-06-11 16:31:24169
[email protected]9706e1b2014-06-11 16:31:24170 // Compressed log data - a serialized protobuf that's been gzipped.
171 std::string compressed_log_data;
172
Jesse Dohertye1c81482018-11-27 22:12:57173 // The SHA1 hash of the log. Computed in Init and stored to catch errors
174 // from memory corruption.
[email protected]9706e1b2014-06-11 16:31:24175 std::string hash;
gayane8b523b872016-09-30 21:43:59176
Jesse Dohertye1c81482018-11-27 22:12:57177 // The HMAC-SHA256 signature of the log, used to validate the log came from
178 // Chrome. It's computed in Init and stored, instead of computed on demand,
179 // to catch errors from memory corruption.
180 std::string signature;
181
gayane8b523b872016-09-30 21:43:59182 // The timestamp of when the log was created as a time_t value.
183 std::string timestamp;
Tao Baiafdf8dfd402020-06-06 03:38:01184
185 // The total number of samples in this log if applicable.
186 base::Optional<base::HistogramBase::Count> samples_count;
[email protected]7f07db62014-05-15 01:12:45187 };
188 // A list of all of the stored logs, stored with SHA1 hashes to check for
189 // corruption while they are stored in memory.
Robert Kaplow96ecc0a2020-07-16 15:29:09190 std::vector<std::unique_ptr<LogInfo>> list_;
[email protected]7f07db62014-05-15 01:12:45191
[email protected]faa8d222014-07-25 21:30:26192 // The index and type of the log staged for upload. If nothing has been
193 // staged, the index will be -1.
194 int staged_log_index_;
[email protected]7f07db62014-05-15 01:12:45195
Tao Baiafdf8dfd402020-06-06 03:38:01196 // The total number of samples that have been sent from this LogStore.
197 base::HistogramBase::Count total_samples_sent_ = 0;
198
Yue Ru Sun227e27bb2019-05-10 23:53:05199 DISALLOW_COPY_AND_ASSIGN(UnsentLogStore);
[email protected]7f07db62014-05-15 01:12:45200};
201
202} // namespace metrics
203
Yue Ru Sun227e27bb2019-05-10 23:53:05204#endif // COMPONENTS_METRICS_UNSENT_LOG_STORE_H_