1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/rappor/rappor_service.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/base64.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/metrics/field_trial.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/prefs/pref_service.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/rand_util.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/stl_util.h" 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/time/time.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/metrics/metrics_hashes.h" 15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/rappor/log_uploader.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/rappor/proto/rappor_metric.pb.h" 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/rappor/rappor_metric.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/rappor/rappor_pref_names.h" 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/variations/variations_associated_data.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace rappor { 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Seconds before the initial log is generated. 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kInitialLogIntervalSeconds = 15; 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Interval between ongoing logs. 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kLogIntervalSeconds = 30 * 60; 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kMimeType[] = "application/vnd.chrome.rappor"; 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char kRapporDailyEventHistogram[] = "Rappor.DailyEvent.IntervalType"; 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Constants for the RAPPOR rollout field trial. 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kRapporRolloutFieldTrialName[] = "RapporRollout"; 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Constant for the finch parameter name for the server URL 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kRapporRolloutServerUrlParam[] = "ServerUrl"; 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Constant for the finch parameter name for the server URL 416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kRapporRolloutRequireUmaParam[] = "RequireUma"; 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// The rappor server's URL. 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kDefaultServerUrl[] = "https://clients4.google.com/rappor"; 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)GURL GetServerUrl(bool metrics_enabled) { 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool require_uma = variations::GetVariationParamValue( 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) kRapporRolloutFieldTrialName, 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) kRapporRolloutRequireUmaParam) != "False"; 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!metrics_enabled && require_uma) 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return GURL(); // Invalid URL disables Rappor. 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string server_url = variations::GetVariationParamValue( 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kRapporRolloutFieldTrialName, 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kRapporRolloutServerUrlParam); 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!server_url.empty()) 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GURL(server_url); 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GURL(kDefaultServerUrl); 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const RapporParameters kRapporParametersForType[NUM_RAPPOR_TYPES] = { 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // ETLD_PLUS_ONE_RAPPOR_TYPE 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) {128 /* Num cohorts */, 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 16 /* Bloom filter size bytes */, 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2 /* Bloom filter hash count */, 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) rappor::PROBABILITY_50 /* Fake data probability */, 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch rappor::PROBABILITY_50 /* Fake one probability */, 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch rappor::PROBABILITY_75 /* One coin probability */, 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) rappor::PROBABILITY_25 /* Zero coin probability */}, 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciRapporService::RapporService(PrefService* pref_service) 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : pref_service_(pref_service), 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cohort_(-1), 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci daily_event_(pref_service, 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci prefs::kRapporLastDailySample, 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kRapporDailyEventHistogram) { 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)RapporService::~RapporService() { 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STLDeleteValues(&metrics_map_); 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RapporService::AddDailyObserver( 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<metrics::DailyEvent::Observer> observer) { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci daily_event_.AddObserver(observer.Pass()); 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RapporService::Start(net::URLRequestContextGetter* request_context, 926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool metrics_enabled) { 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const GURL server_url = GetServerUrl(metrics_enabled); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!server_url.is_valid()) { 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DVLOG(1) << server_url.spec() << " is invalid. " 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << "RapporService not started."; 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(1) << "RapporService started. Reporting to " << server_url.spec(); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!uploader_); 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LoadSecret(); 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LoadCohort(); 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uploader_.reset(new LogUploader(server_url, kMimeType, request_context)); 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) log_rotation_timer_.Start( 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta::FromSeconds(kInitialLogIntervalSeconds), 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &RapporService::OnLogInterval); 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RapporService::OnLogInterval() { 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(uploader_); 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(2) << "RapporService::OnLogInterval"; 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci daily_event_.CheckInterval(); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RapporReports reports; 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (ExportMetrics(&reports)) { 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string log_text; 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool success = reports.SerializeToString(&log_text); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(success); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(1) << "RapporService sending a report of " 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << reports.report_size() << " value(s)."; 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uploader_->QueueLog(log_text); 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) log_rotation_timer_.Start(FROM_HERE, 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta::FromSeconds(kLogIntervalSeconds), 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &RapporService::OnLogInterval); 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RapporService::RegisterPrefs(PrefRegistrySimple* registry) { 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) registry->RegisterStringPref(prefs::kRapporSecret, std::string()); 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registry->RegisterIntegerPref(prefs::kRapporCohortDeprecated, -1); 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registry->RegisterIntegerPref(prefs::kRapporCohortSeed, -1); 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metrics::DailyEvent::RegisterPref(registry, 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci prefs::kRapporLastDailySample); 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RapporService::LoadCohort() { 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!IsInitialized()); 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Ignore and delete old cohort parameter. 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pref_service_->ClearPref(prefs::kRapporCohortDeprecated); 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cohort_ = pref_service_->GetInteger(prefs::kRapporCohortSeed); 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the user is already assigned to a valid cohort, we're done. 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (cohort_ >= 0 && cohort_ < RapporParameters::kMaxCohorts) 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // This is the first time the client has started the service (or their 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // preferences were corrupted). Randomly assign them to a cohort. 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cohort_ = base::RandGenerator(RapporParameters::kMaxCohorts); 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(2) << "Selected a new Rappor cohort: " << cohort_; 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pref_service_->SetInteger(prefs::kRapporCohortSeed, cohort_); 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RapporService::LoadSecret() { 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(secret_.empty()); 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string secret_base64 = pref_service_->GetString(prefs::kRapporSecret); 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!secret_base64.empty()) { 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool decoded = base::Base64Decode(secret_base64, &secret_); 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (decoded && secret_.size() == HmacByteVectorGenerator::kEntropyInputSize) 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the preference fails to decode, or is the wrong size, it must be 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // corrupt, so continue as though it didn't exist yet and generate a new 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // one. 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(2) << "Generated a new Rappor secret."; 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) secret_ = HmacByteVectorGenerator::GenerateEntropyInput(); 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Base64Encode(secret_, &secret_base64); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pref_service_->SetString(prefs::kRapporSecret, secret_base64); 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RapporService::ExportMetrics(RapporReports* reports) { 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (metrics_map_.empty()) 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_GE(cohort_, 0); 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reports->set_cohort(cohort_); 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::map<std::string, RapporMetric*>::const_iterator it = 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch metrics_map_.begin(); 183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != metrics_map_.end(); 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ++it) { 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const RapporMetric* metric = it->second; 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RapporReports::Report* report = reports->add_report(); 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) report->set_name_hash(metrics::HashMetricName(it->first)); 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ByteVector bytes = metric->GetReport(secret_); 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) report->set_bits(std::string(bytes.begin(), bytes.end())); 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STLDeleteValues(&metrics_map_); 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RapporService::IsInitialized() const { 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return cohort_ >= 0; 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RapporService::RecordSample(const std::string& metric_name, 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RapporType type, 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& sample) { 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Ignore the sample if the service hasn't started yet. 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsInitialized()) 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_LT(type, NUM_RAPPOR_TYPES); 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DVLOG(2) << "Recording sample \"" << sample 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "\" for metric \"" << metric_name 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "\" of type: " << type; 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecordSampleInternal(metric_name, kRapporParametersForType[type], sample); 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RapporService::RecordSampleInternal(const std::string& metric_name, 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const RapporParameters& parameters, 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& sample) { 215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(IsInitialized()); 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RapporMetric* metric = LookUpMetric(metric_name, parameters); 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) metric->AddSample(sample); 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)RapporMetric* RapporService::LookUpMetric(const std::string& metric_name, 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const RapporParameters& parameters) { 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(IsInitialized()); 223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::map<std::string, RapporMetric*>::const_iterator it = 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) metrics_map_.find(metric_name); 225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (it != metrics_map_.end()) { 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RapporMetric* metric = it->second; 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(parameters.ToString(), metric->parameters().ToString()); 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return metric; 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RapporMetric* new_metric = new RapporMetric(metric_name, parameters, cohort_); 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) metrics_map_[metric_name] = new_metric; 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new_metric; 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace rappor 237