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

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: Rebase. 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 #endif 464 #endif
455 result.reset(new VariationsService( 465 result.reset(new VariationsService(
456 new web_resource::ResourceRequestAllowedNotifier( 466 new web_resource::ResourceRequestAllowedNotifier(
457 local_state, switches::kDisableBackgroundNetworking), 467 local_state, switches::kDisableBackgroundNetworking),
458 local_state, state_manager)); 468 local_state, state_manager));
459 return result.Pass(); 469 return result.Pass();
460 } 470 }
461 471
462 void VariationsService::DoActualFetch() { 472 void VariationsService::DoActualFetch() {
463 DCHECK(thread_checker_.CalledOnValidThread()); 473 DCHECK(thread_checker_.CalledOnValidThread());
474 DCHECK(!pending_seed_request_);
464 475
465 pending_seed_request_ = net::URLFetcher::Create(0, variations_server_url_, 476 pending_seed_request_ = net::URLFetcher::Create(0, variations_server_url_,
466 net::URLFetcher::GET, this); 477 net::URLFetcher::GET, this);
467 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 478 pending_seed_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
468 net::LOAD_DO_NOT_SAVE_COOKIES); 479 net::LOAD_DO_NOT_SAVE_COOKIES);
469 pending_seed_request_->SetRequestContext( 480 pending_seed_request_->SetRequestContext(
470 g_browser_process->system_request_context()); 481 g_browser_process->system_request_context());
471 pending_seed_request_->SetMaxRetriesOn5xx(kMaxRetrySeedFetch); 482 pending_seed_request_->SetMaxRetriesOn5xx(kMaxRetrySeedFetch);
472 if (!seed_store_.variations_serial_number().empty()) { 483 if (!seed_store_.variations_serial_number().empty() &&
484 !disable_deltas_for_next_request_) {
485 // If the current seed includes a country code, deltas are not supported (as
486 // the serial number doesn't take into account the country code). The server
487 // will update us with a seed that doesn't include a country code which will
488 // enable deltas to work.
489 // TODO(asvitkine): Remove the check in M50+ when the percentage of clients
490 // that have an old seed with a country code becomes miniscule.
491 if (!seed_store_.seed_has_country_code()) {
492 // Tell the server that delta-compressed seeds are supported.
493 pending_seed_request_->AddExtraRequestHeader("A-IM:x-bm");
494 }
495 // Get the seed only if its serial number doesn't match what we have.
473 pending_seed_request_->AddExtraRequestHeader( 496 pending_seed_request_->AddExtraRequestHeader(
474 "If-Match:" + seed_store_.variations_serial_number()); 497 "If-None-Match:" + seed_store_.variations_serial_number());
475 } 498 }
476 pending_seed_request_->Start(); 499 pending_seed_request_->Start();
477 500
478 const base::TimeTicks now = base::TimeTicks::Now(); 501 const base::TimeTicks now = base::TimeTicks::Now();
479 base::TimeDelta time_since_last_fetch; 502 base::TimeDelta time_since_last_fetch;
480 // Record a time delta of 0 (default value) if there was no previous fetch. 503 // Record a time delta of 0 (default value) if there was no previous fetch.
481 if (!last_request_started_time_.is_null()) 504 if (!last_request_started_time_.is_null())
482 time_since_last_fetch = now - last_request_started_time_; 505 time_since_last_fetch = now - last_request_started_time_;
483 UMA_HISTOGRAM_CUSTOM_COUNTS("Variations.TimeSinceLastFetchAttempt", 506 UMA_HISTOGRAM_CUSTOM_COUNTS("Variations.TimeSinceLastFetchAttempt",
484 time_since_last_fetch.InMinutes(), 0, 507 time_since_last_fetch.InMinutes(), 0,
485 base::TimeDelta::FromDays(7).InMinutes(), 50); 508 base::TimeDelta::FromDays(7).InMinutes(), 50);
486 UMA_HISTOGRAM_COUNTS_100("Variations.RequestCount", request_count_); 509 UMA_HISTOGRAM_COUNTS_100("Variations.RequestCount", request_count_);
487 ++request_count_; 510 ++request_count_;
488 last_request_started_time_ = now; 511 last_request_started_time_ = now;
512 disable_deltas_for_next_request_ = false;
489 } 513 }
490 514
491 void VariationsService::StoreSeed(const std::string& seed_data, 515 bool VariationsService::StoreSeed(const std::string& seed_data,
492 const std::string& seed_signature, 516 const std::string& seed_signature,
493 const base::Time& date_fetched) { 517 const std::string& country_code,
518 const base::Time& date_fetched,
519 bool is_delta_compressed) {
494 DCHECK(thread_checker_.CalledOnValidThread()); 520 DCHECK(thread_checker_.CalledOnValidThread());
495 521
496 scoped_ptr<variations::VariationsSeed> seed(new variations::VariationsSeed); 522 scoped_ptr<variations::VariationsSeed> seed(new variations::VariationsSeed);
497 if (!seed_store_.StoreSeedData(seed_data, seed_signature, date_fetched, 523 if (!seed_store_.StoreSeedData(seed_data, seed_signature, country_code,
524 date_fetched, is_delta_compressed,
498 seed.get())) { 525 seed.get())) {
499 return; 526 return false;
500 } 527 }
501 RecordLastFetchTime(); 528 RecordLastFetchTime();
502 529
503 // Perform seed simulation only if |state_manager_| is not-NULL. The state 530 // Perform seed simulation only if |state_manager_| is not-NULL. The state
504 // manager may be NULL for some unit tests. 531 // manager may be NULL for some unit tests.
505 if (!state_manager_) 532 if (!state_manager_)
506 return; 533 return true;
507 534
508 base::PostTaskAndReplyWithResult( 535 base::PostTaskAndReplyWithResult(
509 content::BrowserThread::GetBlockingPool(), 536 content::BrowserThread::GetBlockingPool(),
510 FROM_HERE, 537 FROM_HERE,
511 base::Bind(&GetVersionForSimulation), 538 base::Bind(&GetVersionForSimulation),
512 base::Bind(&VariationsService::PerformSimulationWithVersion, 539 base::Bind(&VariationsService::PerformSimulationWithVersion,
513 weak_ptr_factory_.GetWeakPtr(), base::Passed(&seed))); 540 weak_ptr_factory_.GetWeakPtr(), base::Passed(&seed)));
541 return true;
514 } 542 }
515 543
516 void VariationsService::FetchVariationsSeed() { 544 void VariationsService::FetchVariationsSeed() {
517 DCHECK(thread_checker_.CalledOnValidThread()); 545 DCHECK(thread_checker_.CalledOnValidThread());
518 546
519 const web_resource::ResourceRequestAllowedNotifier::State state = 547 const web_resource::ResourceRequestAllowedNotifier::State state =
520 resource_request_allowed_notifier_->GetResourceRequestsAllowedState(); 548 resource_request_allowed_notifier_->GetResourceRequestsAllowedState();
521 RecordRequestsAllowedHistogram(ResourceRequestStateToHistogramValue(state)); 549 RecordRequestsAllowedHistogram(ResourceRequestStateToHistogramValue(state));
522 if (state != web_resource::ResourceRequestAllowedNotifier::ALLOWED) { 550 if (state != web_resource::ResourceRequestAllowedNotifier::ALLOWED) {
523 DVLOG(1) << "Resource requests were not allowed. Waiting for notification."; 551 DVLOG(1) << "Resource requests were not allowed. Waiting for notification.";
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 // next start up), since 304 is a successful response. 624 // next start up), since 304 is a successful response.
597 seed_store_.UpdateSeedDateAndLogDayChange(response_date); 625 seed_store_.UpdateSeedDateAndLogDayChange(response_date);
598 } 626 }
599 return; 627 return;
600 } 628 }
601 629
602 std::string seed_data; 630 std::string seed_data;
603 bool success = request->GetResponseAsString(&seed_data); 631 bool success = request->GetResponseAsString(&seed_data);
604 DCHECK(success); 632 DCHECK(success);
605 633
606 std::string seed_signature; 634 net::HttpResponseHeaders* headers = request->GetResponseHeaders();
607 request->GetResponseHeaders()->EnumerateHeader(NULL, 635 const std::string signature = GetHeaderValue(headers, "X-Seed-Signature");
608 "X-Seed-Signature", 636 const std::string country_code = GetHeaderValue(headers, "X-Country");
609 &seed_signature); 637 const bool is_delta_compressed = (GetHeaderValue(headers, "IM") == "x-bm");
610 StoreSeed(seed_data, seed_signature, response_date); 638 const bool store_success = StoreSeed(seed_data, signature, country_code,
639 response_date, is_delta_compressed);
640 if (!store_success && is_delta_compressed) {
641 disable_deltas_for_next_request_ = true;
642 request_scheduler_->ScheduleFetchShortly();
643 }
611 } 644 }
612 645
613 void VariationsService::OnResourceRequestsAllowed() { 646 void VariationsService::OnResourceRequestsAllowed() {
614 DCHECK(thread_checker_.CalledOnValidThread()); 647 DCHECK(thread_checker_.CalledOnValidThread());
615 648
616 // Note that this only attempts to fetch the seed at most once per period 649 // Note that this only attempts to fetch the seed at most once per period
617 // (kSeedFetchPeriodHours). This works because 650 // (kSeedFetchPeriodHours). This works because
618 // |resource_request_allowed_notifier_| only calls this method if an 651 // |resource_request_allowed_notifier_| only calls this method if an
619 // attempt was made earlier that fails (which implies that the period had 652 // attempt was made earlier that fails (which implies that the period had
620 // elapsed). After a successful attempt is made, the notifier will know not 653 // elapsed). After a successful attempt is made, the notifier will know not
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 // Otherwise, update the pref with the current Chrome version and country. 778 // Otherwise, update the pref with the current Chrome version and country.
746 base::ListValue new_list_value; 779 base::ListValue new_list_value;
747 new_list_value.AppendString(version.GetString()); 780 new_list_value.AppendString(version.GetString());
748 new_list_value.AppendString(latest_country); 781 new_list_value.AppendString(latest_country);
749 local_state_->Set(prefs::kVariationsPermanentConsistencyCountry, 782 local_state_->Set(prefs::kVariationsPermanentConsistencyCountry,
750 new_list_value); 783 new_list_value);
751 return latest_country; 784 return latest_country;
752 } 785 }
753 786
754 } // namespace chrome_variations 787 } // namespace chrome_variations
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698