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