Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: chrome/browser/metrics/variations_service.cc

Issue 10375043: Variations Service now creates field trials from variations seed. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Alexei's comments Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/metrics/variations_service.h" 5 #include "chrome/browser/metrics/variations_service.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/build_time.h" 8 #include "base/build_time.h"
9 #include "base/version.h" 9 #include "base/version.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/singleton.h" 11 #include "base/memory/singleton.h"
12 #include "base/metrics/field_trial.h"
12 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/metrics/proto/trials_seed.pb.h" 14 #include "chrome/browser/metrics/proto/trials_seed.pb.h"
14 #include "chrome/browser/prefs/pref_service.h" 15 #include "chrome/browser/prefs/pref_service.h"
15 #include "chrome/common/pref_names.h" 16 #include "chrome/common/pref_names.h"
16 #include "content/public/common/url_fetcher.h" 17 #include "content/public/common/url_fetcher.h"
17 #include "googleurl/src/gurl.h" 18 #include "googleurl/src/gurl.h"
18 #include "net/base/load_flags.h" 19 #include "net/base/load_flags.h"
19 #include "net/url_request/url_request_status.h" 20 #include "net/url_request/url_request_status.h"
20 21
21 namespace { 22 namespace {
(...skipping 21 matching lines...) Expand all
43 return chrome::VersionInfo::CHANNEL_UNKNOWN; 44 return chrome::VersionInfo::CHANNEL_UNKNOWN;
44 } 45 }
45 46
46 } // namespace 47 } // namespace
47 48
48 // Static 49 // Static
49 VariationsService* VariationsService::GetInstance() { 50 VariationsService* VariationsService::GetInstance() {
50 return Singleton<VariationsService>::get(); 51 return Singleton<VariationsService>::get();
51 } 52 }
52 53
53 void VariationsService::LoadVariationsSeed(PrefService* local_prefs) { 54 bool VariationsService::CreateTrialsFromSeed(PrefService* local_prefs) {
54 std::string base64_seed_data = local_prefs->GetString(prefs::kVariationsSeed); 55 chrome_variations::TrialsSeed seed;
55 std::string seed_data; 56 if (!LoadVariationsSeed(local_prefs, &seed))
57 return false;
56 58
57 // If the decode process fails, assume the pref value is corrupt, and clear 59 for (int i = 0; i < seed.study_size(); ++i)
58 // it. 60 CreateTrialFromStudy(seed.study(i));
59 if (!base::Base64Decode(base64_seed_data, &seed_data) || 61
60 !variations_seed_.ParseFromString(seed_data)) { 62 return true;
61 VLOG(1) << "Variations Seed data in local pref is corrupt, clearing the "
62 << "pref.";
63 local_prefs->ClearPref(prefs::kVariationsSeed);
64 }
65 } 63 }
66 64
67 void VariationsService::StartFetchingVariationsSeed() { 65 void VariationsService::StartFetchingVariationsSeed() {
68 pending_seed_request_.reset(content::URLFetcher::Create( 66 pending_seed_request_.reset(content::URLFetcher::Create(
69 GURL(kDefaultVariationsServer), content::URLFetcher::GET, this)); 67 GURL(kDefaultVariationsServer), content::URLFetcher::GET, this));
70 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 68 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
71 net::LOAD_DO_NOT_SAVE_COOKIES); 69 net::LOAD_DO_NOT_SAVE_COOKIES);
72 pending_seed_request_->SetRequestContext( 70 pending_seed_request_->SetRequestContext(
73 g_browser_process->system_request_context()); 71 g_browser_process->system_request_context());
72 // TODO(jwd): pull max retries into a contsant
74 pending_seed_request_->SetMaxRetries(5); 73 pending_seed_request_->SetMaxRetries(5);
75 pending_seed_request_->Start(); 74 pending_seed_request_->Start();
76 } 75 }
77 76
78 void VariationsService::OnURLFetchComplete(const content::URLFetcher* source) { 77 void VariationsService::OnURLFetchComplete(const content::URLFetcher* source) {
79 DCHECK_EQ(pending_seed_request_.get(), source); 78 DCHECK_EQ(pending_seed_request_.get(), source);
80 // When we're done handling the request, the fetcher will be deleted. 79 // When we're done handling the request, the fetcher will be deleted.
81 scoped_ptr<const content::URLFetcher> request( 80 scoped_ptr<const content::URLFetcher> request(
82 pending_seed_request_.release()); 81 pending_seed_request_.release());
83 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS || 82 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS ||
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 } 138 }
140 139
141 DVLOG(1) << "Kept study " << study.name() << "."; 140 DVLOG(1) << "Kept study " << study.name() << ".";
142 return true; 141 return true;
143 } 142 }
144 143
145 // static 144 // static
146 bool VariationsService::CheckStudyChannel( 145 bool VariationsService::CheckStudyChannel(
147 const chrome_variations::Study& study, 146 const chrome_variations::Study& study,
148 chrome::VersionInfo::Channel channel) { 147 chrome::VersionInfo::Channel channel) {
148 if (study.channel_size() == 0) {
149 // An empty channel list matches all channels.
150 return true;
151 }
152
149 for (int i = 0; i < study.channel_size(); ++i) { 153 for (int i = 0; i < study.channel_size(); ++i) {
150 if (ConvertStudyChannelToVersionChannel(study.channel(i)) == channel) 154 if (ConvertStudyChannelToVersionChannel(study.channel(i)) == channel)
151 return true; 155 return true;
152 } 156 }
153 return false; 157 return false;
154 } 158 }
155 159
156 // static 160 // static
157 bool VariationsService::CheckStudyVersion(const chrome_variations::Study& study, 161 bool VariationsService::CheckStudyVersion(const chrome_variations::Study& study,
158 const std::string& version_string) { 162 const std::string& version_string) {
(...skipping 22 matching lines...) Expand all
181 return true; 185 return true;
182 } 186 }
183 187
184 // static 188 // static
185 bool VariationsService::CheckStudyDate(const chrome_variations::Study& study, 189 bool VariationsService::CheckStudyDate(const chrome_variations::Study& study,
186 const base::Time& date_time) { 190 const base::Time& date_time) {
187 const base::Time epoch = base::Time::UnixEpoch(); 191 const base::Time epoch = base::Time::UnixEpoch();
188 192
189 if (study.has_start_date()) { 193 if (study.has_start_date()) {
190 const base::Time start_date = 194 const base::Time start_date =
191 epoch + base::TimeDelta::FromMilliseconds(study.start_date()); 195 epoch + base::TimeDelta::FromSeconds(study.start_date());
192 if (date_time < start_date) 196 if (date_time < start_date)
193 return false; 197 return false;
194 } 198 }
195 199
196 if (study.has_expiry_date()) { 200 if (study.has_expiry_date()) {
197 const base::Time expiry_date = 201 const base::Time expiry_date =
198 epoch + base::TimeDelta::FromMilliseconds(study.expiry_date()); 202 epoch + base::TimeDelta::FromSeconds(study.expiry_date());
199 if (date_time >= expiry_date) 203 if (date_time >= expiry_date)
200 return false; 204 return false;
201 } 205 }
202 206
203 return true; 207 return true;
204 } 208 }
209
210 bool VariationsService::LoadVariationsSeed(
211 PrefService* local_prefs,
212 chrome_variations::TrialsSeed* seed) {
213 std::string base64_seed_data = local_prefs->GetString(prefs::kVariationsSeed);
214 std::string seed_data;
215
216 // If the decode process fails, assume the pref value is corrupt, and clear
217 // it.
218 if (!base::Base64Decode(base64_seed_data, &seed_data) ||
219 !seed->ParseFromString(seed_data)) {
220 VLOG(1) << "Variations Seed data in local pref is corrupt, clearing the "
221 << "pref.";
222 local_prefs->ClearPref(prefs::kVariationsSeed);
223 return false;
224 }
225 return true;
226 }
227
228 void VariationsService::CreateTrialFromStudy(
229 const chrome_variations::Study& study) {
230 if (!ShouldAddStudy(study))
231 return;
232
233 // At the moment, a missing default_experiment_name makes the study invalid.
234 if (!study.has_default_experiment_name()) {
235 DVLOG(1) << study.name() << " has no default experiment defined.";
236 return;
237 }
238
239 const std::string& default_group_name = study.default_experiment_name();
240 base::FieldTrial::Probability divisor = 0;
241
242 bool found_default_group = false;
243 for (int i = 0; i < study.experiment_size(); ++i) {
244 divisor += study.experiment(i).probability_weight();
245 if (study.experiment(i).name() == default_group_name) {
246 found_default_group = true;
247 }
248 }
249 if (!found_default_group){
Alexei Svitkine (slow) 2012/05/08 03:40:13 Space before {.
jwd 2012/05/08 03:47:24 Aw man, I'm missing all of these... Done.
250 DVLOG(1) << study.name() << " is missing default experiment in it's "
251 << "experiment list";
252 // The default group was not found in the list of groups. This study is not
253 // valid.
Alexei Svitkine (slow) 2012/05/08 03:40:13 Nit remove space before "valid".
jwd 2012/05/08 03:47:24 Done.
254 return;
255 }
256
257 const base::Time epoch = base::Time::UnixEpoch();
258 const base::Time expiry_date =
259 epoch + base::TimeDelta::FromSeconds(study.expiry_date());
260 base::Time::Exploded exploded_end_date;
261 expiry_date.UTCExplode(&exploded_end_date);
262
263 scoped_refptr<base::FieldTrial> trial(
264 base::FieldTrialList::FactoryGetFieldTrial(
265 study.name(), divisor, default_group_name, exploded_end_date.year,
266 exploded_end_date.month, exploded_end_date.day_of_month, NULL));
Alexei Svitkine (slow) 2012/05/08 03:40:13 Nit: remove space before NULL.
jwd 2012/05/08 03:47:24 Done.
267
268 if (study.has_consistency() &&
269 study.consistency() == chrome_variations::Study_Consistency_PERMANENT)
Alexei Svitkine (slow) 2012/05/08 03:40:13 Nit: Add {'s.
jwd 2012/05/08 03:47:24 Done.
270 trial->UseOneTimeRandomization();
271
272 for (int i = 0; i < study.experiment_size(); ++i) {
273 if (study.experiment(i).name() != default_group_name)
274 trial->AppendGroup(study.experiment(i).name(),
275 study.experiment(i).probability_weight());
Alexei Svitkine (slow) 2012/05/08 03:40:13 Nit: align.
SteveT 2012/05/08 03:44:28 Nit: Braces around if body, since it spans 2 physi
jwd 2012/05/08 03:47:24 Done.
276 }
277
278 trial->SetForced();
279 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698