blob: 839c5b6b6926c3213dbc661d4ccc71e4a0dc4a73 [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"
[email protected]1df24d0a2014-01-20 21:29:5912#include "base/compiler_specific.h"
[email protected]c69b6c12014-03-07 20:32:3613#include "base/gtest_prod_util.h"
avi5dd91f82015-12-25 22:30:4614#include "base/macros.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"
isherman5f556b52017-06-14 16:27:2317#include "components/variations/metrics.h"
Paul Miller49eebb82018-06-14 04:11:0818#include "components/variations/seed_response.h"
[email protected]1df24d0a2014-01-20 21:29:5919
20class PrefService;
21class PrefRegistrySimple;
22
[email protected]59b6f672014-07-26 18:35:4723namespace variations {
[email protected]59b6f672014-07-26 18:35:4724
Ilya Sherman3231a202018-01-13 05:15:0125struct ClientFilterableState;
ishermanb1917aabe2017-06-13 23:35:1426class VariationsSeed;
[email protected]24afce12014-07-25 21:00:3127
[email protected]1df24d0a2014-01-20 21:29:5928// VariationsSeedStore is a helper class for reading and writing the variations
29// seed from Local State.
30class VariationsSeedStore {
31 public:
32 explicit VariationsSeedStore(PrefService* local_state);
Paul Miller49eebb82018-06-14 04:11:0833 // |initial_seed| may be null. If not null, then it will be stored in this
34 // seed store. This is used by Android Chrome to supply the first run seed,
35 // and by Android WebView to supply the seed on every run.
Paul Miller33a495e2018-09-29 04:35:0236 // |on_initial_seed_stored| will be called the first time a seed is stored.
Paul Miller49eebb82018-06-14 04:11:0837 VariationsSeedStore(PrefService* local_state,
Paul Miller33a495e2018-09-29 04:35:0238 std::unique_ptr<SeedResponse> initial_seed,
39 base::OnceCallback<void()> on_initial_seed_stored);
[email protected]1df24d0a2014-01-20 21:29:5940 virtual ~VariationsSeedStore();
41
Ilya Sherman3231a202018-01-13 05:15:0142 // Loads the variations seed data from local state into |seed|, as well as the
43 // raw pref values into |seed_data| and |base64_signature|. If there is a
44 // problem with loading, clears the seed pref value and returns false. If
45 // successful, fills the the outparams with the loaded data and returns true.
Ilya Sherman9534f1d2018-01-24 04:02:2046 // Virtual for testing.
47 virtual bool LoadSeed(VariationsSeed* seed,
48 std::string* seed_data,
49 std::string* base64_seed_signature) WARN_UNUSED_RESULT;
[email protected]1df24d0a2014-01-20 21:29:5950
asvitkineb24f45592015-08-07 02:57:2551 // Stores the given seed |data| (serialized protobuf) to local state, along
[email protected]54af732e2014-01-23 22:20:3952 // with a base64-encoded digital signature for seed and the date when it was
veranikaf6acefe762015-10-19 16:37:5653 // fetched. If |is_gzip_compressed| is true, treats |data| as being gzip
54 // compressed and decompresses it before any other processing.
55 // If |is_delta_compressed| is true, treats |data| as being delta
asvitkineb24f45592015-08-07 02:57:2556 // compressed and attempts to decode it first using the store's seed data.
57 // The actual seed data will be base64 encoded for storage. If the string
58 // is invalid, the existing prefs are untouched and false is returned.
59 // Additionally, stores the |country_code| that was received with the seed in
60 // a separate pref. On success and if |parsed_seed| is not NULL, |parsed_seed|
61 // will be filled with the de-serialized decoded protobuf.
62 bool StoreSeedData(const std::string& data,
[email protected]54af732e2014-01-23 22:20:3963 const std::string& base64_seed_signature,
asvitkineb24f45592015-08-07 02:57:2564 const std::string& country_code,
[email protected]6839813b2014-05-12 22:49:4065 const base::Time& date_fetched,
asvitkineb24f45592015-08-07 02:57:2566 bool is_delta_compressed,
veranikaf6acefe762015-10-19 16:37:5667 bool is_gzip_compressed,
Carlos ILf8472f5f2017-12-19 03:23:2668 bool fetched_insecurely,
isherman5f556b52017-06-14 16:27:2369 VariationsSeed* parsed_seed) WARN_UNUSED_RESULT;
[email protected]1df24d0a2014-01-20 21:29:5970
Ilya Shermane3b22a62018-01-22 06:10:2171 // Loads the safe variations seed data from local state into |seed| and
Ilya Sherman279eff32018-01-31 04:28:3272 // updates any relevant fields in |client_state| and stores the
73 // |seed_fetch_time|. Returns true iff the safe seed was read successfully
74 // from prefs. If the safe seed could not be loaded, it is guaranteed that no
75 // fields in |client_state| are modified.
Ilya Shermane3b22a62018-01-22 06:10:2176 // Side-effect: Upon any failure to read or validate the safe seed, clears all
77 // of the safe seed pref values. This occurs iff the method returns false.
Ilya Sherman9534f1d2018-01-24 04:02:2078 // Virtual for testing.
79 virtual bool LoadSafeSeed(VariationsSeed* seed,
Ilya Sherman279eff32018-01-31 04:28:3280 ClientFilterableState* client_state,
81 base::Time* seed_fetch_time) WARN_UNUSED_RESULT;
Ilya Shermane3b22a62018-01-22 06:10:2182
Ilya Sherman3231a202018-01-13 05:15:0183 // Stores the given |seed_data| (a serialized protobuf) to local state as a
84 // safe seed, along with a base64-encoded digital signature for seed and any
85 // additional client metadata relevant to the safe seed. Returns true on
86 // success or false on failure; no prefs are updated in case of failure.
87 // Virtual for testing.
88 virtual bool StoreSafeSeed(const std::string& seed_data,
89 const std::string& base64_seed_signature,
Ilya Sherman279eff32018-01-31 04:28:3290 const ClientFilterableState& client_state,
91 base::Time seed_fetch_time);
92
93 // Loads the last fetch time (for the latest seed) that was persisted to the
94 // store.
95 base::Time GetLastFetchTime() const;
96
Robbie McElrath27890f12019-10-16 17:25:5997 // Records |fetch_time| as the last time at which a seed was fetched
Ilya Sherman279eff32018-01-31 04:28:3298 // successfully. Also updates the safe seed's fetch time if the latest and
99 // safe seeds are identical.
Robbie McElrath27890f12019-10-16 17:25:59100 void RecordLastFetchTime(base::Time fetch_time);
Ilya Sherman3231a202018-01-13 05:15:01101
[email protected]344c623a2014-03-11 20:29:39102 // Updates |kVariationsSeedDate| and logs when previous date was from a
103 // different day.
104 void UpdateSeedDateAndLogDayChange(const base::Time& server_date_fetched);
105
veranikaf6acefe762015-10-19 16:37:56106 // Reports to UMA that the seed format specified by the server is unsupported.
107 void ReportUnsupportedSeedFormatError();
108
Ilya Shermanc70363ec2018-01-17 05:51:57109 // Returns the serial number of the most recently received seed, or an empty
110 // string if there is no seed (or if it could not be read).
111 // Side-effect: If there is a failure while attempting to read the latest seed
112 // from prefs, clears the prefs associated with the seed.
113 // Efficiency note: If code will eventually need to load the latest seed, it's
114 // more efficient to call LoadSeed() prior to calling this method.
115 const std::string& GetLatestSerialNumber();
[email protected]1df24d0a2014-01-20 21:29:59116
asvitkineb24f45592015-08-07 02:57:25117 // Registers Local State prefs used by this class.
118 static void RegisterPrefs(PrefRegistrySimple* registry);
119
Kyle Milka3aababd2017-07-20 19:01:32120 PrefService* local_state() { return local_state_; }
Kyle Milka3aababd2017-07-20 19:01:32121 const PrefService* local_state() const { return local_state_; }
122
[email protected]c69b6c12014-03-07 20:32:36123 protected:
isherman5f556b52017-06-14 16:27:23124 // Whether signature verification is enabled. Overridable for tests.
125 virtual bool SignatureVerificationEnabled();
[email protected]c69b6c12014-03-07 20:32:36126
[email protected]1df24d0a2014-01-20 21:29:59127 private:
[email protected]c69b6c12014-03-07 20:32:36128 FRIEND_TEST_ALL_PREFIXES(VariationsSeedStoreTest, VerifySeedSignature);
asvitkineb24f45592015-08-07 02:57:25129 FRIEND_TEST_ALL_PREFIXES(VariationsSeedStoreTest, ApplyDeltaPatch);
[email protected]c69b6c12014-03-07 20:32:36130
Ilya Sherman3231a202018-01-13 05:15:01131 // The seed store contains two distinct seeds:
132 // (1) The most recently fetched, or "latest", seed; and
133 // (2) A "safe" seed, which has been observed to keep Chrome in a basically
134 // functional state. In particular, a safe seed is one that allows
135 // Chrome to receive new seed updates from the server.
136 // Note that it's possible for both seeds to be empty, and it's possible for
137 // the two seeds to be identical in their contents.
138 enum class SeedType {
139 LATEST,
140 SAFE,
141 };
142
Ilya Shermane3b22a62018-01-22 06:10:21143 // Clears all prefs related to variations seed storage for the specified seed
144 // type.
145 void ClearPrefs(SeedType seed_type);
[email protected]54af732e2014-01-23 22:20:39146
agulenko25d2111a2015-11-05 05:16:16147#if defined(OS_ANDROID)
Paul Miller49eebb82018-06-14 04:11:08148 // Imports the variations seed from the Java side. Logs UMA on failure.
149 // Android Chrome uses this on first run; WebView uses this on every startup.
150 // In Chrome's case, it's important to set the first run seed as soon as
151 // possible, because some clients query the seed store prefs directly rather
152 // than accessing them via the seed store API: https://crbug.com/829527
153 void ImportInitialSeed(std::unique_ptr<SeedResponse> initial_seed);
agulenko25d2111a2015-11-05 05:16:16154#endif // OS_ANDROID
155
Ilya Shermane3b22a62018-01-22 06:10:21156 // Loads the variations seed data from local state into |seed|, as well as the
157 // raw pref values into |seed_data| and |base64_signature|. Loads either the
158 // safe seed or the latest seed, according to the |seed_type|. Returns whether
159 // loading the seed was successful.
160 // Side-effect: Upon any failure to read or validate the safe seed, clears all
161 // of the pref values for the seed. This occurs iff the method returns false.
162 LoadSeedResult LoadSeedImpl(SeedType seed_type,
163 VariationsSeed* seed,
164 std::string* seed_data,
165 std::string* base64_seed_signature)
166 WARN_UNUSED_RESULT;
167
isherman5f556b52017-06-14 16:27:23168 // Reads the variations seed data from prefs into |seed_data|, and returns the
169 // result of the load. The value stored into |seed_data| should only be used
Ilya Shermane3b22a62018-01-22 06:10:21170 // if the result is SUCCESS. Reads either the latest or the safe seed,
171 // according to the specified |seed_type|.
isherman5f556b52017-06-14 16:27:23172 // Side-effect: If the read fails, clears the prefs associated with the seed.
Ilya Shermane3b22a62018-01-22 06:10:21173 LoadSeedResult ReadSeedData(SeedType seed_type,
174 std::string* seed_data) WARN_UNUSED_RESULT;
asvitkine5ea32c52015-02-12 01:23:11175
asvitkineb24f45592015-08-07 02:57:25176 // Internal version of |StoreSeedData()| that assumes |seed_data| is not delta
177 // compressed.
ishermanb1917aabe2017-06-13 23:35:14178 bool StoreSeedDataNoDelta(const std::string& seed_data,
179 const std::string& base64_seed_signature,
180 const std::string& country_code,
181 const base::Time& date_fetched,
Carlos ILf8472f5f2017-12-19 03:23:26182 bool fetched_insecurely,
isherman5f556b52017-06-14 16:27:23183 VariationsSeed* parsed_seed) WARN_UNUSED_RESULT;
asvitkineb24f45592015-08-07 02:57:25184
Ilya Sherman3231a202018-01-13 05:15:01185 // Validates the |seed_data|, comparing it (if enabled) against the provided
186 // cryptographic signature. Returns the result of the operation. On success,
187 // fills |base64_seed_data| with the compressed and base64-encoded seed data;
188 // and if |parsed_seed| is non-null, fills it with the parsed seed data.
189 // |fetched_insecurely| indicates whether |seed_data| was just fetched from
190 // the server over an insecure channel (i.e. over HTTP rathern than HTTPS).
191 // |seed_type| specifies whether |seed_data| is for the safe seed (vs. the
192 // regular/normal seed).
193 StoreSeedResult VerifyAndCompressSeedData(
194 const std::string& seed_data,
195 const std::string& base64_seed_signature,
196 bool fetched_insecurely,
197 SeedType seed_type,
198 std::string* base64_seed_data,
199 VariationsSeed* parsed_seed) WARN_UNUSED_RESULT;
200
asvitkineb24f45592015-08-07 02:57:25201 // Applies a delta-compressed |patch| to |existing_data|, producing the result
202 // in |output|. Returns whether the operation was successful.
203 static bool ApplyDeltaPatch(const std::string& existing_data,
204 const std::string& patch,
isherman5f556b52017-06-14 16:27:23205 std::string* output) WARN_UNUSED_RESULT;
asvitkineb24f45592015-08-07 02:57:25206
[email protected]1df24d0a2014-01-20 21:29:59207 // The pref service used to persist the variations seed.
208 PrefService* local_state_;
209
210 // Cached serial number from the most recently fetched variations seed.
Ilya Shermanc70363ec2018-01-17 05:51:57211 std::string latest_serial_number_;
[email protected]1df24d0a2014-01-20 21:29:59212
Paul Miller33a495e2018-09-29 04:35:02213 base::OnceCallback<void()> on_initial_seed_stored_;
214
[email protected]1df24d0a2014-01-20 21:29:59215 DISALLOW_COPY_AND_ASSIGN(VariationsSeedStore);
216};
217
blundell57bcfed2015-09-04 08:44:45218} // namespace variations
[email protected]1df24d0a2014-01-20 21:29:59219
blundell0b2305c2015-08-25 15:54:42220#endif // COMPONENTS_VARIATIONS_VARIATIONS_SEED_STORE_H_