unsent_log_store.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // 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. #ifndef COMPONENTS_METRICS_UNSENT_LOG_STORE_H_
  5. #define COMPONENTS_METRICS_UNSENT_LOG_STORE_H_
  6. #include <stddef.h>
  7. #include <memory>
  8. #include <string>
  9. #include <vector>
  10. #include "base/gtest_prod_util.h"
  11. #include "base/logging.h"
  12. #include "base/memory/raw_ptr.h"
  13. #include "base/metrics/histogram_base.h"
  14. #include "base/values.h"
  15. #include "components/metrics/log_store.h"
  16. #include "components/metrics/metrics_log.h"
  17. #include "third_party/abseil-cpp/absl/types/optional.h"
  18. class PrefService;
  19. namespace metrics {
  20. class UnsentLogStoreMetrics;
  21. // Maintains a list of unsent logs that are written and restored from disk.
  22. class UnsentLogStore : public LogStore {
  23. public:
  24. // Constructs an UnsentLogStore that stores data in |local_state| under the
  25. // preference |log_data_pref_name|.
  26. // Calling code is responsible for ensuring that the lifetime of |local_state|
  27. // is longer than the lifetime of UnsentLogStore.
  28. //
  29. // The optional |metadata_pref_name| is the preference that is used to store
  30. // the unsent logs info while the unset logs are persisted. That info will be
  31. // recorded as UMA metrics in next browser startup.
  32. //
  33. // When saving logs to disk, stores either the first |min_log_count| logs, or
  34. // at least |min_log_bytes| bytes of logs, whichever is greater.
  35. //
  36. // If the optional |max_log_size| parameter is non-zero, all logs larger than
  37. // that limit will be skipped when writing to disk.
  38. //
  39. // |signing_key| is used to produce an HMAC-SHA256 signature of the logged
  40. // data, which will be uploaded with the log and used to validate data
  41. // integrity.
  42. UnsentLogStore(std::unique_ptr<UnsentLogStoreMetrics> metrics,
  43. PrefService* local_state,
  44. const char* log_data_pref_name,
  45. const char* metadata_pref_name,
  46. size_t min_log_count,
  47. size_t min_log_bytes,
  48. size_t max_log_size,
  49. const std::string& signing_key);
  50. UnsentLogStore(const UnsentLogStore&) = delete;
  51. UnsentLogStore& operator=(const UnsentLogStore&) = delete;
  52. ~UnsentLogStore() override;
  53. struct LogInfo {
  54. LogInfo();
  55. LogInfo(const LogInfo& other);
  56. ~LogInfo();
  57. // Initializes the members based on uncompressed |log_data|,
  58. // |log_timestamp|, and |signing_key|. |log_data| is the uncompressed
  59. // serialized log protobuf. A hash and a signature are computed from
  60. // |log_data|. The signature is produced using |signing_key|. |log_data|
  61. // will be compressed and stored in |compressed_log_data|. |log_timestamp|
  62. // is stored as is. |log_metadata| is any optional metadata that will be
  63. // attached to the log.
  64. // |metrics| is the parent's metrics_ object, and should not be held.
  65. void Init(UnsentLogStoreMetrics* metrics,
  66. const std::string& log_data,
  67. const std::string& log_timestamp,
  68. const std::string& signing_key,
  69. const LogMetadata& log_metadata);
  70. // Compressed log data - a serialized protobuf that's been gzipped.
  71. std::string compressed_log_data;
  72. // The SHA1 hash of the log. Computed in Init and stored to catch errors
  73. // from memory corruption.
  74. std::string hash;
  75. // The HMAC-SHA256 signature of the log, used to validate the log came from
  76. // Chrome. It's computed in Init and stored, instead of computed on demand,
  77. // to catch errors from memory corruption.
  78. std::string signature;
  79. // The timestamp of when the log was created as a time_t value.
  80. std::string timestamp;
  81. // Properties of the log.
  82. LogMetadata log_metadata;
  83. };
  84. // LogStore:
  85. bool has_unsent_logs() const override;
  86. bool has_staged_log() const override;
  87. const std::string& staged_log() const override;
  88. const std::string& staged_log_hash() const override;
  89. const std::string& staged_log_signature() const override;
  90. absl::optional<uint64_t> staged_log_user_id() const override;
  91. void StageNextLog() override;
  92. void DiscardStagedLog() override;
  93. void MarkStagedLogAsSent() override;
  94. void TrimAndPersistUnsentLogs(bool overwrite_in_memory_store) override;
  95. void LoadPersistedUnsentLogs() override;
  96. // Adds a UMA log to the list. |log_metadata| refers to metadata associated
  97. // with the log.
  98. void StoreLog(const std::string& log_data, const LogMetadata& log_metadata);
  99. // Gets log data at the given index in the list.
  100. const std::string& GetLogAtIndex(size_t index);
  101. // Replaces the compressed log at |index| in the store with given log data and
  102. // |log_metadata| reusing the same timestamp.
  103. std::string ReplaceLogAtIndex(size_t index,
  104. const std::string& new_log_data,
  105. const LogMetadata& log_metadata);
  106. // Deletes all logs, in memory and on disk.
  107. void Purge();
  108. // Returns the timestamp of the element in the front of the list.
  109. const std::string& staged_log_timestamp() const;
  110. // The number of elements currently stored.
  111. size_t size() const { return list_.size(); }
  112. // Computes the HMAC for |log_data| using the |signing_key| and returns a bool
  113. // indicating whether the signing succeeded. The returned HMAC is written to
  114. // the |signature|.
  115. static bool ComputeHMACForLog(const std::string& log_data,
  116. const std::string& signing_key,
  117. std::string* signature);
  118. private:
  119. FRIEND_TEST_ALL_PREFIXES(UnsentLogStoreTest, UnsentLogMetadataMetrics);
  120. // Reads the list of logs from |list|.
  121. void ReadLogsFromPrefList(const base::Value::List& list);
  122. // Writes the unsent log info to the |metadata_pref_name_| preference.
  123. void WriteToMetricsPref(base::HistogramBase::Count unsent_samples_count,
  124. base::HistogramBase::Count sent_samples_count,
  125. size_t persisted_size) const;
  126. // Records the info in |metadata_pref_name_| as UMA metrics.
  127. void RecordMetaDataMetrics();
  128. // An object for recording UMA metrics.
  129. std::unique_ptr<UnsentLogStoreMetrics> metrics_;
  130. // A weak pointer to the PrefService object to read and write the preference
  131. // from. Calling code should ensure this object continues to exist for the
  132. // lifetime of the UnsentLogStore object.
  133. raw_ptr<PrefService> local_state_;
  134. // The name of the preference to serialize logs to/from.
  135. const char* log_data_pref_name_;
  136. // The name of the preference to store the unsent logs info, it could be
  137. // nullptr if the metadata isn't desired.
  138. const char* metadata_pref_name_;
  139. // We will keep at least this |min_log_count_| logs or |min_log_bytes_| bytes
  140. // of logs, whichever is greater, when trimming logs. These apply after
  141. // skipping logs greater than |max_log_size_|.
  142. const size_t min_log_count_;
  143. const size_t min_log_bytes_;
  144. // Logs greater than this size will not be written to disk.
  145. const size_t max_log_size_;
  146. // Used to create a signature of log data, in order to verify reported data is
  147. // authentic.
  148. const std::string signing_key_;
  149. // A list of all of the stored logs, stored with SHA1 hashes to check for
  150. // corruption while they are stored in memory.
  151. std::vector<std::unique_ptr<LogInfo>> list_;
  152. // The index and type of the log staged for upload. If nothing has been
  153. // staged, the index will be -1.
  154. int staged_log_index_;
  155. // The total number of samples that have been sent from this LogStore.
  156. base::HistogramBase::Count total_samples_sent_ = 0;
  157. };
  158. } // namespace metrics
  159. #endif // COMPONENTS_METRICS_UNSENT_LOG_STORE_H_