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/metrics/daily_event.h"
6
7 #include <utility>
8
9 #include "base/metrics/histogram.h"
10 #include "components/prefs/pref_registry_simple.h"
11 #include "components/prefs/pref_service.h"
12
13 namespace metrics {
14
15 namespace {
16
RecordIntervalTypeHistogram(const std::string & histogram_name,DailyEvent::IntervalType type)17 void RecordIntervalTypeHistogram(const std::string& histogram_name,
18 DailyEvent::IntervalType type) {
19 const int num_types = static_cast<int>(DailyEvent::IntervalType::NUM_TYPES);
20 base::Histogram::FactoryGet(histogram_name, 1, num_types, num_types + 1,
21 base::HistogramBase::kUmaTargetedHistogramFlag)
22 ->Add(static_cast<int>(type));
23 }
24
25 } // namespace
26
Observer()27 DailyEvent::Observer::Observer() {
28 }
29
~Observer()30 DailyEvent::Observer::~Observer() {
31 }
32
DailyEvent(PrefService * pref_service,const char * pref_name,const std::string & histogram_name)33 DailyEvent::DailyEvent(PrefService* pref_service,
34 const char* pref_name,
35 const std::string& histogram_name)
36 : pref_service_(pref_service),
37 pref_name_(pref_name),
38 histogram_name_(histogram_name) {
39 }
40
~DailyEvent()41 DailyEvent::~DailyEvent() {
42 }
43
44 // static
RegisterPref(PrefRegistrySimple * registry,const char * pref_name)45 void DailyEvent::RegisterPref(PrefRegistrySimple* registry,
46 const char* pref_name) {
47 registry->RegisterInt64Pref(pref_name, 0);
48 }
49
AddObserver(std::unique_ptr<DailyEvent::Observer> observer)50 void DailyEvent::AddObserver(std::unique_ptr<DailyEvent::Observer> observer) {
51 DVLOG(2) << "DailyEvent observer added.";
52 DCHECK(last_fired_.is_null());
53 observers_.push_back(std::move(observer));
54 }
55
CheckInterval()56 void DailyEvent::CheckInterval() {
57 base::Time now = base::Time::Now();
58 if (last_fired_.is_null()) {
59 // The first time we call CheckInterval, we read the time stored in prefs.
60 last_fired_ = base::Time() + base::TimeDelta::FromMicroseconds(
61 pref_service_->GetInt64(pref_name_));
62
63 DVLOG(1) << "DailyEvent time loaded: " << last_fired_;
64 if (last_fired_.is_null()) {
65 DVLOG(1) << "DailyEvent first run.";
66 RecordIntervalTypeHistogram(histogram_name_, IntervalType::FIRST_RUN);
67 OnInterval(now, IntervalType::FIRST_RUN);
68 return;
69 }
70 }
71 int days_elapsed = (now - last_fired_).InDays();
72 if (days_elapsed >= 1) {
73 DVLOG(1) << "DailyEvent day elapsed.";
74 RecordIntervalTypeHistogram(histogram_name_, IntervalType::DAY_ELAPSED);
75 OnInterval(now, IntervalType::DAY_ELAPSED);
76 } else if (days_elapsed <= -1) {
77 // The "last fired" time is more than a day in the future, so the clock
78 // must have been changed.
79 DVLOG(1) << "DailyEvent clock change detected.";
80 RecordIntervalTypeHistogram(histogram_name_, IntervalType::CLOCK_CHANGED);
81 OnInterval(now, IntervalType::CLOCK_CHANGED);
82 }
83 }
84
OnInterval(base::Time now,IntervalType type)85 void DailyEvent::OnInterval(base::Time now, IntervalType type) {
86 DCHECK(!now.is_null());
87 last_fired_ = now;
88 pref_service_->SetInt64(pref_name_,
89 last_fired_.since_origin().InMicroseconds());
90
91 for (auto it = observers_.begin(); it != observers_.end(); ++it) {
92 (*it)->OnDailyEvent(type);
93 }
94 }
95
96 } // namespace metrics
97