1 // Copyright 2013 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.
5 #include "components/variations/variations_associated_data.h"
11 #include "base/memory/singleton.h"
12 #include "components/variations/metrics_util.h"
14 namespace chrome_variations
{
18 // The internal singleton accessor for the map, used to keep it thread-safe.
19 class GroupMapAccessor
{
21 typedef std::map
<ActiveGroupId
, VariationID
, ActiveGroupIdCompare
>
24 // Retrieve the singleton.
25 static GroupMapAccessor
* GetInstance() {
26 return Singleton
<GroupMapAccessor
>::get();
29 // Note that this normally only sets the ID for a group the first time, unless
30 // |force| is set to true, in which case it will always override it.
31 void AssociateID(IDCollectionKey key
,
32 const ActiveGroupId
& group_identifier
,
36 // Validate that all collections with this |group_identifier| have the same
38 DCHECK_EQ(2, ID_COLLECTION_COUNT
);
39 IDCollectionKey other_key
= GOOGLE_WEB_PROPERTIES
;
40 if (key
== GOOGLE_WEB_PROPERTIES
)
41 other_key
= GOOGLE_UPDATE_SERVICE
;
42 VariationID other_id
= GetID(other_key
, group_identifier
);
43 DCHECK(other_id
== EMPTY_ID
|| other_id
== id
);
46 base::AutoLock
scoped_lock(lock_
);
48 GroupToIDMap
* group_to_id_map
= GetGroupToIDMap(key
);
50 group_to_id_map
->find(group_identifier
) == group_to_id_map
->end())
51 (*group_to_id_map
)[group_identifier
] = id
;
54 VariationID
GetID(IDCollectionKey key
,
55 const ActiveGroupId
& group_identifier
) {
56 base::AutoLock
scoped_lock(lock_
);
57 GroupToIDMap
* group_to_id_map
= GetGroupToIDMap(key
);
58 GroupToIDMap::const_iterator it
= group_to_id_map
->find(group_identifier
);
59 if (it
== group_to_id_map
->end())
64 void ClearAllMapsForTesting() {
65 base::AutoLock
scoped_lock(lock_
);
67 for (int i
= 0; i
< ID_COLLECTION_COUNT
; ++i
) {
68 GroupToIDMap
* map
= GetGroupToIDMap(static_cast<IDCollectionKey
>(i
));
75 friend struct DefaultSingletonTraits
<GroupMapAccessor
>;
77 // Retrieves the GroupToIDMap for |key|.
78 GroupToIDMap
* GetGroupToIDMap(IDCollectionKey key
) {
79 return &group_to_id_maps_
[key
];
83 group_to_id_maps_
.resize(ID_COLLECTION_COUNT
);
85 ~GroupMapAccessor() {}
88 std::vector
<GroupToIDMap
> group_to_id_maps_
;
90 DISALLOW_COPY_AND_ASSIGN(GroupMapAccessor
);
93 // Singleton helper class that keeps track of the parameters of all variations
94 // and ensures access to these is thread-safe.
95 class VariationsParamAssociator
{
97 typedef std::pair
<std::string
, std::string
> VariationKey
;
98 typedef std::map
<std::string
, std::string
> VariationParams
;
100 // Retrieve the singleton.
101 static VariationsParamAssociator
* GetInstance() {
102 return Singleton
<VariationsParamAssociator
>::get();
105 bool AssociateVariationParams(const std::string
& trial_name
,
106 const std::string
& group_name
,
107 const VariationParams
& params
) {
108 base::AutoLock
scoped_lock(lock_
);
110 if (IsFieldTrialActive(trial_name
))
113 const VariationKey
key(trial_name
, group_name
);
114 if (ContainsKey(variation_params_
, key
))
117 variation_params_
[key
] = params
;
121 bool GetVariationParams(const std::string
& trial_name
,
122 VariationParams
* params
) {
123 base::AutoLock
scoped_lock(lock_
);
125 const std::string group_name
=
126 base::FieldTrialList::FindFullName(trial_name
);
127 const VariationKey
key(trial_name
, group_name
);
128 if (!ContainsKey(variation_params_
, key
))
131 *params
= variation_params_
[key
];
135 void ClearAllParamsForTesting() {
136 base::AutoLock
scoped_lock(lock_
);
137 variation_params_
.clear();
141 friend struct DefaultSingletonTraits
<VariationsParamAssociator
>;
143 VariationsParamAssociator() {}
144 ~VariationsParamAssociator() {}
146 // Tests whether a field trial is active (i.e. group() has been called on it).
147 // TODO(asvitkine): Expose this as an API on base::FieldTrial.
148 bool IsFieldTrialActive(const std::string
& trial_name
) {
149 base::FieldTrial::ActiveGroups active_groups
;
150 base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups
);
151 for (size_t i
= 0; i
< active_groups
.size(); ++i
) {
152 if (active_groups
[i
].trial_name
== trial_name
)
159 std::map
<VariationKey
, VariationParams
> variation_params_
;
161 DISALLOW_COPY_AND_ASSIGN(VariationsParamAssociator
);
166 ActiveGroupId
MakeActiveGroupId(const std::string
& trial_name
,
167 const std::string
& group_name
) {
169 id
.name
= metrics::HashName(trial_name
);
170 id
.group
= metrics::HashName(group_name
);
174 void AssociateGoogleVariationID(IDCollectionKey key
,
175 const std::string
& trial_name
,
176 const std::string
& group_name
,
178 GroupMapAccessor::GetInstance()->AssociateID(
179 key
, MakeActiveGroupId(trial_name
, group_name
), id
, false);
182 void AssociateGoogleVariationIDForce(IDCollectionKey key
,
183 const std::string
& trial_name
,
184 const std::string
& group_name
,
186 GroupMapAccessor::GetInstance()->AssociateID(
187 key
, MakeActiveGroupId(trial_name
, group_name
), id
, true);
190 VariationID
GetGoogleVariationID(IDCollectionKey key
,
191 const std::string
& trial_name
,
192 const std::string
& group_name
) {
193 return GroupMapAccessor::GetInstance()->GetID(
194 key
, MakeActiveGroupId(trial_name
, group_name
));
197 bool AssociateVariationParams(
198 const std::string
& trial_name
,
199 const std::string
& group_name
,
200 const std::map
<std::string
, std::string
>& params
) {
201 return VariationsParamAssociator::GetInstance()->AssociateVariationParams(
202 trial_name
, group_name
, params
);
205 bool GetVariationParams(const std::string
& trial_name
,
206 std::map
<std::string
, std::string
>* params
) {
207 return VariationsParamAssociator::GetInstance()->GetVariationParams(
211 std::string
GetVariationParamValue(const std::string
& trial_name
,
212 const std::string
& param_name
) {
213 std::map
<std::string
, std::string
> params
;
214 if (GetVariationParams(trial_name
, ¶ms
)) {
215 std::map
<std::string
, std::string
>::iterator it
= params
.find(param_name
);
216 if (it
!= params
.end())
219 return std::string();
222 // Functions below are exposed for testing explicitly behind this namespace.
223 // They simply wrap existing functions in this file.
226 void ClearAllVariationIDs() {
227 GroupMapAccessor::GetInstance()->ClearAllMapsForTesting();
230 void ClearAllVariationParams() {
231 VariationsParamAssociator::GetInstance()->ClearAllParamsForTesting();
234 } // namespace testing
236 } // namespace chrome_variations