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

Side by Side Diff: components/rappor/rappor_service.cc

Issue 49753002: RAPPOR implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: RapporMetrics StatsTest Created 6 years, 11 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
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/rappor/rappor_service.h"
6
7 #include <cstdlib>
8
9 #include "base/base64.h"
10 #include "base/hash.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/prefs/pref_registry_simple.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/rand_util.h"
15 #include "base/stl_util.h"
16 #include "components/rappor/proto/rappor_metric.pb.h"
17 #include "components/rappor/rappor_pref_names.h"
18
19 namespace {
20
21 // Seconds before the initial log is generated.
22 const int kInitialLogIntervalSeconds = 15;
23 // Interval between ongoing logs.
24 const int kLogIntervalSeconds = 30 * 60;
25
26 const char kServerUrl[] = "https://clients4.google.com/rappor/v2";
Alexei Svitkine (slow) 2014/01/21 18:14:04 Probably wouldn't be v2. Maybe it's a good idea t
Steven Holte 2014/01/21 20:25:14 Done. Also changed service activation to depend o
27 const char kMimeType[] = "application/vnd.chrome.rappor";
28
29 // Constants for the RAPPOR rollout field trial.
30 const char kRapporRolloutFieldTrialName[] = "RapporRollout";
31 const char kRapporRolloutFieldTrialEnabledGroupName[] = "Enabled";
32
33 bool FieldTrialIsActive() {
34 return base::FieldTrialList::FindFullName(kRapporRolloutFieldTrialName) ==
35 kRapporRolloutFieldTrialEnabledGroupName;
36 }
37
38 } // namespace
39
40 namespace rappor {
41
42 RapporService::RapporService() {}
43
44 RapporService::~RapporService() {}
45
46 void RapporService::Start(PrefService* pref_service,
47 net::URLRequestContextGetter* request_context) {
48 if (!FieldTrialIsActive())
49 return;
50 DCHECK(!uploader_);
51 GetSecret(pref_service);
52 uploader_.reset(new LogUploader(kServerUrl, kMimeType, request_context));
53 log_rotation_timer_.Start(
54 FROM_HERE,
55 base::TimeDelta::FromSeconds(kInitialLogIntervalSeconds),
56 this,
57 &RapporService::OnLogInterval);
58 }
59
60 void RapporService::OnLogInterval() {
61 DCHECK(uploader_);
62 RapporReports reports;
63 LogMetrics(&reports);
64 if (reports.report_size() > 0) {
65 std::string log_text;
66 bool success = reports.SerializeToString(&log_text);
67 DCHECK(success);
68 uploader_->QueueLog(log_text);
69 }
70 log_rotation_timer_.Start(FROM_HERE,
71 base::TimeDelta::FromSeconds(kLogIntervalSeconds),
72 this,
73 &RapporService::OnLogInterval);
74 }
75
76 // static
77 void RapporService::RegisterPrefs(PrefRegistrySimple* registry) {
78 registry->RegisterStringPref(prefs::kRapporSecret, std::string());
79 }
80
81 void RapporService::GetSecret(PrefService* pref_service) {
82 if (!secret_.empty())
83 return;
84 std::string secret_base64 =
85 pref_service->GetString(prefs::kRapporSecret);
86 if (!secret_base64.empty()) {
87 bool decoded = base::Base64Decode(secret_base64, &secret_);
88 if (decoded)
89 return;
90 // If the preference fails to decode, it must be corrupt, so continue as
91 // though it didn't exist yet and generate a new one.
92 }
93
94 secret_ = base::RandBytesAsString(128);
95 base::Base64Encode(secret_, &secret_base64);
96 pref_service->SetString(prefs::kRapporSecret, secret_base64);
97 }
98
99 void RapporService::LogMetric(const RapporMetric& metric,
100 RapporReports::Report* report) {
101 report->set_name_hash(base::Hash(metric.parameters()->rappor_name));
102 ByteVector bytes = metric.GetReport(secret_);
103 std::string byte_string(bytes.begin(), bytes.end());
104 report->set_bits(byte_string);
105 }
106
107 void RapporService::LogMetrics(RapporReports* reports) {
108 base::AutoLock auto_lock(lock_);
109
110 for (std::map<std::string, RapporMetric*>::iterator it = metrics_map_.begin();
111 metrics_map_.end() != it;
112 ++it) {
113 const RapporMetric* metric = it->second;
114 DCHECK_EQ(it->first, metric->parameters()->rappor_name);
115 RapporReports::Report* report = reports->add_report();
116 LogMetric(*metric, report);
117 }
118 STLDeleteContainerPairSecondPointers(
119 metrics_map_.begin(), metrics_map_.end());
120 metrics_map_.clear();
121 }
122
123 void RapporService::RecordSamples(const RapporParameters& parameters,
124 const std::vector<std::string>& samples) {
125 if (!FieldTrialIsActive())
126 return;
127 RecordSamplesInternal(parameters, samples);
128 }
129
130 void RapporService::RecordUrl(const RapporParameters& parameters,
131 const GURL& url) {
132 if (!FieldTrialIsActive())
133 return;
134 std::vector<std::string> samples;
135 samples.push_back(url.spec());
136 samples.push_back(url.host());
137 // TODO(holte): break up host more
138 samples.push_back(url.query());
139 samples.push_back(url.path());
140 RecordSamplesInternal(parameters, samples);
141 }
142
143 void RapporService::RecordSamplesInternal(
144 const RapporParameters& parameters,
145 const std::vector<std::string>& samples) {
146 base::AutoLock auto_lock(lock_);
147
148 RapporMetric* metric = LookupMetric(parameters);
149 metric->AddSamples(samples);
150 }
151
152 RapporMetric* RapporService::LookupMetric(
153 const RapporParameters& parameters) {
154 std::map<std::string, RapporMetric*>::iterator it =
155 metrics_map_.find(parameters.rappor_name);
156 if (metrics_map_.end() != it) {
157 RapporMetric* metric = it->second;
158 DCHECK_EQ(parameters, *metric->parameters());
159 return metric;
160 }
161
162 RapporMetric* new_metric = new RapporMetric(parameters);
163 metrics_map_[parameters.rappor_name] = new_metric;
164 return new_metric;
165 }
166
167 } // namespace rappor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698