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 
5 #include "components/variations/active_field_trials.h"
6 
7 #include <stddef.h>
8 
9 #include <vector>
10 
11 #include "base/lazy_instance.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "components/variations/hashing.h"
15 #include "components/variations/synthetic_trials_active_group_id_provider.h"
16 
17 namespace variations {
18 
19 namespace {
20 
21 base::LazyInstance<std::string>::Leaky g_seed_version;
22 
23 // Populates |name_group_ids| based on |active_groups|. Field trial names are
24 // suffixed with |suffix| before hashing is executed.
GetFieldTrialActiveGroupIdsForActiveGroups(base::StringPiece suffix,const base::FieldTrial::ActiveGroups & active_groups,std::vector<ActiveGroupId> * name_group_ids)25 void GetFieldTrialActiveGroupIdsForActiveGroups(
26     base::StringPiece suffix,
27     const base::FieldTrial::ActiveGroups& active_groups,
28     std::vector<ActiveGroupId>* name_group_ids) {
29   DCHECK(name_group_ids->empty());
30   for (auto it = active_groups.begin(); it != active_groups.end(); ++it) {
31     name_group_ids->push_back(
32         MakeActiveGroupId(it->trial_name + suffix.as_string(),
33                           it->group_name + suffix.as_string()));
34   }
35 }
36 
AppendActiveGroupIdsAsStrings(const std::vector<ActiveGroupId> name_group_ids,std::vector<std::string> * output)37 void AppendActiveGroupIdsAsStrings(
38     const std::vector<ActiveGroupId> name_group_ids,
39     std::vector<std::string>* output) {
40   for (const auto& active_group_id : name_group_ids) {
41     output->push_back(base::StringPrintf("%x-%x", active_group_id.name,
42                                          active_group_id.group));
43   }
44 }
45 
46 }  // namespace
47 
MakeActiveGroupId(base::StringPiece trial_name,base::StringPiece group_name)48 ActiveGroupId MakeActiveGroupId(base::StringPiece trial_name,
49                                 base::StringPiece group_name) {
50   ActiveGroupId id;
51   id.name = HashName(trial_name);
52   id.group = HashName(group_name);
53   return id;
54 }
55 
GetFieldTrialActiveGroupIds(base::StringPiece suffix,std::vector<ActiveGroupId> * name_group_ids)56 void GetFieldTrialActiveGroupIds(base::StringPiece suffix,
57                                  std::vector<ActiveGroupId>* name_group_ids) {
58   DCHECK(name_group_ids->empty());
59   // A note on thread safety: Since GetActiveFieldTrialGroups() is thread
60   // safe, and we operate on a separate list of that data, this function is
61   // technically thread safe as well, with respect to the FieldTrialList data.
62   base::FieldTrial::ActiveGroups active_groups;
63   base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
64   GetFieldTrialActiveGroupIdsForActiveGroups(suffix, active_groups,
65                                              name_group_ids);
66 }
67 
GetFieldTrialActiveGroupIdsAsStrings(base::StringPiece suffix,std::vector<std::string> * output)68 void GetFieldTrialActiveGroupIdsAsStrings(base::StringPiece suffix,
69                                           std::vector<std::string>* output) {
70   DCHECK(output->empty());
71   std::vector<ActiveGroupId> name_group_ids;
72   GetFieldTrialActiveGroupIds(suffix, &name_group_ids);
73   AppendActiveGroupIdsAsStrings(name_group_ids, output);
74 }
75 
GetSyntheticTrialGroupIdsAsString(std::vector<std::string> * output)76 void GetSyntheticTrialGroupIdsAsString(std::vector<std::string>* output) {
77   std::vector<ActiveGroupId> name_group_ids;
78   SyntheticTrialsActiveGroupIdProvider::GetInstance()->GetActiveGroupIds(
79       &name_group_ids);
80   AppendActiveGroupIdsAsStrings(name_group_ids, output);
81 }
82 
SetSeedVersion(const std::string & seed_version)83 void SetSeedVersion(const std::string& seed_version) {
84   g_seed_version.Get() = seed_version;
85 }
86 
GetSeedVersion()87 const std::string& GetSeedVersion() {
88   return g_seed_version.Get();
89 }
90 
91 namespace testing {
92 
TestGetFieldTrialActiveGroupIds(base::StringPiece suffix,const base::FieldTrial::ActiveGroups & active_groups,std::vector<ActiveGroupId> * name_group_ids)93 void TestGetFieldTrialActiveGroupIds(
94     base::StringPiece suffix,
95     const base::FieldTrial::ActiveGroups& active_groups,
96     std::vector<ActiveGroupId>* name_group_ids) {
97   GetFieldTrialActiveGroupIdsForActiveGroups(suffix, active_groups,
98                                              name_group_ids);
99 }
100 
101 }  // namespace testing
102 
103 }  // namespace variations
104