variations_seed_store.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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_VARIATIONS_VARIATIONS_SEED_STORE_H_
  5. #define COMPONENTS_VARIATIONS_VARIATIONS_SEED_STORE_H_
  6. #include <memory>
  7. #include <string>
  8. #include "base/callback.h"
  9. #include "base/component_export.h"
  10. #include "base/gtest_prod_util.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/time/time.h"
  13. #include "build/build_config.h"
  14. #include "components/variations/metrics.h"
  15. #include "components/variations/proto/variations_seed.pb.h"
  16. #include "components/variations/seed_response.h"
  17. class PrefService;
  18. class PrefRegistrySimple;
  19. namespace variations {
  20. struct ClientFilterableState;
  21. class VariationsSeed;
  22. // A seed that has passed validation.
  23. struct ValidatedSeed {
  24. // The serialized VariationsSeed bytes.
  25. std::string bytes;
  26. // A cryptographic signature on the seed_data.
  27. std::string base64_seed_signature;
  28. // The seed data parsed as a proto.
  29. VariationsSeed parsed;
  30. };
  31. // VariationsSeedStore is a helper class for reading and writing the variations
  32. // seed from Local State.
  33. class COMPONENT_EXPORT(VARIATIONS) VariationsSeedStore {
  34. public:
  35. // Standard constructor. Enables signature verification.
  36. explicit VariationsSeedStore(PrefService* local_state);
  37. // |initial_seed| may be null. If not null, then it will be stored in this
  38. // seed store. This is used by Android Chrome to supply the first run seed,
  39. // and by Android WebView to supply the seed on every run.
  40. // |signature_verification_enabled| can be used in unit tests to disable
  41. // signature checks on the seed. If |use_first_run_prefs| is true (default),
  42. // then this VariationsSeedStore may modify the Java SharedPreferences ("first
  43. // run prefs") which are set during first run; otherwise this will not access
  44. // SharedPreferences at all.
  45. VariationsSeedStore(PrefService* local_state,
  46. std::unique_ptr<SeedResponse> initial_seed,
  47. bool signature_verification_enabled,
  48. bool use_first_run_prefs = true);
  49. VariationsSeedStore(const VariationsSeedStore&) = delete;
  50. VariationsSeedStore& operator=(const VariationsSeedStore&) = delete;
  51. virtual ~VariationsSeedStore();
  52. // Loads the variations seed data from local state into |seed|, as well as the
  53. // raw pref values into |seed_data| and |base64_signature|. If there is a
  54. // problem with loading, clears the seed pref value and returns false. If
  55. // successful, fills the the outparams with the loaded data and returns true.
  56. // Virtual for testing.
  57. [[nodiscard]] virtual bool LoadSeed(VariationsSeed* seed,
  58. std::string* seed_data,
  59. std::string* base64_seed_signature);
  60. // Stores the given seed |data| (serialized protobuf) to local state, along
  61. // with a base64-encoded digital signature for seed and the date when it was
  62. // fetched. If |is_gzip_compressed| is true, treats |data| as being gzip
  63. // compressed and decompresses it before any other processing.
  64. // If |is_delta_compressed| is true, treats |data| as being delta
  65. // compressed and attempts to decode it first using the store's seed data.
  66. // The actual seed data will be base64 encoded for storage. If the string
  67. // is invalid, the existing prefs are untouched and false is returned.
  68. // Additionally, stores the |country_code| that was received with the seed in
  69. // a separate pref. On success and if |parsed_seed| is not NULL, |parsed_seed|
  70. // will be filled with the de-serialized decoded protobuf.
  71. [[nodiscard]] bool StoreSeedData(const std::string& data,
  72. const std::string& base64_seed_signature,
  73. const std::string& country_code,
  74. const base::Time& date_fetched,
  75. bool is_delta_compressed,
  76. bool is_gzip_compressed,
  77. VariationsSeed* parsed_seed);
  78. // Loads the safe variations seed data from local state into |seed| and
  79. // updates any relevant fields in |client_state|. Returns true iff the safe
  80. // seed was read successfully from prefs. If the safe seed could not be
  81. // loaded, it is guaranteed that no fields in |client_state| are modified.
  82. //
  83. // Side effect: Upon failing to read or validate the safe seed, clears all
  84. // of the safe seed pref values.
  85. //
  86. // Virtual for testing.
  87. [[nodiscard]] virtual bool LoadSafeSeed(VariationsSeed* seed,
  88. ClientFilterableState* client_state);
  89. // Stores the given |seed_data| (a serialized protobuf) to local state as a
  90. // safe seed, along with a base64-encoded digital signature for seed and any
  91. // additional client metadata relevant to the safe seed. Returns true on
  92. // success or false on failure; no prefs are updated in case of failure.
  93. // Virtual for testing.
  94. virtual bool StoreSafeSeed(const std::string& seed_data,
  95. const std::string& base64_seed_signature,
  96. int seed_milestone,
  97. const ClientFilterableState& client_state,
  98. base::Time seed_fetch_time);
  99. // Loads the last fetch time (for the latest seed) that was persisted to the
  100. // store.
  101. base::Time GetLastFetchTime() const;
  102. // Returns the time at which the safe seed was fetched.
  103. base::Time GetSafeSeedFetchTime() const;
  104. // Records |fetch_time| as the last time at which a seed was fetched
  105. // successfully. Also updates the safe seed's fetch time if the latest and
  106. // safe seeds are identical.
  107. void RecordLastFetchTime(base::Time fetch_time);
  108. // Updates |kVariationsSeedDate| and logs when previous date was from a
  109. // different day.
  110. void UpdateSeedDateAndLogDayChange(const base::Time& server_date_fetched);
  111. // Returns the serial number of the most recently received seed, or an empty
  112. // string if there is no seed (or if it could not be read).
  113. // Side-effect: If there is a failure while attempting to read the latest seed
  114. // from prefs, clears the prefs associated with the seed.
  115. // Efficiency note: If code will eventually need to load the latest seed, it's
  116. // more efficient to call LoadSeed() prior to calling this method.
  117. const std::string& GetLatestSerialNumber();
  118. // Registers Local State prefs used by this class.
  119. static void RegisterPrefs(PrefRegistrySimple* registry);
  120. PrefService* local_state() { return local_state_; }
  121. const PrefService* local_state() const { return local_state_; }
  122. static VerifySignatureResult VerifySeedSignatureForTesting(
  123. const std::string& seed_bytes,
  124. const std::string& base64_seed_signature);
  125. private:
  126. FRIEND_TEST_ALL_PREFIXES(VariationsSeedStoreTest, VerifySeedSignature);
  127. FRIEND_TEST_ALL_PREFIXES(VariationsSeedStoreTest, ApplyDeltaPatch);
  128. // The seed store contains two distinct seeds:
  129. // (1) The most recently fetched, or "latest", seed; and
  130. // (2) A "safe" seed, which has been observed to keep Chrome in a basically
  131. // functional state. In particular, a safe seed is one that allows
  132. // Chrome to receive new seed updates from the server.
  133. // Note that it's possible for both seeds to be empty, and it's possible for
  134. // the two seeds to be identical in their contents.
  135. enum class SeedType {
  136. LATEST,
  137. SAFE,
  138. };
  139. // Clears all prefs related to variations seed storage for the specified seed
  140. // type.
  141. void ClearPrefs(SeedType seed_type);
  142. #if BUILDFLAG(IS_ANDROID)
  143. // Imports the variations seed from the Java side. Logs UMA on failure.
  144. // Android Chrome uses this on first run; WebView uses this on every startup.
  145. // In Chrome's case, it's important to set the first run seed as soon as
  146. // possible, because some clients query the seed store prefs directly rather
  147. // than accessing them via the seed store API: https://crbug.com/829527
  148. void ImportInitialSeed(std::unique_ptr<SeedResponse> initial_seed);
  149. #endif // BUILDFLAG(IS_ANDROID)
  150. // Loads the variations seed data from local state into |seed|, as well as the
  151. // raw pref values into |seed_data| and |base64_signature|. Loads either the
  152. // safe seed or the latest seed, according to the |seed_type|. Returns whether
  153. // loading the seed was successful.
  154. // Side-effect: Upon any failure to read or validate the safe seed, clears all
  155. // of the pref values for the seed. This occurs iff the method returns false.
  156. [[nodiscard]] LoadSeedResult LoadSeedImpl(SeedType seed_type,
  157. VariationsSeed* seed,
  158. std::string* seed_data,
  159. std::string* base64_seed_signature);
  160. // Reads the variations seed data from prefs into |seed_data|, and returns the
  161. // result of the load. The value stored into |seed_data| should only be used
  162. // if the result is SUCCESS. Reads either the latest or the safe seed,
  163. // according to the specified |seed_type|.
  164. // Side-effect: If the read fails, clears the prefs associated with the seed.
  165. [[nodiscard]] LoadSeedResult ReadSeedData(SeedType seed_type,
  166. std::string* seed_data);
  167. // Resolves a |delta_bytes| against the latest seed.
  168. // Returns success or an error, populating |seed_bytes| on success.
  169. [[nodiscard]] StoreSeedResult ResolveDelta(const std::string& delta_bytes,
  170. std::string* seed_bytes);
  171. // Resolves instance manipulations applied to received data.
  172. // Returns success or an error, populating |seed_bytes| on success.
  173. [[nodiscard]] StoreSeedResult ResolveInstanceManipulations(
  174. const std::string& data,
  175. const InstanceManipulations& im,
  176. std::string* seed_bytes);
  177. // Validates that |seed_bytes| parses and matches |base64_seed_signature|.
  178. // Signature checking may be disabled via |signature_verification_enabled_|.
  179. // |seed_type| indicates the source of the seed for logging purposes.
  180. // |result| must be non-null, and will be populated on success.
  181. // Returns success or some error value.
  182. [[nodiscard]] StoreSeedResult ValidateSeedBytes(
  183. const std::string& seed_bytes,
  184. const std::string& base64_seed_signature,
  185. SeedType seed_type,
  186. ValidatedSeed* result);
  187. // Gzip compresses and base64 encodes a validated seed.
  188. // Returns success or error and populates base64_seed_data on success.
  189. [[nodiscard]] StoreSeedResult CompressSeedBytes(
  190. const ValidatedSeed& validated,
  191. std::string* base64_seed_data);
  192. // Updates the latest seed with validated data.
  193. [[nodiscard]] StoreSeedResult StoreValidatedSeed(
  194. const ValidatedSeed& seed,
  195. const std::string& country_code,
  196. const base::Time& date_fetched);
  197. // Updates the safe seed with validated data.
  198. [[nodiscard]] StoreSeedResult StoreValidatedSafeSeed(
  199. const ValidatedSeed& seed,
  200. int seed_milestone,
  201. const ClientFilterableState& client_state,
  202. base::Time seed_fetch_time);
  203. // Applies a delta-compressed |patch| to |existing_data|, producing the result
  204. // in |output|. Returns whether the operation was successful.
  205. [[nodiscard]] static bool ApplyDeltaPatch(const std::string& existing_data,
  206. const std::string& patch,
  207. std::string* output);
  208. // The pref service used to persist the variations seed.
  209. raw_ptr<PrefService> local_state_;
  210. // Cached serial number from the most recently fetched variations seed.
  211. std::string latest_serial_number_;
  212. // Whether to validate signatures on the seed. Always on except in unit tests.
  213. const bool signature_verification_enabled_;
  214. // Whether this may read or write to Java "first run" SharedPreferences.
  215. const bool use_first_run_prefs_;
  216. };
  217. } // namespace variations
  218. #endif // COMPONENTS_VARIATIONS_VARIATIONS_SEED_STORE_H_