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