| 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/variations_service.h" | 5 #include "chrome/browser/metrics/variations/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" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/metrics/field_trial.h" | 13 #include "base/metrics/field_trial.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/version.h" | 15 #include "base/version.h" |
| 16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/metrics/proto/trials_seed.pb.h" | 17 #include "chrome/browser/metrics/proto/trials_seed.pb.h" |
| 18 #include "chrome/browser/prefs/pref_service.h" | 18 #include "chrome/browser/prefs/pref_service.h" |
| 19 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
| 20 #include "chrome/common/metrics/variations/variations_util.h" | 20 #include "chrome/common/metrics/variations/variations_util.h" |
| 21 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
| 22 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 23 #include "content/public/common/url_fetcher.h" | 23 #include "content/public/common/url_fetcher.h" |
| 24 #include "googleurl/src/gurl.h" | 24 #include "googleurl/src/gurl.h" |
| 25 #include "net/base/load_flags.h" | 25 #include "net/base/load_flags.h" |
| 26 #include "net/base/network_change_notifier.h" | 26 #include "net/base/network_change_notifier.h" |
| 27 #include "net/http/http_response_headers.h" | 27 #include "net/http/http_response_headers.h" |
| 28 #include "net/http/http_status_code.h" |
| 28 #include "net/http/http_util.h" | 29 #include "net/http/http_util.h" |
| 29 #include "net/url_request/url_fetcher.h" | 30 #include "net/url_request/url_fetcher.h" |
| 30 #include "net/url_request/url_request_status.h" | 31 #include "net/url_request/url_request_status.h" |
| 31 | 32 |
| 32 namespace chrome_variations { | 33 namespace chrome_variations { |
| 33 | 34 |
| 34 namespace { | 35 namespace { |
| 35 | 36 |
| 36 // Default server of Variations seed info. | 37 // Default server of Variations seed info. |
| 37 const char kDefaultVariationsServerURL[] = | 38 const char kDefaultVariationsServerURL[] = |
| 38 "https://clients4.google.com/chrome-variations/seed"; | 39 "https://clients4.google.com/chrome-variations/seed"; |
| 39 const int kMaxRetrySeedFetch = 5; | 40 const int kMaxRetrySeedFetch = 5; |
| 40 | 41 |
| 41 // Time between seed fetches, in hours. | 42 // Time between seed fetches, in hours. |
| 42 const int kSeedFetchPeriodHours = 5; | 43 const int kSeedFetchPeriodHours = 5; |
| 43 | 44 |
| 45 // TODO(mad): To be removed when we stop updating the NetworkTimeTracker. |
| 46 // For the HTTP date headers, the resolution of the server time is 1 second. |
| 47 const int64 kServerTimeResolutionMs = 1000; |
| 48 |
| 44 // Maps Study_Channel enum values to corresponding chrome::VersionInfo::Channel | 49 // Maps Study_Channel enum values to corresponding chrome::VersionInfo::Channel |
| 45 // enum values. | 50 // enum values. |
| 46 chrome::VersionInfo::Channel ConvertStudyChannelToVersionChannel( | 51 chrome::VersionInfo::Channel ConvertStudyChannelToVersionChannel( |
| 47 Study_Channel study_channel) { | 52 Study_Channel study_channel) { |
| 48 switch (study_channel) { | 53 switch (study_channel) { |
| 49 case Study_Channel_CANARY: | 54 case Study_Channel_CANARY: |
| 50 return chrome::VersionInfo::CHANNEL_CANARY; | 55 return chrome::VersionInfo::CHANNEL_CANARY; |
| 51 case Study_Channel_DEV: | 56 case Study_Channel_DEV: |
| 52 return chrome::VersionInfo::CHANNEL_DEV; | 57 return chrome::VersionInfo::CHANNEL_DEV; |
| 53 case Study_Channel_BETA: | 58 case Study_Channel_BETA: |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 DCHECK(create_trials_from_seed_called_); | 185 DCHECK(create_trials_from_seed_called_); |
| 181 | 186 |
| 182 // Perform the first fetch. | 187 // Perform the first fetch. |
| 183 FetchVariationsSeed(); | 188 FetchVariationsSeed(); |
| 184 | 189 |
| 185 // Repeat this periodically. | 190 // Repeat this periodically. |
| 186 timer_.Start(FROM_HERE, base::TimeDelta::FromHours(kSeedFetchPeriodHours), | 191 timer_.Start(FROM_HERE, base::TimeDelta::FromHours(kSeedFetchPeriodHours), |
| 187 this, &VariationsService::FetchVariationsSeed); | 192 this, &VariationsService::FetchVariationsSeed); |
| 188 } | 193 } |
| 189 | 194 |
| 195 bool VariationsService::GetNetworkTime(base::Time* network_time, |
| 196 base::TimeDelta* uncertainty) const { |
| 197 return network_time_tracker_.GetNetworkTime(network_time, uncertainty); |
| 198 } |
| 199 |
| 190 #if defined(OS_WIN) | 200 #if defined(OS_WIN) |
| 191 void VariationsService::StartGoogleUpdateRegistrySync() { | 201 void VariationsService::StartGoogleUpdateRegistrySync() { |
| 192 registry_syncer_.RequestRegistrySync(); | 202 registry_syncer_.RequestRegistrySync(); |
| 193 } | 203 } |
| 194 #endif | 204 #endif |
| 195 | 205 |
| 196 void VariationsService::SetCreateTrialsFromSeedCalledForTesting(bool called) { | 206 void VariationsService::SetCreateTrialsFromSeedCalledForTesting(bool called) { |
| 197 create_trials_from_seed_called_ = called; | 207 create_trials_from_seed_called_ = called; |
| 198 } | 208 } |
| 199 | 209 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 DCHECK_EQ(pending_seed_request_.get(), source); | 259 DCHECK_EQ(pending_seed_request_.get(), source); |
| 250 // The fetcher will be deleted when the request is handled. | 260 // The fetcher will be deleted when the request is handled. |
| 251 scoped_ptr<const net::URLFetcher> request( | 261 scoped_ptr<const net::URLFetcher> request( |
| 252 pending_seed_request_.release()); | 262 pending_seed_request_.release()); |
| 253 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS) { | 263 if (request->GetStatus().status() != net::URLRequestStatus::SUCCESS) { |
| 254 DVLOG(1) << "Variations server request failed."; | 264 DVLOG(1) << "Variations server request failed."; |
| 255 return; | 265 return; |
| 256 } | 266 } |
| 257 | 267 |
| 258 // Log the response code. | 268 // Log the response code. |
| 269 const int response_code = request->GetResponseCode(); |
| 259 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Variations.SeedFetchResponseCode", | 270 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Variations.SeedFetchResponseCode", |
| 260 net::HttpUtil::MapStatusCodeForHistogram(request->GetResponseCode()), | 271 net::HttpUtil::MapStatusCodeForHistogram(response_code), |
| 261 net::HttpUtil::GetStatusCodesForHistogram()); | 272 net::HttpUtil::GetStatusCodesForHistogram()); |
| 262 | 273 |
| 263 const base::TimeDelta latency = | 274 const base::TimeDelta latency = |
| 264 base::TimeTicks::Now() - last_request_started_time_; | 275 base::TimeTicks::Now() - last_request_started_time_; |
| 265 | 276 |
| 266 if (request->GetResponseCode() != 200) { | 277 base::Time response_date; |
| 267 DVLOG(1) << "Variations server request returned non-200 response code: " | 278 if (response_code == net::HTTP_OK || |
| 268 << request->GetResponseCode(); | 279 response_code == net::HTTP_NOT_MODIFIED) { |
| 269 if (request->GetResponseCode() == 304) | 280 bool success = request->GetResponseHeaders()->GetDateValue(&response_date); |
| 281 DCHECK(success || response_date.is_null()); |
| 282 |
| 283 if (!response_date.is_null()) { |
| 284 network_time_tracker_.UpdateNetworkTime( |
| 285 response_date, |
| 286 base::TimeDelta::FromMilliseconds(kServerTimeResolutionMs), |
| 287 latency); |
| 288 } |
| 289 } else if (response_code != net::HTTP_OK) { |
| 290 DVLOG(1) << "Variations server request returned non-HTTP_OK response code: " |
| 291 << response_code; |
| 292 if (response_code == net::HTTP_NOT_MODIFIED) |
| 270 UMA_HISTOGRAM_MEDIUM_TIMES("Variations.FetchNotModifiedLatency", latency); | 293 UMA_HISTOGRAM_MEDIUM_TIMES("Variations.FetchNotModifiedLatency", latency); |
| 271 else | 294 else |
| 272 UMA_HISTOGRAM_MEDIUM_TIMES("Variations.FetchOtherLatency", latency); | 295 UMA_HISTOGRAM_MEDIUM_TIMES("Variations.FetchOtherLatency", latency); |
| 273 return; | 296 return; |
| 274 } | 297 } |
| 275 UMA_HISTOGRAM_MEDIUM_TIMES("Variations.FetchSuccessLatency", latency); | 298 UMA_HISTOGRAM_MEDIUM_TIMES("Variations.FetchSuccessLatency", latency); |
| 276 | 299 |
| 277 std::string seed_data; | 300 std::string seed_data; |
| 278 bool success = request->GetResponseAsString(&seed_data); | 301 bool success = request->GetResponseAsString(&seed_data); |
| 279 DCHECK(success); | 302 DCHECK(success); |
| 280 | 303 |
| 281 base::Time response_date; | |
| 282 success = request->GetResponseHeaders()->GetDateValue(&response_date); | |
| 283 DCHECK(success || response_date.is_null()); | |
| 284 | |
| 285 StoreSeedData(seed_data, response_date, g_browser_process->local_state()); | 304 StoreSeedData(seed_data, response_date, g_browser_process->local_state()); |
| 286 } | 305 } |
| 287 | 306 |
| 288 void VariationsService::OnResourceRequestsAllowed() { | 307 void VariationsService::OnResourceRequestsAllowed() { |
| 289 // Note that this only attempts to fetch the seed at most once per period | 308 // Note that this only attempts to fetch the seed at most once per period |
| 290 // (kSeedFetchPeriodHours). This works because | 309 // (kSeedFetchPeriodHours). This works because |
| 291 // |resource_request_allowed_notifier_| only calls this method if an | 310 // |resource_request_allowed_notifier_| only calls this method if an |
| 292 // attempt was made earlier that fails (which implies that the period had | 311 // attempt was made earlier that fails (which implies that the period had |
| 293 // elapsed). After a successful attempt is made, the notifier will know not | 312 // elapsed). After a successful attempt is made, the notifier will know not |
| 294 // to call this method again until another failed attempt occurs. | 313 // to call this method again until another failed attempt occurs. |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 variation_id); | 578 variation_id); |
| 560 } | 579 } |
| 561 } | 580 } |
| 562 | 581 |
| 563 trial->SetForced(); | 582 trial->SetForced(); |
| 564 if (IsStudyExpired(study, reference_date)) | 583 if (IsStudyExpired(study, reference_date)) |
| 565 trial->Disable(); | 584 trial->Disable(); |
| 566 } | 585 } |
| 567 | 586 |
| 568 } // namespace chrome_variations | 587 } // namespace chrome_variations |
| OLD | NEW |