Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/build_time.h" | 10 #include "base/build_time.h" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 if (server_url.empty()) | 91 if (server_url.empty()) |
| 92 server_url = kDefaultVariationsServerURL; | 92 server_url = kDefaultVariationsServerURL; |
| 93 GURL url_as_gurl = GURL(server_url); | 93 GURL url_as_gurl = GURL(server_url); |
| 94 DCHECK(url_as_gurl.is_valid()); | 94 DCHECK(url_as_gurl.is_valid()); |
| 95 return url_as_gurl; | 95 return url_as_gurl; |
| 96 } | 96 } |
| 97 | 97 |
| 98 } // namespace | 98 } // namespace |
| 99 | 99 |
| 100 VariationsService::VariationsService() | 100 VariationsService::VariationsService() |
| 101 : variations_server_url_(GetVariationsServerURL()) { | 101 : variations_server_url_(GetVariationsServerURL()), |
| 102 create_trials_from_seed_called_(false) { | |
| 102 } | 103 } |
| 103 | 104 |
| 104 VariationsService::~VariationsService() {} | 105 VariationsService::~VariationsService() {} |
| 105 | 106 |
| 106 bool VariationsService::CreateTrialsFromSeed(PrefService* local_prefs) { | 107 bool VariationsService::CreateTrialsFromSeed(PrefService* local_prefs) { |
| 108 create_trials_from_seed_called_ = true; | |
|
Ilya Sherman
2012/08/02 23:40:49
nit: Is it ok that this method can return |false|
Alexei Svitkine (slow)
2012/08/02 23:51:02
Right, it's just making sure we don't lose the opt
| |
| 109 | |
| 107 TrialsSeed seed; | 110 TrialsSeed seed; |
| 108 if (!LoadTrialsSeedFromPref(local_prefs, &seed)) | 111 if (!LoadTrialsSeedFromPref(local_prefs, &seed)) |
| 109 return false; | 112 return false; |
| 110 | 113 |
| 111 const int64 date_value = local_prefs->GetInt64(prefs::kVariationsSeedDate); | 114 const int64 date_value = local_prefs->GetInt64(prefs::kVariationsSeedDate); |
| 112 const base::Time seed_date = base::Time::FromInternalValue(date_value); | 115 const base::Time seed_date = base::Time::FromInternalValue(date_value); |
| 113 const base::Time build_time = base::GetBuildTime(); | 116 const base::Time build_time = base::GetBuildTime(); |
| 114 // Use the build time for date checks if either the seed date is invalid or | 117 // Use the build time for date checks if either the seed date is invalid or |
| 115 // the build time is newer than the seed date. | 118 // the build time is newer than the seed date. |
| 116 base::Time reference_date = seed_date; | 119 base::Time reference_date = seed_date; |
| 117 if (seed_date.is_null() || seed_date < build_time) | 120 if (seed_date.is_null() || seed_date < build_time) |
| 118 reference_date = build_time; | 121 reference_date = build_time; |
| 119 | 122 |
| 120 const chrome::VersionInfo current_version_info; | 123 const chrome::VersionInfo current_version_info; |
| 121 if (!current_version_info.is_valid()) | 124 if (!current_version_info.is_valid()) |
| 122 return false; | 125 return false; |
| 123 | 126 |
| 124 for (int i = 0; i < seed.study_size(); ++i) { | 127 for (int i = 0; i < seed.study_size(); ++i) { |
| 125 if (ShouldAddStudy(seed.study(i), current_version_info, reference_date)) | 128 if (ShouldAddStudy(seed.study(i), current_version_info, reference_date)) |
| 126 CreateTrialFromStudy(seed.study(i), reference_date); | 129 CreateTrialFromStudy(seed.study(i), reference_date); |
| 127 } | 130 } |
| 128 | 131 |
| 129 return true; | 132 return true; |
| 130 } | 133 } |
| 131 | 134 |
| 132 void VariationsService::StartRepeatedVariationsSeedFetch() { | 135 void VariationsService::StartRepeatedVariationsSeedFetch() { |
| 133 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 136 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 134 | 137 |
| 138 // Check that |CreateTrialsFromSeed| was called, which is necessary to | |
| 139 // retrieve the serial number that will be sent to the server. | |
| 140 DCHECK(create_trials_from_seed_called_); | |
| 141 | |
| 135 // Perform the first fetch. | 142 // Perform the first fetch. |
| 136 FetchVariationsSeed(); | 143 FetchVariationsSeed(); |
| 137 | 144 |
| 138 // Repeat this periodically. | 145 // Repeat this periodically. |
| 139 timer_.Start(FROM_HERE, base::TimeDelta::FromHours(kSeedFetchPeriodHours), | 146 timer_.Start(FROM_HERE, base::TimeDelta::FromHours(kSeedFetchPeriodHours), |
| 140 this, &VariationsService::FetchVariationsSeed); | 147 this, &VariationsService::FetchVariationsSeed); |
| 141 } | 148 } |
| 142 | 149 |
| 143 void VariationsService::FetchVariationsSeed() { | 150 void VariationsService::FetchVariationsSeed() { |
| 144 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 151 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 145 | 152 |
| 146 const bool is_offline = net::NetworkChangeNotifier::IsOffline(); | 153 const bool is_offline = net::NetworkChangeNotifier::IsOffline(); |
| 147 UMA_HISTOGRAM_BOOLEAN("Variations.NetworkAvailability", !is_offline); | 154 UMA_HISTOGRAM_BOOLEAN("Variations.NetworkAvailability", !is_offline); |
| 148 if (is_offline) { | 155 if (is_offline) { |
| 149 DVLOG(1) << "Network was offline."; | 156 DVLOG(1) << "Network was offline."; |
| 150 return; | 157 return; |
| 151 } | 158 } |
| 152 | 159 |
| 153 pending_seed_request_.reset(net::URLFetcher::Create( | 160 pending_seed_request_.reset(net::URLFetcher::Create( |
| 154 variations_server_url_, net::URLFetcher::GET, this)); | 161 variations_server_url_, net::URLFetcher::GET, this)); |
| 155 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 162 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 156 net::LOAD_DO_NOT_SAVE_COOKIES); | 163 net::LOAD_DO_NOT_SAVE_COOKIES); |
| 157 pending_seed_request_->SetRequestContext( | 164 pending_seed_request_->SetRequestContext( |
| 158 g_browser_process->system_request_context()); | 165 g_browser_process->system_request_context()); |
| 159 pending_seed_request_->SetMaxRetries(kMaxRetrySeedFetch); | 166 pending_seed_request_->SetMaxRetries(kMaxRetrySeedFetch); |
| 167 if (!variations_serial_number_.empty()) { | |
| 168 pending_seed_request_->AddExtraRequestHeader("If-Match:" + | |
| 169 variations_serial_number_); | |
| 170 } | |
| 160 pending_seed_request_->Start(); | 171 pending_seed_request_->Start(); |
| 161 } | 172 } |
| 162 | 173 |
| 163 void VariationsService::OnURLFetchComplete(const net::URLFetcher* source) { | 174 void VariationsService::OnURLFetchComplete(const net::URLFetcher* source) { |
| 164 DCHECK_EQ(pending_seed_request_.get(), source); | 175 DCHECK_EQ(pending_seed_request_.get(), source); |
| 165 // When we're done handling the request, the fetcher will be deleted. | 176 // When we're done handling the request, the fetcher will be deleted. |
| 166 scoped_ptr<const net::URLFetcher> request( | 177 scoped_ptr<const net::URLFetcher> request( |
| 167 pending_seed_request_.release()); | 178 pending_seed_request_.release()); |
| 168 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS) { | 179 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS) { |
| 169 DVLOG(1) << "Variations server request failed."; | 180 DVLOG(1) << "Variations server request failed."; |
| 170 return; | 181 return; |
| 171 } | 182 } |
| 183 | |
| 172 if (request->GetResponseCode() != 200) { | 184 if (request->GetResponseCode() != 200) { |
| 173 DVLOG(1) << "Variations server request returned non-200 response code: " | 185 DVLOG(1) << "Variations server request returned non-200 response code: " |
| 174 << request->GetResponseCode(); | 186 << request->GetResponseCode(); |
| 175 return; | 187 return; |
| 176 } | 188 } |
| 177 | 189 |
| 178 std::string seed_data; | 190 std::string seed_data; |
| 179 bool success = request->GetResponseAsString(&seed_data); | 191 bool success = request->GetResponseAsString(&seed_data); |
| 180 DCHECK(success); | 192 DCHECK(success); |
| 181 | 193 |
| 182 base::Time response_date; | 194 base::Time response_date; |
| 183 success = request->GetResponseHeaders()->GetDateValue(&response_date); | 195 success = request->GetResponseHeaders()->GetDateValue(&response_date); |
| 184 DCHECK(success || response_date.is_null()); | 196 DCHECK(success || response_date.is_null()); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 207 std::string base64_seed_data; | 219 std::string base64_seed_data; |
| 208 if (!base::Base64Encode(seed_data, &base64_seed_data)) { | 220 if (!base::Base64Encode(seed_data, &base64_seed_data)) { |
| 209 VLOG(1) << "Variations Seed data from server fails Base64Encode, rejecting " | 221 VLOG(1) << "Variations Seed data from server fails Base64Encode, rejecting " |
| 210 << "the seed."; | 222 << "the seed."; |
| 211 return false; | 223 return false; |
| 212 } | 224 } |
| 213 | 225 |
| 214 local_prefs->SetString(prefs::kVariationsSeed, base64_seed_data); | 226 local_prefs->SetString(prefs::kVariationsSeed, base64_seed_data); |
| 215 local_prefs->SetInt64(prefs::kVariationsSeedDate, | 227 local_prefs->SetInt64(prefs::kVariationsSeedDate, |
| 216 seed_date.ToInternalValue()); | 228 seed_date.ToInternalValue()); |
| 229 variations_serial_number_ = seed.serial_number(); | |
| 217 return true; | 230 return true; |
| 218 } | 231 } |
| 219 | 232 |
| 220 // static | 233 // static |
| 221 bool VariationsService::ShouldAddStudy( | 234 bool VariationsService::ShouldAddStudy( |
| 222 const Study& study, | 235 const Study& study, |
| 223 const chrome::VersionInfo& version_info, | 236 const chrome::VersionInfo& version_info, |
| 224 const base::Time& reference_date) { | 237 const base::Time& reference_date) { |
| 225 if (study.has_filter()) { | 238 if (study.has_filter()) { |
| 226 if (!CheckStudyChannel(study.filter(), chrome::VersionInfo::GetChannel())) { | 239 if (!CheckStudyChannel(study.filter(), chrome::VersionInfo::GetChannel())) { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 | 421 |
| 409 // If the decode process fails, assume the pref value is corrupt, and clear | 422 // If the decode process fails, assume the pref value is corrupt, and clear |
| 410 // it. | 423 // it. |
| 411 if (!base::Base64Decode(base64_seed_data, &seed_data) || | 424 if (!base::Base64Decode(base64_seed_data, &seed_data) || |
| 412 !seed->ParseFromString(seed_data)) { | 425 !seed->ParseFromString(seed_data)) { |
| 413 VLOG(1) << "Variations Seed data in local pref is corrupt, clearing the " | 426 VLOG(1) << "Variations Seed data in local pref is corrupt, clearing the " |
| 414 << "pref."; | 427 << "pref."; |
| 415 local_prefs->ClearPref(prefs::kVariationsSeed); | 428 local_prefs->ClearPref(prefs::kVariationsSeed); |
| 416 return false; | 429 return false; |
| 417 } | 430 } |
| 431 variations_serial_number_ = seed->serial_number(); | |
| 418 return true; | 432 return true; |
| 419 } | 433 } |
| 420 | 434 |
| 421 void VariationsService::CreateTrialFromStudy(const Study& study, | 435 void VariationsService::CreateTrialFromStudy(const Study& study, |
| 422 const base::Time& reference_date) { | 436 const base::Time& reference_date) { |
| 423 base::FieldTrial::Probability total_probability = 0; | 437 base::FieldTrial::Probability total_probability = 0; |
| 424 if (!ValidateStudyAndComputeTotalProbability(study, &total_probability)) | 438 if (!ValidateStudyAndComputeTotalProbability(study, &total_probability)) |
| 425 return; | 439 return; |
| 426 | 440 |
| 427 // The trial is created without specifying an expiration date because the | 441 // The trial is created without specifying an expiration date because the |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 450 variation_id); | 464 variation_id); |
| 451 } | 465 } |
| 452 } | 466 } |
| 453 | 467 |
| 454 trial->SetForced(); | 468 trial->SetForced(); |
| 455 if (IsStudyExpired(study, reference_date)) | 469 if (IsStudyExpired(study, reference_date)) |
| 456 trial->Disable(); | 470 trial->Disable(); |
| 457 } | 471 } |
| 458 | 472 |
| 459 } // namespace chrome_variations | 473 } // namespace chrome_variations |
| OLD | NEW |