variations_field_trial_creator.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright 2017 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_SERVICE_VARIATIONS_FIELD_TRIAL_CREATOR_H_
  5. #define COMPONENTS_VARIATIONS_SERVICE_VARIATIONS_FIELD_TRIAL_CREATOR_H_
  6. #include <memory>
  7. #include <string>
  8. #include <unordered_map>
  9. #include <vector>
  10. #include "base/compiler_specific.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/metrics/field_trial.h"
  13. #include "base/time/time.h"
  14. #include "build/build_config.h"
  15. #include "components/variations/client_filterable_state.h"
  16. #include "components/variations/metrics.h"
  17. #include "components/variations/proto/study.pb.h"
  18. #include "components/variations/seed_response.h"
  19. #include "components/variations/service/buildflags.h"
  20. #include "components/variations/service/ui_string_overrider.h"
  21. #include "components/variations/variations_seed_store.h"
  22. namespace metrics {
  23. class MetricsStateManager;
  24. }
  25. namespace variations {
  26. // Denotes whether Chrome used a variations seed. Also captures (a) the kind of
  27. // seed and (b) the conditions under which the seed was used or failed to be
  28. // used. Exposed for testing.
  29. //
  30. // These values are persisted to logs. Entries should not be renumbered and
  31. // numeric values should never be reused.
  32. enum class SeedUsage {
  33. kRegularSeedUsed = 0,
  34. kExpiredRegularSeedNotUsed = 1,
  35. kUnloadableRegularSeedNotUsed = 2,
  36. kSafeSeedUsed = 3,
  37. kExpiredSafeSeedNotUsed = 4,
  38. // The below three enumerators were deprecated in M100.
  39. // kCorruptedSafeSeedNotUsed = 5,
  40. // kRegularSeedUsedAfterEmptySafeSeedLoaded = 6,
  41. // kExpiredRegularSeedNotUsedAfterEmptySafeSeedLoaded = 7,
  42. // kCorruptedRegularSeedNotUsedAfterEmptySafeSeedLoaded = 8,
  43. kRegularSeedForFutureMilestoneNotUsed = 9,
  44. kSafeSeedForFutureMilestoneNotUsed = 10,
  45. kUnloadableSafeSeedNotUsed = 11,
  46. kMaxValue = kUnloadableSafeSeedNotUsed,
  47. };
  48. // Denotes a variations seed's expiry state. Exposed for testing.
  49. //
  50. // These values are persisted to logs. Entries should not be renumbered and
  51. // numeric values should never be reused.
  52. enum class VariationsSeedExpiry {
  53. kNotExpired = 0,
  54. kFetchTimeMissing = 1,
  55. kExpired = 2,
  56. kMaxValue = kExpired,
  57. };
  58. enum LoadPermanentConsistencyCountryResult {
  59. LOAD_COUNTRY_NO_PREF_NO_SEED = 0,
  60. LOAD_COUNTRY_NO_PREF_HAS_SEED,
  61. LOAD_COUNTRY_INVALID_PREF_NO_SEED,
  62. LOAD_COUNTRY_INVALID_PREF_HAS_SEED,
  63. LOAD_COUNTRY_HAS_PREF_NO_SEED_VERSION_EQ,
  64. LOAD_COUNTRY_HAS_PREF_NO_SEED_VERSION_NEQ,
  65. LOAD_COUNTRY_HAS_BOTH_VERSION_EQ_COUNTRY_EQ,
  66. LOAD_COUNTRY_HAS_BOTH_VERSION_EQ_COUNTRY_NEQ,
  67. LOAD_COUNTRY_HAS_BOTH_VERSION_NEQ_COUNTRY_EQ,
  68. LOAD_COUNTRY_HAS_BOTH_VERSION_NEQ_COUNTRY_NEQ,
  69. LOAD_COUNTRY_HAS_PERMANENT_OVERRIDDEN_COUNTRY,
  70. LOAD_COUNTRY_MAX,
  71. };
  72. class PlatformFieldTrials;
  73. class SafeSeedManager;
  74. class VariationsServiceClient;
  75. // Used to set up field trials based on stored variations seed data.
  76. class VariationsFieldTrialCreator {
  77. public:
  78. // Caller is responsible for ensuring that objects passed to the constructor
  79. // stay valid for the lifetime of this object.
  80. VariationsFieldTrialCreator(VariationsServiceClient* client,
  81. std::unique_ptr<VariationsSeedStore> seed_store,
  82. const UIStringOverrider& ui_string_overrider);
  83. VariationsFieldTrialCreator(const VariationsFieldTrialCreator&) = delete;
  84. VariationsFieldTrialCreator& operator=(const VariationsFieldTrialCreator&) =
  85. delete;
  86. virtual ~VariationsFieldTrialCreator();
  87. // Returns what variations will consider to be the latest country. Returns
  88. // empty if it is not available.
  89. std::string GetLatestCountry() const;
  90. VariationsSeedStore* seed_store() { return seed_store_.get(); }
  91. // Sets up field trials based on stored variations seed data. Returns whether
  92. // setup completed successfully.
  93. //
  94. // |variation_ids| allows for forcing ids selected in chrome://flags.
  95. // |command_line_variation_ids| allows for forcing ids through the
  96. // "--force-variation-ids" command line flag. It should be a comma-separated
  97. // list of variation ids. Ids prefixed with the character "t" will be treated
  98. // as Trigger Variation Ids.
  99. // |extra_overrides| gives a list of feature overrides that should be applied
  100. // after the features explicitly disabled/enabled from the command line via
  101. // --disable-features and --enable-features, but before field trials.
  102. // |low_entropy_provider| allows for field trial randomization. May be null.
  103. // |feature_list| contains the list of all active features for this client.
  104. // Must not be null.
  105. // |metrics_state_manager| facilitates signaling that Chrome has not yet
  106. // exited cleanly. Must not be null.
  107. // |platform_field_trials| provides the platform-specific field trial setup
  108. // for Chrome. Must not be null.
  109. // |safe_seed_manager| should be notified of the combined server and client
  110. // state that was activated to create the field trials (only when the return
  111. // value is true). Must not be null.
  112. // |low_entropy_source_value| contains the low entropy source value that was
  113. // used for client-side randomization of variations.
  114. //
  115. // NOTE: The ordering of the FeatureList method calls is such that the
  116. // explicit --disable-features and --enable-features from the command line
  117. // take precedence over |extra_overrides|, which takes precedence over the
  118. // field trials.
  119. bool SetUpFieldTrials(
  120. const std::vector<std::string>& variation_ids,
  121. const std::string& command_line_variation_ids,
  122. const std::vector<base::FeatureList::FeatureOverrideInfo>&
  123. extra_overrides,
  124. std::unique_ptr<const base::FieldTrial::EntropyProvider>
  125. low_entropy_provider,
  126. std::unique_ptr<base::FeatureList> feature_list,
  127. metrics::MetricsStateManager* metrics_state_manager,
  128. PlatformFieldTrials* platform_field_trials,
  129. SafeSeedManager* safe_seed_manager,
  130. absl::optional<int> low_entropy_source_value);
  131. // Returns all of the client state used for filtering studies.
  132. // As a side-effect, may update the stored permanent consistency country.
  133. std::unique_ptr<ClientFilterableState> GetClientFilterableStateForVersion(
  134. const base::Version& version);
  135. // Loads the country code to use for filtering permanent consistency studies,
  136. // updating the stored country code if the stored value was for a different
  137. // Chrome version. The country used for permanent consistency studies is kept
  138. // consistent between Chrome upgrades in order to avoid annoying the user due
  139. // to experiment churn while traveling.
  140. std::string LoadPermanentConsistencyCountry(
  141. const base::Version& version,
  142. const std::string& latest_country);
  143. // Sets the stored permanent country pref for this client.
  144. void StorePermanentCountry(const base::Version& version,
  145. const std::string& country);
  146. // Sets the stored permanent variations overridden country pref for this
  147. // client.
  148. void StoreVariationsOverriddenCountry(const std::string& country);
  149. // Allow the platform that is used to filter the set of active trials to be
  150. // overridden.
  151. void OverrideVariationsPlatform(Study::Platform platform_override);
  152. // Overrides cached UI strings on the resource bundle once it is initialized.
  153. void OverrideCachedUIStrings();
  154. // Returns whether the map of the cached UI strings to override is empty.
  155. bool IsOverrideResourceMapEmpty();
  156. // Returns the locale that was used for evaluating trials.
  157. const std::string& application_locale() const { return application_locale_; }
  158. protected:
  159. // Get the platform we're running on, respecting OverrideVariationsPlatform().
  160. // Protected for testing.
  161. Study::Platform GetPlatform();
  162. // Overrides the string resource specified by |hash| with |str| in the
  163. // resource bundle. Protected for testing.
  164. void OverrideUIString(uint32_t hash, const std::u16string& str);
  165. // Get the client's current form factor. Protected for testing.
  166. Study::FormFactor GetCurrentFormFactor();
  167. #if BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
  168. // Applies the field trial testing config defined in
  169. // testing/variations/fieldtrial_testing_config.json to the current session.
  170. // Protected and virtual for testing.
  171. virtual void ApplyFieldTrialTestingConfig(base::FeatureList* feature_list);
  172. #endif // BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
  173. private:
  174. // Returns true if the loaded VariationsSeed has expired. An expired seed is
  175. // one that (a) was fetched over |kMaxVariationsSeedAgeDays| ago and (b) is
  176. // older than the binary build time.
  177. //
  178. // Also, records a couple VariationsSeed-related metrics.
  179. bool HasSeedExpired(bool is_safe_seed);
  180. // Returns true if the loaded VariationsSeed is for a future milestone (e.g.
  181. // if the client is on M92 and the seed was fetched with M93). A seed for a
  182. // future milestone is invalid as it may be missing studies filtered out by
  183. // the server.
  184. bool IsSeedForFutureMilestone(bool is_safe_seed);
  185. // Creates field trials based on the variations seed loaded from local state.
  186. // If there is a problem loading the seed data, all trials specified by the
  187. // seed may not be created. Some field trials are configured to override or
  188. // associate with (for reporting) specific features. These associations are
  189. // registered with |feature_list|. Returns true if trials were created
  190. // successfully; and if so, stores the loaded variations state into the
  191. // |safe_seed_manager|.
  192. bool CreateTrialsFromSeed(
  193. const base::FieldTrial::EntropyProvider* low_entropy_provider,
  194. base::FeatureList* feature_list,
  195. SafeSeedManager* safe_seed_manager);
  196. // Reads a seed's data and signature from the file at |seed_path| and writes
  197. // them to Local State. Exits Chrome (A) if the file's contents can't be
  198. // loaded or (B) if the contents do not contain |kVariationsCompressedSeed| or
  199. // |kVariationsSeedSignature|. Also forces Chrome to not run in variations
  200. // safe mode. Used for variations seed testing.
  201. void LoadSeedFromFile(const base::FilePath& seed_path);
  202. // Returns the seed store. Virtual for testing.
  203. virtual VariationsSeedStore* GetSeedStore();
  204. // Returns the time at which the binary was built. Virtual for testing.
  205. virtual base::Time GetBuildTime() const;
  206. PrefService* local_state() { return seed_store_->local_state(); }
  207. const PrefService* local_state() const { return seed_store_->local_state(); }
  208. raw_ptr<VariationsServiceClient> client_;
  209. UIStringOverrider ui_string_overrider_;
  210. std::unique_ptr<VariationsSeedStore> seed_store_;
  211. // Tracks whether |CreateTrialsFromSeed| has been called, to ensure that it is
  212. // called at most once.
  213. bool create_trials_from_seed_called_;
  214. // The application locale won't change after the startup, so we cache the
  215. // value the first time when GetApplicationLocale() is called in the
  216. // constructor.
  217. std::string application_locale_;
  218. // Indiciate if OverrideVariationsPlatform has been used to set
  219. // |platform_override_|.
  220. bool has_platform_override_;
  221. // Platform to be used for variations filtering, overridding the current
  222. // platform.
  223. Study::Platform platform_override_;
  224. // Caches the UI strings which need to be overridden in the resource bundle.
  225. // These strings are cached before the resource bundle is initialized.
  226. std::unordered_map<int, std::u16string> overridden_strings_map_;
  227. SEQUENCE_CHECKER(sequence_checker_);
  228. };
  229. // A testing feature that forces a crash during field trial creation
  230. // on developer and test builds.
  231. extern const base::Feature kForceFieldTrialSetupCrashForTesting;
  232. } // namespace variations
  233. #endif // COMPONENTS_VARIATIONS_SERVICE_VARIATIONS_FIELD_TRIAL_CREATOR_H_