OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/variations/variations_seed_processor.h" | 5 #include "components/variations/variations_seed_processor.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/metrics/field_trial.h" | 12 #include "base/metrics/field_trial.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/version.h" | 14 #include "base/version.h" |
| 15 #include "components/variations/processed_study.h" |
15 #include "components/variations/variations_associated_data.h" | 16 #include "components/variations/variations_associated_data.h" |
16 | 17 |
17 namespace chrome_variations { | 18 namespace chrome_variations { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 Study_Platform GetCurrentPlatform() { | 22 Study_Platform GetCurrentPlatform() { |
22 #if defined(OS_WIN) | 23 #if defined(OS_WIN) |
23 return Study_Platform_PLATFORM_WINDOWS; | 24 return Study_Platform_PLATFORM_WINDOWS; |
24 #elif defined(OS_IOS) | 25 #elif defined(OS_IOS) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 63 |
63 VariationsSeedProcessor::~VariationsSeedProcessor() { | 64 VariationsSeedProcessor::~VariationsSeedProcessor() { |
64 } | 65 } |
65 | 66 |
66 void VariationsSeedProcessor::CreateTrialsFromSeed( | 67 void VariationsSeedProcessor::CreateTrialsFromSeed( |
67 const VariationsSeed& seed, | 68 const VariationsSeed& seed, |
68 const std::string& locale, | 69 const std::string& locale, |
69 const base::Time& reference_date, | 70 const base::Time& reference_date, |
70 const base::Version& version, | 71 const base::Version& version, |
71 Study_Channel channel) { | 72 Study_Channel channel) { |
| 73 std::vector<ProcessedStudy> filtered_studies; |
| 74 FilterAndValidateStudies(seed, locale, reference_date, version, channel, |
| 75 &filtered_studies); |
| 76 |
| 77 for (size_t i = 0; i < filtered_studies.size(); ++i) |
| 78 CreateTrialFromStudy(filtered_studies[i]); |
| 79 } |
| 80 |
| 81 void VariationsSeedProcessor::FilterAndValidateStudies( |
| 82 const VariationsSeed& seed, |
| 83 const std::string& locale, |
| 84 const base::Time& reference_date, |
| 85 const base::Version& version, |
| 86 Study_Channel channel, |
| 87 std::vector<ProcessedStudy>* filtered_studies) { |
72 DCHECK(version.IsValid()); | 88 DCHECK(version.IsValid()); |
73 | 89 |
74 // Add expired studies (in a disabled state) only after all the non-expired | 90 // Add expired studies (in a disabled state) only after all the non-expired |
75 // studies have been added (and do not add an expired study if a corresponding | 91 // studies have been added (and do not add an expired study if a corresponding |
76 // non-expired study got added). This way, if there's both an expired and a | 92 // non-expired study got added). This way, if there's both an expired and a |
77 // non-expired study that applies, the non-expired study takes priority. | 93 // non-expired study that applies, the non-expired study takes priority. |
78 std::set<std::string> created_studies; | 94 std::set<std::string> created_studies; |
79 std::vector<const Study*> expired_studies; | 95 std::vector<const Study*> expired_studies; |
80 | 96 |
81 for (int i = 0; i < seed.study_size(); ++i) { | 97 for (int i = 0; i < seed.study_size(); ++i) { |
82 const Study& study = seed.study(i); | 98 const Study& study = seed.study(i); |
83 if (!ShouldAddStudy(study, locale, reference_date, version, channel)) | 99 if (!ShouldAddStudy(study, locale, reference_date, version, channel)) |
84 continue; | 100 continue; |
85 | 101 |
86 if (IsStudyExpired(study, reference_date)) { | 102 if (IsStudyExpired(study, reference_date)) { |
87 expired_studies.push_back(&study); | 103 expired_studies.push_back(&study); |
88 } else { | 104 } else if (!ContainsKey(created_studies, study.name())) { |
89 CreateTrialFromStudy(study, false); | 105 ValidateAndAddStudy(study, false, filtered_studies); |
90 created_studies.insert(study.name()); | 106 created_studies.insert(study.name()); |
91 } | 107 } |
92 } | 108 } |
93 | 109 |
94 for (size_t i = 0; i < expired_studies.size(); ++i) { | 110 for (size_t i = 0; i < expired_studies.size(); ++i) { |
95 if (!ContainsKey(created_studies, expired_studies[i]->name())) | 111 if (!ContainsKey(created_studies, expired_studies[i]->name())) |
96 CreateTrialFromStudy(*expired_studies[i], true); | 112 ValidateAndAddStudy(*expired_studies[i], true, filtered_studies); |
97 } | 113 } |
98 } | 114 } |
99 | 115 |
| 116 void VariationsSeedProcessor::ValidateAndAddStudy( |
| 117 const Study& study, |
| 118 bool is_expired, |
| 119 std::vector<ProcessedStudy>* filtered_studies) { |
| 120 base::FieldTrial::Probability total_probability = 0; |
| 121 if (!ValidateStudyAndComputeTotalProbability(study, &total_probability)) |
| 122 return; |
| 123 filtered_studies->push_back(ProcessedStudy(&study, total_probability, |
| 124 is_expired)); |
| 125 } |
| 126 |
100 bool VariationsSeedProcessor::CheckStudyChannel(const Study_Filter& filter, | 127 bool VariationsSeedProcessor::CheckStudyChannel(const Study_Filter& filter, |
101 Study_Channel channel) { | 128 Study_Channel channel) { |
102 // An empty channel list matches all channels. | 129 // An empty channel list matches all channels. |
103 if (filter.channel_size() == 0) | 130 if (filter.channel_size() == 0) |
104 return true; | 131 return true; |
105 | 132 |
106 for (int i = 0; i < filter.channel_size(); ++i) { | 133 for (int i = 0; i < filter.channel_size(); ++i) { |
107 if (filter.channel(i) == channel) | 134 if (filter.channel(i) == channel) |
108 return true; | 135 return true; |
109 } | 136 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 } | 186 } |
160 | 187 |
161 if (filter.has_max_version()) { | 188 if (filter.has_max_version()) { |
162 if (version.CompareToWildcardString(filter.max_version()) > 0) | 189 if (version.CompareToWildcardString(filter.max_version()) > 0) |
163 return false; | 190 return false; |
164 } | 191 } |
165 | 192 |
166 return true; | 193 return true; |
167 } | 194 } |
168 | 195 |
169 void VariationsSeedProcessor::CreateTrialFromStudy(const Study& study, | 196 void VariationsSeedProcessor::CreateTrialFromStudy( |
170 bool is_expired) { | 197 const ProcessedStudy& processed_study) { |
171 base::FieldTrial::Probability total_probability = 0; | 198 const Study& study = *processed_study.study; |
172 if (!ValidateStudyAndComputeTotalProbability(study, &total_probability)) | |
173 return; | |
174 | 199 |
175 // Check if any experiments need to be forced due to a command line | 200 // Check if any experiments need to be forced due to a command line |
176 // flag. Force the first experiment with an existing flag. | 201 // flag. Force the first experiment with an existing flag. |
177 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 202 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
178 for (int i = 0; i < study.experiment_size(); ++i) { | 203 for (int i = 0; i < study.experiment_size(); ++i) { |
179 const Study_Experiment& experiment = study.experiment(i); | 204 const Study_Experiment& experiment = study.experiment(i); |
180 if (experiment.has_forcing_flag() && | 205 if (experiment.has_forcing_flag() && |
181 command_line->HasSwitch(experiment.forcing_flag())) { | 206 command_line->HasSwitch(experiment.forcing_flag())) { |
182 base::FieldTrialList::CreateFieldTrial(study.name(), experiment.name()); | 207 base::FieldTrialList::CreateFieldTrial(study.name(), experiment.name()); |
183 RegisterExperimentParams(study, experiment); | 208 RegisterExperimentParams(study, experiment); |
(...skipping 11 matching lines...) Expand all Loading... |
195 randomization_type = base::FieldTrial::ONE_TIME_RANDOMIZED; | 220 randomization_type = base::FieldTrial::ONE_TIME_RANDOMIZED; |
196 if (study.has_randomization_seed()) | 221 if (study.has_randomization_seed()) |
197 randomization_seed = study.randomization_seed(); | 222 randomization_seed = study.randomization_seed(); |
198 } | 223 } |
199 | 224 |
200 // The trial is created without specifying an expiration date because the | 225 // The trial is created without specifying an expiration date because the |
201 // expiration check in field_trial.cc is based on the build date. Instead, | 226 // expiration check in field_trial.cc is based on the build date. Instead, |
202 // the expiration check using |reference_date| is done explicitly below. | 227 // the expiration check using |reference_date| is done explicitly below. |
203 scoped_refptr<base::FieldTrial> trial( | 228 scoped_refptr<base::FieldTrial> trial( |
204 base::FieldTrialList::FactoryGetFieldTrialWithRandomizationSeed( | 229 base::FieldTrialList::FactoryGetFieldTrialWithRandomizationSeed( |
205 study.name(), total_probability, study.default_experiment_name(), | 230 study.name(), processed_study.total_probability, |
| 231 study.default_experiment_name(), |
206 base::FieldTrialList::kNoExpirationYear, 1, 1, randomization_type, | 232 base::FieldTrialList::kNoExpirationYear, 1, 1, randomization_type, |
207 randomization_seed, NULL)); | 233 randomization_seed, NULL)); |
208 | 234 |
209 for (int i = 0; i < study.experiment_size(); ++i) { | 235 for (int i = 0; i < study.experiment_size(); ++i) { |
210 const Study_Experiment& experiment = study.experiment(i); | 236 const Study_Experiment& experiment = study.experiment(i); |
211 RegisterExperimentParams(study, experiment); | 237 RegisterExperimentParams(study, experiment); |
212 | 238 |
213 // Groups with flags can't be selected randomly, so we don't add them to | 239 // Groups with flags can't be selected randomly, so we don't add them to |
214 // the field trial. | 240 // the field trial. |
215 if (experiment.has_forcing_flag()) | 241 if (experiment.has_forcing_flag()) |
(...skipping 14 matching lines...) Expand all Loading... |
230 const VariationID variation_id = | 256 const VariationID variation_id = |
231 static_cast<VariationID>(experiment.google_update_experiment_id()); | 257 static_cast<VariationID>(experiment.google_update_experiment_id()); |
232 AssociateGoogleVariationIDForce(GOOGLE_UPDATE_SERVICE, | 258 AssociateGoogleVariationIDForce(GOOGLE_UPDATE_SERVICE, |
233 study.name(), | 259 study.name(), |
234 experiment.name(), | 260 experiment.name(), |
235 variation_id); | 261 variation_id); |
236 } | 262 } |
237 } | 263 } |
238 | 264 |
239 trial->SetForced(); | 265 trial->SetForced(); |
240 if (is_expired) | 266 if (processed_study.is_expired) |
241 trial->Disable(); | 267 trial->Disable(); |
242 else if (study.activation_type() == Study_ActivationType_ACTIVATION_AUTO) | 268 else if (study.activation_type() == Study_ActivationType_ACTIVATION_AUTO) |
243 trial->group(); | 269 trial->group(); |
244 } | 270 } |
245 | 271 |
246 bool VariationsSeedProcessor::IsStudyExpired(const Study& study, | 272 bool VariationsSeedProcessor::IsStudyExpired(const Study& study, |
247 const base::Time& date_time) { | 273 const base::Time& date_time) { |
248 if (study.has_expiry_date()) { | 274 if (study.has_expiry_date()) { |
249 const base::Time expiry_date = | 275 const base::Time expiry_date = |
250 ConvertStudyDateToBaseTime(study.expiry_date()); | 276 ConvertStudyDateToBaseTime(study.expiry_date()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 // The default group was not found in the list of groups. This study is not | 367 // The default group was not found in the list of groups. This study is not |
342 // valid. | 368 // valid. |
343 return false; | 369 return false; |
344 } | 370 } |
345 | 371 |
346 *total_probability = divisor; | 372 *total_probability = divisor; |
347 return true; | 373 return true; |
348 } | 374 } |
349 | 375 |
350 } // namespace chrome_variations | 376 } // namespace chrome_variations |
OLD | NEW |