summaryrefslogtreecommitdiff
path: root/chromium/components/variations/synthetic_trial_registry.h
blob: 10caa0cb31831deb5592ac5c0081fe45cfd42f03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_VARIATIONS_SYNTHETIC_TRIAL_REGISTRY_H_
#define COMPONENTS_VARIATIONS_SYNTHETIC_TRIAL_REGISTRY_H_

#include <vector>

#include "base/feature_list.h"
#include "base/observer_list.h"
#include "components/variations/synthetic_trials.h"

namespace metrics {
class MetricsServiceAccessor;
}  // namespace metrics

namespace variations {

struct ActiveGroupId;
class FieldTrialsProvider;
class FieldTrialsProviderTest;
class SyntheticTrialRegistryTest;

namespace internal {
extern const base::Feature kExternalExperimentAllowlist;
}  // namespace internal

class SyntheticTrialRegistry {
 public:
  // Constructor that specifies whether the SyntheticTrialRegistry should use
  // an allowlist for external experiments. Some embedders such as WebLayer
  // do not run as Chrome and do not use the allowlist.
  // Note: The allowlist is enabled only if |kExternalExperimentAllowlist| is
  // also enabled, even if the parameter value is true. The default constructor
  // defaults to the feature state.
  explicit SyntheticTrialRegistry(bool enable_external_experiment_allowlist);

  SyntheticTrialRegistry();
  ~SyntheticTrialRegistry();

  // Adds an observer to be notified when the synthetic trials list changes.
  void AddSyntheticTrialObserver(SyntheticTrialObserver* observer);

  // Removes an existing observer of synthetic trials list changes.
  void RemoveSyntheticTrialObserver(SyntheticTrialObserver* observer);

  // Specifies the mode of RegisterExternalExperiments() operation.
  enum OverrideMode {
    // Previously-registered external experiment ids are overridden (replaced)
    // with the new list.
    kOverrideExistingIds,
    // Previously-registered external experiment ids are not overridden, but
    // new experiment ids may be added.
    kDoNotOverrideExistingIds,
  };

  // Registers a list of experiment ids coming from an external application.
  // The input ids are in the VariationID format.
  //
  // When |enable_external_experiment_allowlist| is true, the supplied ids must
  // have corresponding entries in the "ExternalExperimentAllowlist" (coming via
  // a feature param) to be applied. The allowlist also supplies the
  // corresponding trial name that should be used for reporting to UMA.
  //
  // When |enable_external_experiment_allowlist| is false, |fallback_study_name|
  // will be used as the trial name for all provided experiment ids.
  //
  // If |mode| is kOverrideExistingIds, this API clears previously-registered
  // external experiment ids, replacing them with the new list (which may be
  // empty). If |mode| is kDoNotOverrideExistingIds, any new ids that are not
  // already registered will be added, but existing ones will not be replaced.
  void RegisterExternalExperiments(const std::string& fallback_study_name,
                                   const std::vector<int>& experiment_ids,
                                   OverrideMode mode);

 private:
  friend metrics::MetricsServiceAccessor;
  friend FieldTrialsProvider;
  friend FieldTrialsProviderTest;
  friend SyntheticTrialRegistryTest;
  FRIEND_TEST_ALL_PREFIXES(SyntheticTrialRegistryTest, RegisterSyntheticTrial);
  FRIEND_TEST_ALL_PREFIXES(SyntheticTrialRegistryTest,
                           GetSyntheticFieldTrialActiveGroups);
  FRIEND_TEST_ALL_PREFIXES(VariationsCrashKeysTest, BasicFunctionality);

  // Registers a field trial name and group to be used to annotate a UMA report
  // with a particular Chrome configuration state. A UMA report will be
  // annotated with this trial group if and only if all events in the report
  // were created after the trial is registered. Only one group name may be
  // registered at a time for a given trial_name. Only the last group name that
  // is registered for a given trial name will be recorded. The values passed
  // in must not correspond to any real field trial in the code.
  // Note: Should not be used to replace trials that were registered with
  // RegisterExternalExperiments().
  void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group);

  // Returns the study name corresponding to |experiment_id| from the allowlist
  // contained in |params| if the allowlist is enabled, otherwise returns
  // |fallback_study_name|. An empty string piece is returned when the
  // experiment is not in the allowlist.
  base::StringPiece GetStudyNameForExpId(const std::string& fallback_study_name,
                                         const base::FieldTrialParams& params,
                                         const std::string& experiment_id);

  // Returns a list of synthetic field trials that are older than |time|.
  void GetSyntheticFieldTrialsOlderThan(
      base::TimeTicks time,
      std::vector<ActiveGroupId>* synthetic_trials) const;

  // Notifies observers on a synthetic trial list change.
  void NotifySyntheticTrialObservers();

  // Whether the allowlist is enabled. Some configurations, like WebLayer
  // do not use the allowlist.
  bool enable_external_experiment_allowlist_ = true;

  // Field trial groups that map to Chrome configuration states.
  std::vector<SyntheticTrialGroup> synthetic_trial_groups_;

  // List of observers of |synthetic_trial_groups_| changes.
  base::ObserverList<SyntheticTrialObserver>::Unchecked
      synthetic_trial_observer_list_;
};

}  // namespace variations

#endif  // COMPONENTS_VARIATIONS_SYNTHETIC_TRIAL_REGISTRY_H_