summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chrome_browser_main.cc1
-rw-r--r--chrome/browser/extensions/activity_log/ad_injection_unittest.cc7
-rw-r--r--chrome/browser/metrics/metrics_services_manager.cc2
-rw-r--r--components/components_tests.gyp1
-rw-r--r--components/metrics.gypi2
-rw-r--r--components/metrics/BUILD.gn2
-rw-r--r--components/metrics/daily_event.cc106
-rw-r--r--components/metrics/daily_event.h92
-rw-r--r--components/metrics/daily_event_unittest.cc96
-rw-r--r--components/rappor/rappor_pref_names.cc3
-rw-r--r--components/rappor/rappor_pref_names.h1
-rw-r--r--components/rappor/rappor_service.cc39
-rw-r--r--components/rappor/rappor_service.h42
-rw-r--r--components/rappor/rappor_service_unittest.cc24
-rw-r--r--tools/metrics/histograms/histograms.xml11
15 files changed, 396 insertions, 33 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 14990cf..2a261b9 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -656,7 +656,6 @@ void ChromeBrowserMainParts::StartMetricsRecording() {
// TODO(asvitkine): Since this function is not run on Android, RAPPOR is
// currently disabled there. http://crbug.com/370041
browser_process_->rappor_service()->Start(
- browser_process_->local_state(),
browser_process_->system_request_context(),
metrics_enabled);
}
diff --git a/chrome/browser/extensions/activity_log/ad_injection_unittest.cc b/chrome/browser/extensions/activity_log/ad_injection_unittest.cc
index be2e6c4..d723efc 100644
--- a/chrome/browser/extensions/activity_log/ad_injection_unittest.cc
+++ b/chrome/browser/extensions/activity_log/ad_injection_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/prefs/testing_pref_service.h"
#include "base/time/time.h"
#include "chrome/browser/extensions/activity_log/activity_actions.h"
#include "components/rappor/byte_vector_utils.h"
@@ -42,9 +43,13 @@ class TestRapporService : public rappor::RapporService {
// be from the last time GetReports() was called (not from the beginning of
// the test).
rappor::RapporReports GetReports();
+
+ protected:
+ TestingPrefServiceSimple prefs_;
};
-TestRapporService::TestRapporService() {
+TestRapporService::TestRapporService()
+ : rappor::RapporService(&prefs_) {
// Initialize the RapporService for testing.
SetCohortForTesting(0);
SetSecretForTesting(rappor::HmacByteVectorGenerator::GenerateEntropyInput());
diff --git a/chrome/browser/metrics/metrics_services_manager.cc b/chrome/browser/metrics/metrics_services_manager.cc
index 186bfde..15cae12 100644
--- a/chrome/browser/metrics/metrics_services_manager.cc
+++ b/chrome/browser/metrics/metrics_services_manager.cc
@@ -38,7 +38,7 @@ metrics::MetricsService* MetricsServicesManager::GetMetricsService() {
rappor::RapporService* MetricsServicesManager::GetRapporService() {
DCHECK(thread_checker_.CalledOnValidThread());
if (!rappor_service_)
- rappor_service_.reset(new rappor::RapporService);
+ rappor_service_.reset(new rappor::RapporService(local_state_));
return rappor_service_.get();
}
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index e7733eb..b733649 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -144,6 +144,7 @@
'language_usage_metrics/language_usage_metrics_unittest.cc',
'leveldb_proto/proto_database_impl_unittest.cc',
'metrics/compression_utils_unittest.cc',
+ 'metrics/daily_event_unittest.cc',
'metrics/machine_id_provider_win_unittest.cc',
'metrics/metrics_hashes_unittest.cc',
'metrics/metrics_log_manager_unittest.cc',
diff --git a/components/metrics.gypi b/components/metrics.gypi
index c16c191..1e41f86 100644
--- a/components/metrics.gypi
+++ b/components/metrics.gypi
@@ -26,6 +26,8 @@
'metrics/cloned_install_detector.h',
'metrics/compression_utils.cc',
'metrics/compression_utils.h',
+ 'metrics/daily_event.cc',
+ 'metrics/daily_event.h',
'metrics/machine_id_provider.h',
'metrics/machine_id_provider_stub.cc',
'metrics/machine_id_provider_win.cc',
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn
index 89bedd8..685788c 100644
--- a/components/metrics/BUILD.gn
+++ b/components/metrics/BUILD.gn
@@ -13,6 +13,8 @@ source_set("metrics") {
"cloned_install_detector.h",
"compression_utils.cc",
"compression_utils.h",
+ "daily_event.cc",
+ "daily_event.h",
"machine_id_provider.h",
"machine_id_provider_stub.cc",
"machine_id_provider_win.cc",
diff --git a/components/metrics/daily_event.cc b/components/metrics/daily_event.cc
new file mode 100644
index 0000000..34c3426
--- /dev/null
+++ b/components/metrics/daily_event.cc
@@ -0,0 +1,106 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/metrics/daily_event.h"
+
+#include "base/i18n/time_formatting.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+
+namespace metrics {
+
+namespace {
+
+enum IntervalType {
+ FIRST_RUN,
+ DAY_ELAPSED,
+ CLOCK_CHANGED,
+ NUM_INTERVAL_TYPES
+};
+
+void RecordIntervalTypeHistogram(const std::string& histogram_name,
+ IntervalType type) {
+ base::Histogram::FactoryGet(
+ histogram_name,
+ 1,
+ NUM_INTERVAL_TYPES,
+ NUM_INTERVAL_TYPES + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->Add(type);
+}
+
+} // namespace
+
+DailyEvent::Observer::Observer() {
+}
+
+DailyEvent::Observer::~Observer() {
+}
+
+DailyEvent::DailyEvent(PrefService* pref_service,
+ const char* pref_name,
+ const std::string& histogram_name)
+ : pref_service_(pref_service),
+ pref_name_(pref_name),
+ histogram_name_(histogram_name) {
+}
+
+DailyEvent::~DailyEvent() {
+}
+
+// static
+void DailyEvent::RegisterPref(PrefRegistrySimple* registry,
+ const char* pref_name) {
+ registry->RegisterInt64Pref(pref_name, base::Time().ToInternalValue());
+}
+
+void DailyEvent::AddObserver(scoped_ptr<DailyEvent::Observer> observer) {
+ DVLOG(2) << "DailyEvent observer added.";
+ DCHECK(last_fired_.is_null());
+ observers_.push_back(observer.release());
+}
+
+void DailyEvent::CheckInterval() {
+ base::Time now = base::Time::Now();
+ if (last_fired_.is_null()) {
+ // The first time we call CheckInterval, we read the time stored in prefs.
+ last_fired_ = base::Time::FromInternalValue(
+ pref_service_->GetInt64(pref_name_));
+ DVLOG(1) << "DailyEvent time loaded: "
+ << base::TimeFormatShortDateAndTime(last_fired_);
+ if (last_fired_.is_null()) {
+ DVLOG(1) << "DailyEvent first run.";
+ RecordIntervalTypeHistogram(pref_name_, FIRST_RUN);
+ OnInterval(now);
+ return;
+ }
+ }
+ int days_elapsed = (now - last_fired_).InDays();
+ if (days_elapsed >= 1) {
+ DVLOG(1) << "DailyEvent day elapsed.";
+ RecordIntervalTypeHistogram(pref_name_, DAY_ELAPSED);
+ OnInterval(now);
+ } else if (days_elapsed <= -1) {
+ // The "last fired" time is more than a day in the future, so the clock
+ // must have been changed.
+ DVLOG(1) << "DailyEvent clock change detected.";
+ RecordIntervalTypeHistogram(pref_name_, CLOCK_CHANGED);
+ OnInterval(now);
+ }
+}
+
+void DailyEvent::OnInterval(base::Time now) {
+ DCHECK(!now.is_null());
+ last_fired_ = now;
+ pref_service_->SetInt64(pref_name_, last_fired_.ToInternalValue());
+
+ // Notify all observers
+ for (ScopedVector<DailyEvent::Observer>::iterator it = observers_.begin();
+ it != observers_.end();
+ ++it) {
+ (*it)->OnDailyEvent();
+ }
+}
+
+} // namespace metrics
diff --git a/components/metrics/daily_event.h b/components/metrics/daily_event.h
new file mode 100644
index 0000000..24b31dc
--- /dev/null
+++ b/components/metrics/daily_event.h
@@ -0,0 +1,92 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_METRICS_DAILY_EVENT_H_
+#define COMPONENTS_METRICS_DAILY_EVENT_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/time/time.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace metrics {
+
+// DailyEvent is used for throttling an event to about once per day, even if
+// the program is restarted more frequently. It is based on local machine
+// time, so it could be fired more often if the clock is changed.
+//
+// The service using the DailyEvent should first provide all of the Observers
+// for the interval, and then arrange for CheckInterval() to be called
+// periodically to test if the event should be fired.
+class DailyEvent {
+ public:
+ // Observer receives notifications from a DailyEvent.
+ // Observers must be added before the DailyEvent begins checking time,
+ // and will be owned by the DailyEvent.
+ class Observer {
+ public:
+ Observer();
+ virtual ~Observer();
+
+ // Called when the daily event is fired.
+ virtual void OnDailyEvent() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Observer);
+ };
+
+ // Constructs DailyEvent monitor which stores the time it last fired in the
+ // preference |pref_name|. |pref_name| should be registered by calling
+ // RegisterPref before using this object.
+ // Caller is responsible for ensuring that |pref_service| and |pref_name|
+ // outlive the DailyEvent.
+ // |histogram_name| is the name of the UMA metric which record when this
+ // interval fires, and should be registered in histograms.xml
+ DailyEvent(PrefService* pref_service,
+ const char* pref_name,
+ const std::string& histogram_name);
+ ~DailyEvent();
+
+ // Adds a observer to be notified when a day elapses. All observers should
+ // be registered before the the DailyEvent starts checking time.
+ void AddObserver(scoped_ptr<Observer> observer);
+
+ // Checks if a day has elapsed. If it has, OnDailyEvent will be called on
+ // all observers.
+ void CheckInterval();
+
+ // Registers the preference used by this interval.
+ static void RegisterPref(PrefRegistrySimple* registry, const char* pref_name);
+
+ private:
+ // Handles an interval elapsing.
+ void OnInterval(base::Time now);
+
+ // A weak pointer to the PrefService object to read and write preferences
+ // from. Calling code should ensure this object continues to exist for the
+ // lifetime of the DailyEvent object.
+ PrefService* pref_service_;
+
+ // The name of the preference to store the last fired time in.
+ // Calling code should ensure this outlives the DailyEvent.
+ const char* pref_name_;
+
+ // The name of the histogram to record intervals.
+ std::string histogram_name_;
+
+ // A list of observers.
+ ScopedVector<Observer> observers_;
+
+ // The time that the daily event was last fired.
+ base::Time last_fired_;
+
+ DISALLOW_COPY_AND_ASSIGN(DailyEvent);
+};
+
+} // namespace metrics
+
+#endif // COMPONENTS_METRICS_DAILY_EVENT_H_
diff --git a/components/metrics/daily_event_unittest.cc b/components/metrics/daily_event_unittest.cc
new file mode 100644
index 0000000..4253c13
--- /dev/null
+++ b/components/metrics/daily_event_unittest.cc
@@ -0,0 +1,96 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/metrics/daily_event.h"
+
+#include "base/prefs/testing_pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace metrics {
+
+namespace {
+
+const char kTestPrefName[] = "TestPref";
+const char kTestMetricName[] = "TestMetric";
+
+class TestDailyObserver : public DailyEvent::Observer {
+ public:
+ TestDailyObserver() : fired_(false) {}
+
+ bool fired() const { return fired_; }
+
+ virtual void OnDailyEvent() OVERRIDE {
+ fired_ = true;
+ }
+
+ void Reset() {
+ fired_ = false;
+ }
+
+ private:
+ // True if this event has been observed.
+ bool fired_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDailyObserver);
+};
+
+class DailyEventTest : public testing::Test {
+ public:
+ DailyEventTest() : event_(&prefs_, kTestPrefName, kTestMetricName) {
+ DailyEvent::RegisterPref(prefs_.registry(), kTestPrefName);
+ observer_ = new TestDailyObserver();
+ scoped_ptr<metrics::DailyEvent::Observer> p(observer_);
+ event_.AddObserver(p.Pass());
+ }
+
+ protected:
+ TestingPrefServiceSimple prefs_;
+ TestDailyObserver* observer_;
+ DailyEvent event_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DailyEventTest);
+};
+
+} // namespace
+
+// The event should fire if the preference is not available.
+TEST_F(DailyEventTest, TestNewFires) {
+ event_.CheckInterval();
+ EXPECT_TRUE(observer_->fired());
+}
+
+// The event should fire if the preference is more than a day old.
+TEST_F(DailyEventTest, TestOldFires) {
+ base::Time last_time = base::Time::Now() - base::TimeDelta::FromHours(25);
+ prefs_.SetInt64(kTestPrefName, last_time.ToInternalValue());
+ event_.CheckInterval();
+ EXPECT_TRUE(observer_->fired());
+}
+
+// The event should fire if the preference is more than a day in the future.
+TEST_F(DailyEventTest, TestFutureFires) {
+ base::Time last_time = base::Time::Now() + base::TimeDelta::FromHours(25);
+ prefs_.SetInt64(kTestPrefName, last_time.ToInternalValue());
+ event_.CheckInterval();
+ EXPECT_TRUE(observer_->fired());
+}
+
+// The event should not fire if the preference is more recent than a day.
+TEST_F(DailyEventTest, TestRecentNotFired) {
+ base::Time last_time = base::Time::Now() - base::TimeDelta::FromMinutes(2);
+ prefs_.SetInt64(kTestPrefName, last_time.ToInternalValue());
+ event_.CheckInterval();
+ EXPECT_FALSE(observer_->fired());
+}
+
+// The event should not fire if the preference is less than a day in the future.
+TEST_F(DailyEventTest, TestSoonNotFired) {
+ base::Time last_time = base::Time::Now() + base::TimeDelta::FromMinutes(2);
+ prefs_.SetInt64(kTestPrefName, last_time.ToInternalValue());
+ event_.CheckInterval();
+ EXPECT_FALSE(observer_->fired());
+}
+
+} // namespace metrics
diff --git a/components/rappor/rappor_pref_names.cc b/components/rappor/rappor_pref_names.cc
index ff444ef..b879c4b 100644
--- a/components/rappor/rappor_pref_names.cc
+++ b/components/rappor/rappor_pref_names.cc
@@ -13,6 +13,9 @@ const char kRapporCohortDeprecated[] = "rappor.cohort";
// A randomly generated number, which determines cohorts data is reported for.
const char kRapporCohortSeed[] = "rappor.cohort_seed";
+// Timestamp of the last time we sampled daily metrics.
+const char kRapporLastDailySample[] = "rappor.last_daily_sample";
+
// A base-64 encoded, randomly generated byte string, which is used as a seed
// for redacting collected data.
// Important: This value should remain secret at the client, and never be
diff --git a/components/rappor/rappor_pref_names.h b/components/rappor/rappor_pref_names.h
index 9cb60ca..06ea8d5 100644
--- a/components/rappor/rappor_pref_names.h
+++ b/components/rappor/rappor_pref_names.h
@@ -12,6 +12,7 @@ namespace prefs {
// component. Keep alphabetized, and document each in the .cc file.
extern const char kRapporCohortDeprecated[];
extern const char kRapporCohortSeed[];
+extern const char kRapporLastDailySample[];
extern const char kRapporSecret[];
} // namespace prefs
diff --git a/components/rappor/rappor_service.cc b/components/rappor/rappor_service.cc
index 6ca64b7..11419f5 100644
--- a/components/rappor/rappor_service.cc
+++ b/components/rappor/rappor_service.cc
@@ -29,6 +29,8 @@ const int kLogIntervalSeconds = 30 * 60;
const char kMimeType[] = "application/vnd.chrome.rappor";
+const char kRapporDailyEventHistogram[] = "Rappor.DailyEvent.IntervalType";
+
// Constants for the RAPPOR rollout field trial.
const char kRapporRolloutFieldTrialName[] = "RapporRollout";
@@ -69,14 +71,24 @@ const RapporParameters kRapporParametersForType[NUM_RAPPOR_TYPES] = {
} // namespace
-RapporService::RapporService() : cohort_(-1) {}
+RapporService::RapporService(PrefService* pref_service)
+ : pref_service_(pref_service),
+ cohort_(-1),
+ daily_event_(pref_service,
+ prefs::kRapporLastDailySample,
+ kRapporDailyEventHistogram) {
+}
RapporService::~RapporService() {
STLDeleteValues(&metrics_map_);
}
-void RapporService::Start(PrefService* pref_service,
- net::URLRequestContextGetter* request_context,
+void RapporService::AddDailyObserver(
+ scoped_ptr<metrics::DailyEvent::Observer> observer) {
+ daily_event_.AddObserver(observer.Pass());
+}
+
+void RapporService::Start(net::URLRequestContextGetter* request_context,
bool metrics_enabled) {
const GURL server_url = GetServerUrl(metrics_enabled);
if (!server_url.is_valid()) {
@@ -86,8 +98,8 @@ void RapporService::Start(PrefService* pref_service,
}
DVLOG(1) << "RapporService started. Reporting to " << server_url.spec();
DCHECK(!uploader_);
- LoadSecret(pref_service);
- LoadCohort(pref_service);
+ LoadSecret();
+ LoadCohort();
uploader_.reset(new LogUploader(server_url, kMimeType, request_context));
log_rotation_timer_.Start(
FROM_HERE,
@@ -99,6 +111,7 @@ void RapporService::Start(PrefService* pref_service,
void RapporService::OnLogInterval() {
DCHECK(uploader_);
DVLOG(2) << "RapporService::OnLogInterval";
+ daily_event_.CheckInterval();
RapporReports reports;
if (ExportMetrics(&reports)) {
std::string log_text;
@@ -119,14 +132,16 @@ void RapporService::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kRapporSecret, std::string());
registry->RegisterIntegerPref(prefs::kRapporCohortDeprecated, -1);
registry->RegisterIntegerPref(prefs::kRapporCohortSeed, -1);
+ metrics::DailyEvent::RegisterPref(registry,
+ prefs::kRapporLastDailySample);
}
-void RapporService::LoadCohort(PrefService* pref_service) {
+void RapporService::LoadCohort() {
DCHECK(!IsInitialized());
// Ignore and delete old cohort parameter.
- pref_service->ClearPref(prefs::kRapporCohortDeprecated);
+ pref_service_->ClearPref(prefs::kRapporCohortDeprecated);
- cohort_ = pref_service->GetInteger(prefs::kRapporCohortSeed);
+ cohort_ = pref_service_->GetInteger(prefs::kRapporCohortSeed);
// If the user is already assigned to a valid cohort, we're done.
if (cohort_ >= 0 && cohort_ < RapporParameters::kMaxCohorts)
return;
@@ -135,12 +150,12 @@ void RapporService::LoadCohort(PrefService* pref_service) {
// preferences were corrupted). Randomly assign them to a cohort.
cohort_ = base::RandGenerator(RapporParameters::kMaxCohorts);
DVLOG(2) << "Selected a new Rappor cohort: " << cohort_;
- pref_service->SetInteger(prefs::kRapporCohortSeed, cohort_);
+ pref_service_->SetInteger(prefs::kRapporCohortSeed, cohort_);
}
-void RapporService::LoadSecret(PrefService* pref_service) {
+void RapporService::LoadSecret() {
DCHECK(secret_.empty());
- std::string secret_base64 = pref_service->GetString(prefs::kRapporSecret);
+ std::string secret_base64 = pref_service_->GetString(prefs::kRapporSecret);
if (!secret_base64.empty()) {
bool decoded = base::Base64Decode(secret_base64, &secret_);
if (decoded && secret_.size() == HmacByteVectorGenerator::kEntropyInputSize)
@@ -153,7 +168,7 @@ void RapporService::LoadSecret(PrefService* pref_service) {
DVLOG(2) << "Generated a new Rappor secret.";
secret_ = HmacByteVectorGenerator::GenerateEntropyInput();
base::Base64Encode(secret_, &secret_base64);
- pref_service->SetString(prefs::kRapporSecret, secret_base64);
+ pref_service_->SetString(prefs::kRapporSecret, secret_base64);
}
bool RapporService::ExportMetrics(RapporReports* reports) {
diff --git a/components/rappor/rappor_service.h b/components/rappor/rappor_service.h
index f02a85a..b48c31c 100644
--- a/components/rappor/rappor_service.h
+++ b/components/rappor/rappor_service.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
+#include "components/metrics/daily_event.h"
class PrefRegistrySimple;
class PrefService;
@@ -38,12 +39,17 @@ enum RapporType {
// and periodically generates and uploads reports based on the collected data.
class RapporService {
public:
- RapporService();
+ // Constructs a RapporService.
+ // Calling code is responsible for ensuring that the lifetime of
+ // |pref_service| is longer than the lifetime of RapporService.
+ explicit RapporService(PrefService* pref_service);
virtual ~RapporService();
+ // Add an observer for collecting daily metrics.
+ void AddDailyObserver(scoped_ptr<metrics::DailyEvent::Observer> observer);
+
// Starts the periodic generation of reports and upload attempts.
- void Start(PrefService* pref_service,
- net::URLRequestContextGetter* context,
+ void Start(net::URLRequestContextGetter* context,
bool metrics_enabled);
// Records a sample of the rappor metric specified by |metric_name|.
@@ -52,10 +58,10 @@ class RapporService {
RapporType type,
const std::string& sample);
- // Sets the cohort value. For use by tests only.
+ // Sets the cohort value. For use by tests only.
void SetCohortForTesting(uint32_t cohort) { cohort_ = cohort; }
- // Sets the secret value. For use by tests only.
+ // Sets the secret value. For use by tests only.
void SetSecretForTesting(const std::string& secret) { secret_ = secret; }
// Registers the names of all of the preferences used by RapporService in the
@@ -63,8 +69,17 @@ class RapporService {
static void RegisterPrefs(PrefRegistrySimple* registry);
protected:
+ // Retrieves the cohort number this client was assigned to, generating it if
+ // doesn't already exist. The cohort should be persistent.
+ void LoadCohort();
+
+ // Retrieves the value for secret_ from preferences, generating it if doesn't
+ // already exist. The secret should be persistent, so that additional bits
+ // from the client do not get exposed over time.
+ void LoadSecret();
+
// Logs all of the collected metrics to the reports proto message and clears
- // the internal map. Exposed for tests. Returns true if any metrics were
+ // the internal map. Exposed for tests. Returns true if any metrics were
// recorded.
bool ExportMetrics(RapporReports* reports);
@@ -79,15 +94,6 @@ class RapporService {
// Check if the service has been started successfully.
bool IsInitialized() const;
- // Retrieves the cohort number this client was assigned to, generating it if
- // doesn't already exist. The cohort should be persistent.
- void LoadCohort(PrefService* pref_service);
-
- // Retrieves the value for secret_ from preferences, generating it if doesn't
- // already exist. The secret should be persistent, so that additional bits
- // from the client do not get exposed over time.
- void LoadSecret(PrefService* pref_service);
-
// Called whenever the logging interval elapses to generate a new log of
// reports and pass it to the uploader.
void OnLogInterval();
@@ -97,6 +103,9 @@ class RapporService {
RapporMetric* LookUpMetric(const std::string& metric_name,
const RapporParameters& parameters);
+ // A weak pointer to the PrefService used to read and write preferences.
+ PrefService* pref_service_;
+
// Client-side secret used to generate fake bits.
std::string secret_;
@@ -106,6 +115,9 @@ class RapporService {
// Timer which schedules calls to OnLogInterval().
base::OneShotTimer<RapporService> log_rotation_timer_;
+ // A daily event for collecting metrics once a day.
+ metrics::DailyEvent daily_event_;
+
// A private LogUploader instance for sending reports to the server.
scoped_ptr<LogUploader> uploader_;
diff --git a/components/rappor/rappor_service_unittest.cc b/components/rappor/rappor_service_unittest.cc
index a91db8c..4430ee3 100644
--- a/components/rappor/rappor_service_unittest.cc
+++ b/components/rappor/rappor_service_unittest.cc
@@ -4,23 +4,44 @@
#include "components/rappor/rappor_service.h"
+#include "base/base64.h"
+#include "base/prefs/testing_pref_service.h"
#include "components/rappor/byte_vector_utils.h"
#include "components/rappor/proto/rappor_metric.pb.h"
#include "components/rappor/rappor_parameters.h"
+#include "components/rappor/rappor_pref_names.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace rappor {
class TestRapporService : public RapporService {
public:
+ TestRapporService() : RapporService(&prefs_) {
+ RegisterPrefs(prefs_.registry());
+ prefs_.SetInteger(prefs::kRapporCohortSeed, 0);
+ std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
+ std::string secret_base64;
+ base::Base64Encode(secret, &secret_base64);
+ prefs_.SetString(prefs::kRapporSecret, secret_base64);
+ LoadCohort();
+ LoadSecret();
+ }
+
void GetReports(RapporReports* reports) {
ExportMetrics(reports);
}
+
void TestRecordSample(const std::string& metric_name,
const RapporParameters& parameters,
const std::string& sample) {
RecordSampleInternal(metric_name, parameters, sample);
}
+
+ protected:
+ TestingPrefServiceSimple prefs_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestRapporService);
};
TEST(RapporServiceTest, RecordAndExportMetrics) {
@@ -34,9 +55,6 @@ TEST(RapporServiceTest, RecordAndExportMetrics) {
PROBABILITY_50 /* Zero coin probability */};
TestRapporService rappor_service;
- rappor_service.SetCohortForTesting(0);
- rappor_service.SetSecretForTesting(
- HmacByteVectorGenerator::GenerateEntropyInput());
rappor_service.TestRecordSample("MyMetric", kTestRapporParameters, "foo");
rappor_service.TestRecordSample("MyMetric", kTestRapporParameters, "bar");
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b3b3c0e..ec7c7a3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -26389,6 +26389,11 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</summary>
</histogram>
+<histogram name="Rappor.DailyEvent.IntervalType" enum="DailyEventIntervalType">
+ <owner>holte@chromium.org</owner>
+ <summary>Counts how often daily interval events were fired.</summary>
+</histogram>
+
<histogram name="Rappor.DiscardReason" enum="RapporDiscardReason">
<owner>holte@chromium.org</owner>
<summary>
@@ -39465,6 +39470,12 @@ Therefore, the affected-histogram name has to have at least one dot in it.
<int value="8" label="PlayMusic"/>
</enum>
+<enum name="DailyEventIntervalType" type="int">
+ <int value="0" label="First Run"/>
+ <int value="1" label="Day Elapsed"/>
+ <int value="2" label="Clock Changed"/>
+</enum>
+
<enum name="DataChannelCounters" type="int">
<int value="0" label="Channel created."/>
<int value="1" label="Channel reached Open state."/>