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