1 // Copyright (c) 2012 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 CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__ 6 #define CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/memory/weak_ptr.h" 13 #include "base/timer/timer.h" 14 #include "chrome/browser/extensions/api/profile_keyed_api_factory.h" 15 #include "chrome/browser/extensions/extension_function.h" 16 #include "chrome/common/extensions/api/alarms.h" 17 #include "content/public/browser/notification_observer.h" 18 #include "content/public/browser/notification_registrar.h" 19 20 class Profile; 21 22 namespace base { 23 class Clock; 24 } // namespace base 25 26 namespace extensions { 27 28 class ExtensionAlarmsSchedulingTest; 29 30 struct Alarm { 31 Alarm(); 32 Alarm(const std::string& name, 33 const api::alarms::AlarmCreateInfo& create_info, 34 base::TimeDelta min_granularity, 35 base::Time now); 36 ~Alarm(); 37 38 linked_ptr<api::alarms::Alarm> js_alarm; 39 // The granularity isn't exposed to the extension's javascript, but we poll at 40 // least as often as the shortest alarm's granularity. It's initialized as 41 // the relative delay requested in creation, even if creation uses an absolute 42 // time. This will always be at least as large as the min_granularity 43 // constructor argument. 44 base::TimeDelta granularity; 45 }; 46 47 // Manages the currently pending alarms for every extension in a profile. 48 // There is one manager per virtual Profile. 49 class AlarmManager 50 : public ProfileKeyedAPI, 51 public content::NotificationObserver, 52 public base::SupportsWeakPtr<AlarmManager> { 53 public: 54 typedef std::vector<Alarm> AlarmList; 55 56 class Delegate { 57 public: 58 virtual ~Delegate() {} 59 // Called when an alarm fires. 60 virtual void OnAlarm(const std::string& extension_id, 61 const Alarm& alarm) = 0; 62 }; 63 64 explicit AlarmManager(Profile* profile); 65 virtual ~AlarmManager(); 66 67 // Override the default delegate. Callee assumes onwership. Used for testing. 68 void set_delegate(Delegate* delegate) { delegate_.reset(delegate); } 69 70 // Adds |alarm| for the given extension, and starts the timer. 71 void AddAlarm(const std::string& extension_id, 72 const Alarm& alarm); 73 74 // Returns the alarm with the given name, or NULL if none exists. 75 const Alarm* GetAlarm(const std::string& extension_id, 76 const std::string& name); 77 78 // Returns the list of pending alarms for the given extension, or NULL 79 // if none exist. 80 const AlarmList* GetAllAlarms(const std::string& extension_id); 81 82 // Cancels and removes the alarm with the given name. 83 bool RemoveAlarm(const std::string& extension_id, 84 const std::string& name); 85 86 // Cancels and removes all alarms for the given extension. 87 void RemoveAllAlarms(const std::string& extension_id); 88 89 // Replaces AlarmManager's owned clock with |clock| and takes ownership of it. 90 void SetClockForTesting(base::Clock* clock); 91 92 // ProfileKeyedAPI implementation. 93 static ProfileKeyedAPIFactory<AlarmManager>* GetFactoryInstance(); 94 95 // Convenience method to get the AlarmManager for a profile. 96 static AlarmManager* Get(Profile* profile); 97 98 private: 99 FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsTest, CreateRepeating); 100 FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsTest, Clear); 101 friend class ExtensionAlarmsSchedulingTest; 102 FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsSchedulingTest, PollScheduling); 103 FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsSchedulingTest, 104 ReleasedExtensionPollsInfrequently); 105 FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsSchedulingTest, TimerRunning); 106 friend class ProfileKeyedAPIFactory<AlarmManager>; 107 108 typedef std::string ExtensionId; 109 typedef std::map<ExtensionId, AlarmList> AlarmMap; 110 111 // Iterator used to identify a particular alarm within the Map/List pair. 112 // "Not found" is represented by <alarms_.end(), invalid_iterator>. 113 typedef std::pair<AlarmMap::iterator, AlarmList::iterator> AlarmIterator; 114 115 // Helper to return the iterators within the AlarmMap and AlarmList for the 116 // matching alarm, or an iterator to the end of the AlarmMap if none were 117 // found. 118 AlarmIterator GetAlarmIterator(const std::string& extension_id, 119 const std::string& name); 120 121 // Helper to cancel and remove the alarm at the given iterator. The iterator 122 // must be valid. 123 void RemoveAlarmIterator(const AlarmIterator& iter); 124 125 // Callback for when an alarm fires. 126 void OnAlarm(AlarmIterator iter); 127 128 // Internal helper to add an alarm and start the timer with the given delay. 129 void AddAlarmImpl(const std::string& extension_id, 130 const Alarm& alarm); 131 132 // Syncs our alarm data for the given extension to/from the state storage. 133 void WriteToStorage(const std::string& extension_id); 134 void ReadFromStorage(const std::string& extension_id, 135 scoped_ptr<base::Value> value); 136 137 // Schedules the next poll of alarms for when the next soonest alarm runs, 138 // but not more often than the minimum granularity of all alarms. 139 void ScheduleNextPoll(); 140 141 // Polls the alarms, running any that have elapsed. After running them and 142 // rescheduling repeating alarms, schedule the next poll. 143 void PollAlarms(); 144 145 // NotificationObserver: 146 virtual void Observe(int type, 147 const content::NotificationSource& source, 148 const content::NotificationDetails& details) OVERRIDE; 149 150 // ProfileKeyedAPI implementation. 151 static const char* service_name() { 152 return "AlarmManager"; 153 } 154 static const bool kServiceHasOwnInstanceInIncognito = true; 155 156 Profile* const profile_; 157 scoped_ptr<base::Clock> clock_; 158 content::NotificationRegistrar registrar_; 159 scoped_ptr<Delegate> delegate_; 160 161 // The timer for this alarm manager. 162 base::OneShotTimer<AlarmManager> timer_; 163 164 // A map of our pending alarms, per extension. 165 // Invariant: None of the AlarmLists are empty. 166 AlarmMap alarms_; 167 168 // The previous and next time that alarms were and will be run. 169 base::Time last_poll_time_; 170 base::Time next_poll_time_; 171 172 DISALLOW_COPY_AND_ASSIGN(AlarmManager); 173 }; 174 175 } // namespace extensions 176 177 #endif // CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__ 178