blob: 714e18b1208209d854bf7f5d73a52e61a51d4a05 [file] [log] [blame]
[email protected]1df24d0a2014-01-20 21:29:591// 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
blundell0b2305c2015-08-25 15:54:425#ifndef COMPONENTS_VARIATIONS_VARIATIONS_SEED_STORE_H_
6#define COMPONENTS_VARIATIONS_VARIATIONS_SEED_STORE_H_
[email protected]1df24d0a2014-01-20 21:29:597
Paul Miller49eebb82018-06-14 04:11:088#include <memory>
[email protected]1df24d0a2014-01-20 21:29:599#include <string>
10
Paul Miller33a495e2018-09-29 04:35:0211#include "base/callback.h"
Scott Violet69a5d8dd2021-06-01 23:46:4812#include "base/component_export.h"
[email protected]c69b6c12014-03-07 20:32:3613#include "base/gtest_prod_util.h"
Keishi Hattori0e45c022021-11-27 09:25:5214#include "base/memory/raw_ptr.h"
[email protected]1df24d0a2014-01-20 21:29:5915#include "base/time/time.h"
avi5dd91f82015-12-25 22:30:4616#include "build/build_config.h"
isherman5f556b512017-06-14 16:27:2317#include "components/variations/metrics.h"
Steven Holte75115332e2021-08-09 23:55:0818#include "components/variations/proto/variations_seed.pb.h"
Paul Miller49eebb82018-06-14 04:11:0819#include "components/variations/seed_response.h"
[email protected]1df24d0a2014-01-20 21:29:5920
21class PrefService;
22class PrefRegistrySimple;
23
[email protected]59b6f672014-07-26 18:35:4724namespace variations {
[email protected]59b6f672014-07-26 18:35:4725
Ilya Sherman3231a202018-01-13 05:15:0126struct ClientFilterableState;
ishermanb1917aabe2017-06-13 23:35:1427class VariationsSeed;
[email protected]24afce12014-07-25 21:00:3128
Steven Holte75115332e2021-08-09 23:55:0829// A seed that has passed validation.
30struct ValidatedSeed {
31 // The serialized VariationsSeed bytes.
32 std::string bytes;
33 // A cryptographic signature on the seed_data.
34 std::string base64_seed_signature;
35 // The seed data parsed as a proto.
36 VariationsSeed parsed;
37};
38
[email protected]1df24d0a2014-01-20 21:29:5939// VariationsSeedStore is a helper class for reading and writing the variations
40// seed from Local State.
Scott Violet69a5d8dd2021-06-01 23:46:4841class COMPONENT_EXPORT(VARIATIONS) VariationsSeedStore {
[email protected]1df24d0a2014-01-20 21:29:5942 public:
Adrian Taylor2613db72020-05-20 20:26:5543 // Standard constructor. Enables signature verification.
[email protected]1df24d0a2014-01-20 21:29:5944 explicit VariationsSeedStore(PrefService* local_state);
Paul Miller49eebb82018-06-14 04:11:0845 // |initial_seed| may be null. If not null, then it will be stored in this
46 // seed store. This is used by Android Chrome to supply the first run seed,
47 // and by Android WebView to supply the seed on every run.
Adrian Taylor2613db72020-05-20 20:26:5548 // |signature_verification_enabled| can be used in unit tests to disable
Nate Fischer0d7bb6db2020-10-05 21:49:4849 // signature checks on the seed. If |use_first_run_prefs| is true (default),
50 // then this VariationsSeedStore may modify the Java SharedPreferences ("first
51 // run prefs") which are set during first run; otherwise this will not access
52 // SharedPreferences at all.
Paul Miller49eebb82018-06-14 04:11:0853 VariationsSeedStore(PrefService* local_state,
Paul Miller33a495e2018-09-29 04:35:0254 std::unique_ptr<SeedResponse> initial_seed,
Nate Fischer0d7bb6db2020-10-05 21:49:4855 bool signature_verification_enabled,
56 bool use_first_run_prefs = true);
Peter Boström09c01822021-09-20 22:43:2757
58 VariationsSeedStore(const VariationsSeedStore&) = delete;
59 VariationsSeedStore& operator=(const VariationsSeedStore&) = delete;
60
[email protected]1df24d0a2014-01-20 21:29:5961 virtual ~VariationsSeedStore();
62
Ilya Sherman3231a202018-01-13 05:15:0163 // Loads the variations seed data from local state into |seed|, as well as the
64 // raw pref values into |seed_data| and |base64_signature|. If there is a
65 // problem with loading, clears the seed pref value and returns false. If
66 // successful, fills the the outparams with the loaded data and returns true.
Ilya Sherman9534f1d2018-01-24 04:02:2067 // Virtual for testing.
Daniel Cheng5cda1cf32022-01-13 23:33:4368 [[nodiscard]] virtual bool LoadSeed(VariationsSeed* seed,
69 std::string* seed_data,
70 std::string* base64_seed_signature);
[email protected]1df24d0a2014-01-20 21:29:5971
asvitkineb24f45592015-08-07 02:57:2572 // Stores the given seed |data| (serialized protobuf) to local state, along
[email protected]54af732e2014-01-23 22:20:3973 // with a base64-encoded digital signature for seed and the date when it was
veranikaf6acefe762015-10-19 16:37:5674 // fetched. If |is_gzip_compressed| is true, treats |data| as being gzip
75 // compressed and decompresses it before any other processing.
76 // If |is_delta_compressed| is true, treats |data| as being delta
asvitkineb24f45592015-08-07 02:57:2577 // compressed and attempts to decode it first using the store's seed data.
78 // The actual seed data will be base64 encoded for storage. If the string
79 // is invalid, the existing prefs are untouched and false is returned.
80 // Additionally, stores the |country_code| that was received with the seed in
81 // a separate pref. On success and if |parsed_seed| is not NULL, |parsed_seed|
82 // will be filled with the de-serialized decoded protobuf.
Daniel Cheng5cda1cf32022-01-13 23:33:4383 [[nodiscard]] bool StoreSeedData(const std::string& data,
84 const std::string& base64_seed_signature,
85 const std::string& country_code,
86 const base::Time& date_fetched,
87 bool is_delta_compressed,
88 bool is_gzip_compressed,
89 VariationsSeed* parsed_seed);
[email protected]1df24d0a2014-01-20 21:29:5990
Caitlin Fischer4dc0babf2021-07-23 03:20:5791 // Loads the safe variations seed data from local state into |seed| and
Caitlin Fischerc1a31b12022-02-08 19:40:3292 // updates any relevant fields in |client_state|. Returns true iff the safe
93 // seed was read successfully from prefs. If the safe seed could not be
94 // loaded, it is guaranteed that no fields in |client_state| are modified.
Caitlin Fischer4700f752021-06-29 02:20:1195 //
96 // Side effect: Upon failing to read or validate the safe seed, clears all
97 // of the safe seed pref values.
98 //
Ilya Sherman9534f1d2018-01-24 04:02:2099 // Virtual for testing.
Caitlin Fischerc1a31b12022-02-08 19:40:32100 [[nodiscard]] virtual bool LoadSafeSeed(VariationsSeed* seed,
101 ClientFilterableState* client_state);
Ilya Shermane3b22a62018-01-22 06:10:21102
Ilya Sherman3231a202018-01-13 05:15:01103 // Stores the given |seed_data| (a serialized protobuf) to local state as a
104 // safe seed, along with a base64-encoded digital signature for seed and any
105 // additional client metadata relevant to the safe seed. Returns true on
106 // success or false on failure; no prefs are updated in case of failure.
107 // Virtual for testing.
108 virtual bool StoreSafeSeed(const std::string& seed_data,
109 const std::string& base64_seed_signature,
Caitlin Fischerbf634b62021-10-30 00:07:22110 int seed_milestone,
Ilya Sherman279eff32018-01-31 04:28:32111 const ClientFilterableState& client_state,
112 base::Time seed_fetch_time);
113
114 // Loads the last fetch time (for the latest seed) that was persisted to the
115 // store.
116 base::Time GetLastFetchTime() const;
117
Caitlin Fischer4dc0babf2021-07-23 03:20:57118 // Returns the time at which the safe seed was fetched.
119 base::Time GetSafeSeedFetchTime() const;
120
Robbie McElrath27890f12019-10-16 17:25:59121 // Records |fetch_time| as the last time at which a seed was fetched
Ilya Sherman279eff32018-01-31 04:28:32122 // successfully. Also updates the safe seed's fetch time if the latest and
123 // safe seeds are identical.
Robbie McElrath27890f12019-10-16 17:25:59124 void RecordLastFetchTime(base::Time fetch_time);
Ilya Sherman3231a202018-01-13 05:15:01125
[email protected]344c623a2014-03-11 20:29:39126 // Updates |kVariationsSeedDate| and logs when previous date was from a
127 // different day.
128 void UpdateSeedDateAndLogDayChange(const base::Time& server_date_fetched);
129
Ilya Shermanc70363ec2018-01-17 05:51:57130 // Returns the serial number of the most recently received seed, or an empty
131 // string if there is no seed (or if it could not be read).
132 // Side-effect: If there is a failure while attempting to read the latest seed
133 // from prefs, clears the prefs associated with the seed.
134 // Efficiency note: If code will eventually need to load the latest seed, it's
135 // more efficient to call LoadSeed() prior to calling this method.
136 const std::string& GetLatestSerialNumber();
[email protected]1df24d0a2014-01-20 21:29:59137
asvitkineb24f45592015-08-07 02:57:25138 // Registers Local State prefs used by this class.
139 static void RegisterPrefs(PrefRegistrySimple* registry);
140
Kyle Milka3aababd2017-07-20 19:01:32141 PrefService* local_state() { return local_state_; }
Kyle Milka3aababd2017-07-20 19:01:32142 const PrefService* local_state() const { return local_state_; }
143
Roger McFarlane3da6db2732021-10-06 13:41:04144 static VerifySignatureResult VerifySeedSignatureForTesting(
145 const std::string& seed_bytes,
146 const std::string& base64_seed_signature);
147
[email protected]1df24d0a2014-01-20 21:29:59148 private:
[email protected]c69b6c12014-03-07 20:32:36149 FRIEND_TEST_ALL_PREFIXES(VariationsSeedStoreTest, VerifySeedSignature);
asvitkineb24f45592015-08-07 02:57:25150 FRIEND_TEST_ALL_PREFIXES(VariationsSeedStoreTest, ApplyDeltaPatch);
[email protected]c69b6c12014-03-07 20:32:36151
Ilya Sherman3231a202018-01-13 05:15:01152 // The seed store contains two distinct seeds:
153 // (1) The most recently fetched, or "latest", seed; and
154 // (2) A "safe" seed, which has been observed to keep Chrome in a basically
155 // functional state. In particular, a safe seed is one that allows
156 // Chrome to receive new seed updates from the server.
157 // Note that it's possible for both seeds to be empty, and it's possible for
158 // the two seeds to be identical in their contents.
159 enum class SeedType {
160 LATEST,
161 SAFE,
162 };
163
Ilya Shermane3b22a62018-01-22 06:10:21164 // Clears all prefs related to variations seed storage for the specified seed
165 // type.
166 void ClearPrefs(SeedType seed_type);
[email protected]54af732e2014-01-23 22:20:39167
Xiaohan Wangd30b05ae2022-01-14 19:51:28168#if BUILDFLAG(IS_ANDROID)
Paul Miller49eebb82018-06-14 04:11:08169 // Imports the variations seed from the Java side. Logs UMA on failure.
170 // Android Chrome uses this on first run; WebView uses this on every startup.
171 // In Chrome's case, it's important to set the first run seed as soon as
172 // possible, because some clients query the seed store prefs directly rather
173 // than accessing them via the seed store API: https://crbug.com/829527
174 void ImportInitialSeed(std::unique_ptr<SeedResponse> initial_seed);
Xiaohan Wangd30b05ae2022-01-14 19:51:28175#endif // BUILDFLAG(IS_ANDROID)
agulenko25d2111a2015-11-05 05:16:16176
Ilya Shermane3b22a62018-01-22 06:10:21177 // Loads the variations seed data from local state into |seed|, as well as the
178 // raw pref values into |seed_data| and |base64_signature|. Loads either the
179 // safe seed or the latest seed, according to the |seed_type|. Returns whether
180 // loading the seed was successful.
181 // Side-effect: Upon any failure to read or validate the safe seed, clears all
182 // of the pref values for the seed. This occurs iff the method returns false.
Daniel Cheng5cda1cf32022-01-13 23:33:43183 [[nodiscard]] LoadSeedResult LoadSeedImpl(SeedType seed_type,
184 VariationsSeed* seed,
185 std::string* seed_data,
186 std::string* base64_seed_signature);
Ilya Shermane3b22a62018-01-22 06:10:21187
isherman5f556b512017-06-14 16:27:23188 // Reads the variations seed data from prefs into |seed_data|, and returns the
189 // result of the load. The value stored into |seed_data| should only be used
Ilya Shermane3b22a62018-01-22 06:10:21190 // if the result is SUCCESS. Reads either the latest or the safe seed,
191 // according to the specified |seed_type|.
isherman5f556b512017-06-14 16:27:23192 // Side-effect: If the read fails, clears the prefs associated with the seed.
Daniel Cheng5cda1cf32022-01-13 23:33:43193 [[nodiscard]] LoadSeedResult ReadSeedData(SeedType seed_type,
194 std::string* seed_data);
asvitkine5ea32c52015-02-12 01:23:11195
Steven Holte75115332e2021-08-09 23:55:08196 // Resolves a |delta_bytes| against the latest seed.
197 // Returns success or an error, populating |seed_bytes| on success.
Daniel Cheng5cda1cf32022-01-13 23:33:43198 [[nodiscard]] StoreSeedResult ResolveDelta(const std::string& delta_bytes,
199 std::string* seed_bytes);
asvitkineb24f45592015-08-07 02:57:25200
Steven Holte75115332e2021-08-09 23:55:08201 // Resolves instance manipulations applied to received data.
202 // Returns success or an error, populating |seed_bytes| on success.
Daniel Cheng5cda1cf32022-01-13 23:33:43203 [[nodiscard]] StoreSeedResult ResolveInstanceManipulations(
204 const std::string& data,
205 const InstanceManipulations& im,
206 std::string* seed_bytes);
Steven Holte75115332e2021-08-09 23:55:08207
208 // Validates that |seed_bytes| parses and matches |base64_seed_signature|.
209 // Signature checking may be disabled via |signature_verification_enabled_|.
210 // |seed_type| indicates the source of the seed for logging purposes.
211 // |result| must be non-null, and will be populated on success.
212 // Returns success or some error value.
Daniel Cheng5cda1cf32022-01-13 23:33:43213 [[nodiscard]] StoreSeedResult ValidateSeedBytes(
214 const std::string& seed_bytes,
215 const std::string& base64_seed_signature,
216 SeedType seed_type,
217 ValidatedSeed* result);
Steven Holte75115332e2021-08-09 23:55:08218
219 // Gzip compresses and base64 encodes a validated seed.
220 // Returns success or error and populates base64_seed_data on success.
Daniel Cheng5cda1cf32022-01-13 23:33:43221 [[nodiscard]] StoreSeedResult CompressSeedBytes(
222 const ValidatedSeed& validated,
223 std::string* base64_seed_data);
Steven Holte75115332e2021-08-09 23:55:08224
225 // Updates the latest seed with validated data.
Daniel Cheng5cda1cf32022-01-13 23:33:43226 [[nodiscard]] StoreSeedResult StoreValidatedSeed(
227 const ValidatedSeed& seed,
228 const std::string& country_code,
229 const base::Time& date_fetched);
Steven Holte75115332e2021-08-09 23:55:08230
231 // Updates the safe seed with validated data.
Daniel Cheng5cda1cf32022-01-13 23:33:43232 [[nodiscard]] StoreSeedResult StoreValidatedSafeSeed(
Caitlin Fischerbf634b62021-10-30 00:07:22233 const ValidatedSeed& seed,
234 int seed_milestone,
Steven Holte75115332e2021-08-09 23:55:08235 const ClientFilterableState& client_state,
Daniel Cheng5cda1cf32022-01-13 23:33:43236 base::Time seed_fetch_time);
Ilya Sherman3231a202018-01-13 05:15:01237
asvitkineb24f45592015-08-07 02:57:25238 // Applies a delta-compressed |patch| to |existing_data|, producing the result
239 // in |output|. Returns whether the operation was successful.
Daniel Cheng5cda1cf32022-01-13 23:33:43240 [[nodiscard]] static bool ApplyDeltaPatch(const std::string& existing_data,
241 const std::string& patch,
242 std::string* output);
asvitkineb24f45592015-08-07 02:57:25243
[email protected]1df24d0a2014-01-20 21:29:59244 // The pref service used to persist the variations seed.
Keishi Hattori0e45c022021-11-27 09:25:52245 raw_ptr<PrefService> local_state_;
[email protected]1df24d0a2014-01-20 21:29:59246
247 // Cached serial number from the most recently fetched variations seed.
Ilya Shermanc70363ec2018-01-17 05:51:57248 std::string latest_serial_number_;
[email protected]1df24d0a2014-01-20 21:29:59249
Caitlin Fischer6920a082021-06-29 05:25:24250 // Whether to validate signatures on the seed. Always on except in unit tests.
Nate Fischer0d7bb6db2020-10-05 21:49:48251 const bool signature_verification_enabled_;
252
253 // Whether this may read or write to Java "first run" SharedPreferences.
254 const bool use_first_run_prefs_;
[email protected]1df24d0a2014-01-20 21:29:59255};
256
blundell57bcfed2015-09-04 08:44:45257} // namespace variations
[email protected]1df24d0a2014-01-20 21:29:59258
blundell0b2305c2015-08-25 15:54:42259#endif // COMPONENTS_VARIATIONS_VARIATIONS_SEED_STORE_H_