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

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

Issue 1200233005: Support delta-compressed variations server responses. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing missing return in !is_compressed case. Created 5 years, 4 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
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/variations_service.h" 5 #include "chrome/browser/metrics/variations/variations_service.h"
6 6
7 #include "base/build_time.h" 7 #include "base/build_time.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/metrics/sparse_histogram.h" 10 #include "base/metrics/sparse_histogram.h"
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 const base::Time seed_date = base::Time::FromInternalValue(date_value); 213 const base::Time seed_date = base::Time::FromInternalValue(date_value);
214 const base::Time build_time = base::GetBuildTime(); 214 const base::Time build_time = base::GetBuildTime();
215 // Use the build time for date checks if either the seed date is invalid or 215 // Use the build time for date checks if either the seed date is invalid or
216 // the build time is newer than the seed date. 216 // the build time is newer than the seed date.
217 base::Time reference_date = seed_date; 217 base::Time reference_date = seed_date;
218 if (seed_date.is_null() || seed_date < build_time) 218 if (seed_date.is_null() || seed_date < build_time)
219 reference_date = build_time; 219 reference_date = build_time;
220 return reference_date; 220 return reference_date;
221 } 221 }
222 222
223 // Returns the header value for |name| from |headers| or an empty string if not
224 // set.
225 std::string GetHeaderValue(const net::HttpResponseHeaders* headers,
226 const base::StringPiece& name) {
227 std::string value;
228 headers->EnumerateHeader(NULL, name, &value);
229 return value;
230 }
231
223 // Overrides the string resource sepecified by |hash| with |string| in the 232 // Overrides the string resource sepecified by |hash| with |string| in the
224 // resource bundle. Used as a callback passed to the variations seed processor. 233 // resource bundle. Used as a callback passed to the variations seed processor.
225 void OverrideUIString(uint32_t hash, const base::string16& string) { 234 void OverrideUIString(uint32_t hash, const base::string16& string) {
226 int resource_id = GetResourceIndex(hash); 235 int resource_id = GetResourceIndex(hash);
227 if (resource_id == -1) 236 if (resource_id == -1)
228 return; 237 return;
229 238
230 ui::ResourceBundle::GetSharedInstance().OverrideLocaleStringResource( 239 ui::ResourceBundle::GetSharedInstance().OverrideLocaleStringResource(
231 resource_id, string); 240 resource_id, string);
232 } 241 }
233 242
234 } // namespace 243 } // namespace
235 244
236 VariationsService::VariationsService( 245 VariationsService::VariationsService(
237 web_resource::ResourceRequestAllowedNotifier* notifier, 246 web_resource::ResourceRequestAllowedNotifier* notifier,
238 PrefService* local_state, 247 PrefService* local_state,
239 metrics::MetricsStateManager* state_manager) 248 metrics::MetricsStateManager* state_manager)
240 : local_state_(local_state), 249 : local_state_(local_state),
241 state_manager_(state_manager), 250 state_manager_(state_manager),
242 policy_pref_service_(local_state), 251 policy_pref_service_(local_state),
243 seed_store_(local_state), 252 seed_store_(local_state),
244 create_trials_from_seed_called_(false), 253 create_trials_from_seed_called_(false),
245 initial_request_completed_(false), 254 initial_request_completed_(false),
255 disable_deltas_for_next_request_(false),
246 resource_request_allowed_notifier_(notifier), 256 resource_request_allowed_notifier_(notifier),
247 request_count_(0), 257 request_count_(0),
248 weak_ptr_factory_(this) { 258 weak_ptr_factory_(this) {
249 resource_request_allowed_notifier_->Init(this); 259 resource_request_allowed_notifier_->Init(this);
250 } 260 }
251 261
252 VariationsService::~VariationsService() { 262 VariationsService::~VariationsService() {
253 } 263 }
254 264
255 bool VariationsService::CreateTrialsFromSeed() { 265 bool VariationsService::CreateTrialsFromSeed() {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 #endif 463 #endif
454 result.reset(new VariationsService( 464 result.reset(new VariationsService(
455 new web_resource::ResourceRequestAllowedNotifier( 465 new web_resource::ResourceRequestAllowedNotifier(
456 local_state, switches::kDisableBackgroundNetworking), 466 local_state, switches::kDisableBackgroundNetworking),
457 local_state, state_manager)); 467 local_state, state_manager));
458 return result.Pass(); 468 return result.Pass();
459 } 469 }
460 470
461 void VariationsService::DoActualFetch() { 471 void VariationsService::DoActualFetch() {
462 DCHECK(thread_checker_.CalledOnValidThread()); 472 DCHECK(thread_checker_.CalledOnValidThread());
473 DCHECK(!pending_seed_request_);
463 474
464 pending_seed_request_ = net::URLFetcher::Create(0, variations_server_url_, 475 pending_seed_request_ = net::URLFetcher::Create(0, variations_server_url_,
465 net::URLFetcher::GET, this); 476 net::URLFetcher::GET, this);
466 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 477 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
467 net::LOAD_DO_NOT_SAVE_COOKIES); 478 net::LOAD_DO_NOT_SAVE_COOKIES);
468 pending_seed_request_->SetRequestContext( 479 pending_seed_request_->SetRequestContext(
469 g_browser_process->system_request_context()); 480 g_browser_process->system_request_context());
470 pending_seed_request_->SetMaxRetriesOn5xx(kMaxRetrySeedFetch); 481 pending_seed_request_->SetMaxRetriesOn5xx(kMaxRetrySeedFetch);
471 if (!seed_store_.variations_serial_number().empty()) { 482 if (!seed_store_.variations_serial_number().empty() &&
483 !disable_deltas_for_next_request_) {
484 // If the current seed includes a country code, deltas are not supported (as
485 // the serial number doesn't take into account the country code). The server
486 // will update us with a seed that doesn't include a country code which will
487 // enable deltas to work.
488 // TODO(asvitkine): Remove the check in M50+ when the percentage of clients
489 // that have an old seed with a country code becomes miniscule.
490 if (!seed_store_.seed_has_country_code()) {
491 // Tell the server that delta-compressed seeds are supported.
492 pending_seed_request_->AddExtraRequestHeader("A-IM:x-bm");
493 }
494 // Get the seed only if its serial number doesn't match what we have.
472 pending_seed_request_->AddExtraRequestHeader( 495 pending_seed_request_->AddExtraRequestHeader(
473 "If-Match:" + seed_store_.variations_serial_number()); 496 "If-None-Match:" + seed_store_.variations_serial_number());
474 } 497 }
475 pending_seed_request_->Start(); 498 pending_seed_request_->Start();
476 499
477 const base::TimeTicks now = base::TimeTicks::Now(); 500 const base::TimeTicks now = base::TimeTicks::Now();
478 base::TimeDelta time_since_last_fetch; 501 base::TimeDelta time_since_last_fetch;
479 // Record a time delta of 0 (default value) if there was no previous fetch. 502 // Record a time delta of 0 (default value) if there was no previous fetch.
480 if (!last_request_started_time_.is_null()) 503 if (!last_request_started_time_.is_null())
481 time_since_last_fetch = now - last_request_started_time_; 504 time_since_last_fetch = now - last_request_started_time_;
482 UMA_HISTOGRAM_CUSTOM_COUNTS("Variations.TimeSinceLastFetchAttempt", 505 UMA_HISTOGRAM_CUSTOM_COUNTS("Variations.TimeSinceLastFetchAttempt",
483 time_since_last_fetch.InMinutes(), 0, 506 time_since_last_fetch.InMinutes(), 0,
484 base::TimeDelta::FromDays(7).InMinutes(), 50); 507 base::TimeDelta::FromDays(7).InMinutes(), 50);
485 UMA_HISTOGRAM_COUNTS_100("Variations.RequestCount", request_count_); 508 UMA_HISTOGRAM_COUNTS_100("Variations.RequestCount", request_count_);
486 ++request_count_; 509 ++request_count_;
487 last_request_started_time_ = now; 510 last_request_started_time_ = now;
511 disable_deltas_for_next_request_ = false;
488 } 512 }
489 513
490 void VariationsService::StoreSeed(const std::string& seed_data, 514 bool VariationsService::StoreSeed(const std::string& seed_data,
491 const std::string& seed_signature, 515 const std::string& seed_signature,
492 const base::Time& date_fetched) { 516 const std::string& country_code,
517 const base::Time& date_fetched,
518 bool is_delta_compressed) {
493 DCHECK(thread_checker_.CalledOnValidThread()); 519 DCHECK(thread_checker_.CalledOnValidThread());
494 520
495 scoped_ptr<variations::VariationsSeed> seed(new variations::VariationsSeed); 521 scoped_ptr<variations::VariationsSeed> seed(new variations::VariationsSeed);
496 if (!seed_store_.StoreSeedData(seed_data, seed_signature, date_fetched, 522 if (!seed_store_.StoreSeedData(seed_data, seed_signature, country_code,
523 date_fetched, is_delta_compressed,
497 seed.get())) { 524 seed.get())) {
498 return; 525 return false;
499 } 526 }
500 RecordLastFetchTime(); 527 RecordLastFetchTime();
501 528
502 // Perform seed simulation only if |state_manager_| is not-NULL. The state 529 // Perform seed simulation only if |state_manager_| is not-NULL. The state
503 // manager may be NULL for some unit tests. 530 // manager may be NULL for some unit tests.
504 if (!state_manager_) 531 if (!state_manager_)
505 return; 532 return true;
506 533
507 base::PostTaskAndReplyWithResult( 534 base::PostTaskAndReplyWithResult(
508 content::BrowserThread::GetBlockingPool(), 535 content::BrowserThread::GetBlockingPool(),
509 FROM_HERE, 536 FROM_HERE,
510 base::Bind(&GetVersionForSimulation), 537 base::Bind(&GetVersionForSimulation),
511 base::Bind(&VariationsService::PerformSimulationWithVersion, 538 base::Bind(&VariationsService::PerformSimulationWithVersion,
512 weak_ptr_factory_.GetWeakPtr(), base::Passed(&seed))); 539 weak_ptr_factory_.GetWeakPtr(), base::Passed(&seed)));
540 return true;
513 } 541 }
514 542
515 void VariationsService::FetchVariationsSeed() { 543 void VariationsService::FetchVariationsSeed() {
516 DCHECK(thread_checker_.CalledOnValidThread()); 544 DCHECK(thread_checker_.CalledOnValidThread());
517 545
518 const web_resource::ResourceRequestAllowedNotifier::State state = 546 const web_resource::ResourceRequestAllowedNotifier::State state =
519 resource_request_allowed_notifier_->GetResourceRequestsAllowedState(); 547 resource_request_allowed_notifier_->GetResourceRequestsAllowedState();
520 RecordRequestsAllowedHistogram(ResourceRequestStateToHistogramValue(state)); 548 RecordRequestsAllowedHistogram(ResourceRequestStateToHistogramValue(state));
521 if (state != web_resource::ResourceRequestAllowedNotifier::ALLOWED) { 549 if (state != web_resource::ResourceRequestAllowedNotifier::ALLOWED) {
522 DVLOG(1) << "Resource requests were not allowed. Waiting for notification."; 550 DVLOG(1) << "Resource requests were not allowed. Waiting for notification.";
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 // next start up), since 304 is a successful response. 623 // next start up), since 304 is a successful response.
596 seed_store_.UpdateSeedDateAndLogDayChange(response_date); 624 seed_store_.UpdateSeedDateAndLogDayChange(response_date);
597 } 625 }
598 return; 626 return;
599 } 627 }
600 628
601 std::string seed_data; 629 std::string seed_data;
602 bool success = request->GetResponseAsString(&seed_data); 630 bool success = request->GetResponseAsString(&seed_data);
603 DCHECK(success); 631 DCHECK(success);
604 632
605 std::string seed_signature; 633 net::HttpResponseHeaders* headers = request->GetResponseHeaders();
606 request->GetResponseHeaders()->EnumerateHeader(NULL, 634 const std::string signature = GetHeaderValue(headers, "X-Seed-Signature");
607 "X-Seed-Signature", 635 const std::string country_code = GetHeaderValue(headers, "X-Country");
608 &seed_signature); 636 const bool is_delta_compressed = (GetHeaderValue(headers, "IM") == "x-bm");
609 StoreSeed(seed_data, seed_signature, response_date); 637 const bool store_success = StoreSeed(seed_data, signature, country_code,
638 response_date, is_delta_compressed);
639 if (!store_success && is_delta_compressed) {
640 disable_deltas_for_next_request_ = true;
641 request_scheduler_->ScheduleFetchShortly();
642 }
610 } 643 }
611 644
612 void VariationsService::OnResourceRequestsAllowed() { 645 void VariationsService::OnResourceRequestsAllowed() {
613 DCHECK(thread_checker_.CalledOnValidThread()); 646 DCHECK(thread_checker_.CalledOnValidThread());
614 647
615 // Note that this only attempts to fetch the seed at most once per period 648 // Note that this only attempts to fetch the seed at most once per period
616 // (kSeedFetchPeriodHours). This works because 649 // (kSeedFetchPeriodHours). This works because
617 // |resource_request_allowed_notifier_| only calls this method if an 650 // |resource_request_allowed_notifier_| only calls this method if an
618 // attempt was made earlier that fails (which implies that the period had 651 // attempt was made earlier that fails (which implies that the period had
619 // elapsed). After a successful attempt is made, the notifier will know not 652 // elapsed). After a successful attempt is made, the notifier will know not
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 // Otherwise, update the pref with the current Chrome version and country. 777 // Otherwise, update the pref with the current Chrome version and country.
745 base::ListValue new_list_value; 778 base::ListValue new_list_value;
746 new_list_value.AppendString(version.GetString()); 779 new_list_value.AppendString(version.GetString());
747 new_list_value.AppendString(latest_country); 780 new_list_value.AppendString(latest_country);
748 local_state_->Set(prefs::kVariationsPermanentConsistencyCountry, 781 local_state_->Set(prefs::kVariationsPermanentConsistencyCountry,
749 new_list_value); 782 new_list_value);
750 return latest_country; 783 return latest_country;
751 } 784 }
752 785
753 } // namespace chrome_variations 786 } // namespace chrome_variations
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698