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 #ifndef COMPONENTS_METRICS_DAILY_EVENT_H_
6 #define COMPONENTS_METRICS_DAILY_EVENT_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/macros.h"
12 #include "base/time/time.h"
13 
14 class PrefRegistrySimple;
15 class PrefService;
16 
17 namespace metrics {
18 
19 // DailyEvent is used for throttling an event to about once per day, even if
20 // the program is restarted more frequently.  It is based on local machine
21 // time, so it could be fired more often if the clock is changed.
22 //
23 // The service using the DailyEvent should first provide all of the Observers
24 // for the interval, and then arrange for CheckInterval() to be called
25 // periodically to test if the event should be fired.
26 class DailyEvent {
27  public:
28   // Different reasons that Observer::OnDailyEvent() is called.
29   // This enum is used for histograms and must not be renumbered.
30   enum class IntervalType {
31     FIRST_RUN,
32     DAY_ELAPSED,
33     CLOCK_CHANGED,
34     NUM_TYPES,
35   };
36 
37   // Observer receives notifications from a DailyEvent.
38   // Observers must be added before the DailyEvent begins checking time,
39   // and will be owned by the DailyEvent.
40   class Observer {
41    public:
42     Observer();
43     virtual ~Observer();
44 
45     // Called when the daily event is fired.
46     virtual void OnDailyEvent(IntervalType type) = 0;
47 
48    private:
49     DISALLOW_COPY_AND_ASSIGN(Observer);
50   };
51 
52   // Constructs DailyEvent monitor which stores the time it last fired in the
53   // preference |pref_name|. |pref_name| should be registered by calling
54   // RegisterPref before using this object.
55   // Caller is responsible for ensuring that |pref_service| and |pref_name|
56   // outlive the DailyEvent.
57   // |histogram_name| is the name of the UMA metric which record when this
58   // interval fires, and should be registered in histograms.xml
59   DailyEvent(PrefService* pref_service,
60              const char* pref_name,
61              const std::string& histogram_name);
62   ~DailyEvent();
63 
64   // Adds a observer to be notified when a day elapses. All observers should
65   // be registered before the the DailyEvent starts checking time.
66   void AddObserver(std::unique_ptr<Observer> observer);
67 
68   // Checks if a day has elapsed. If it has, OnDailyEvent will be called on
69   // all observers.
70   void CheckInterval();
71 
72   // Registers the preference used by this interval.
73   static void RegisterPref(PrefRegistrySimple* registry, const char* pref_name);
74 
75  private:
76   // Handles an interval elapsing because of |type|.
77   void OnInterval(base::Time now, IntervalType type);
78 
79   // A weak pointer to the PrefService object to read and write preferences
80   // from. Calling code should ensure this object continues to exist for the
81   // lifetime of the DailyEvent object.
82   PrefService* pref_service_;
83 
84   // The name of the preference to store the last fired time in.
85   // Calling code should ensure this outlives the DailyEvent.
86   const char* pref_name_;
87 
88   // The name of the histogram to record intervals.
89   std::string histogram_name_;
90 
91   // A list of observers.
92   std::vector<std::unique_ptr<Observer>> observers_;
93 
94   // The time that the daily event was last fired.
95   base::Time last_fired_;
96 
97   DISALLOW_COPY_AND_ASSIGN(DailyEvent);
98 };
99 
100 }  // namespace metrics
101 
102 #endif  // COMPONENTS_METRICS_DAILY_EVENT_H_
103