OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/alarms/alarm_manager.h" | 5 #include "chrome/browser/extensions/api/alarms/alarm_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "chrome/browser/extensions/extension_event_router.h" | 11 #include "chrome/browser/extensions/extension_event_router.h" |
| 12 #include "chrome/browser/extensions/extension_prefs.h" |
| 13 #include "chrome/browser/extensions/extension_service.h" |
12 #include "chrome/browser/extensions/extension_system.h" | 14 #include "chrome/browser/extensions/extension_system.h" |
13 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/common/chrome_notification_types.h" |
| 17 #include "content/public/browser/notification_service.h" |
14 | 18 |
15 namespace extensions { | 19 namespace extensions { |
16 | 20 |
17 namespace { | 21 namespace { |
18 | 22 |
19 const char kOnAlarmEvent[] = "experimental.alarms.onAlarm"; | 23 const char kOnAlarmEvent[] = "experimental.alarms.onAlarm"; |
20 | 24 |
21 class DefaultAlarmDelegate : public AlarmManager::Delegate { | 25 class DefaultAlarmDelegate : public AlarmManager::Delegate { |
22 public: | 26 public: |
23 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} | 27 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} |
(...skipping 11 matching lines...) Expand all Loading... |
35 | 39 |
36 private: | 40 private: |
37 Profile* profile_; | 41 Profile* profile_; |
38 }; | 42 }; |
39 | 43 |
40 } | 44 } |
41 | 45 |
42 AlarmManager::AlarmManager(Profile* profile) | 46 AlarmManager::AlarmManager(Profile* profile) |
43 : profile_(profile), | 47 : profile_(profile), |
44 delegate_(new DefaultAlarmDelegate(profile)) { | 48 delegate_(new DefaultAlarmDelegate(profile)) { |
| 49 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| 50 content::Source<Profile>(profile_)); |
45 } | 51 } |
46 | 52 |
47 AlarmManager::~AlarmManager() { | 53 AlarmManager::~AlarmManager() { |
48 } | 54 } |
49 | 55 |
50 void AlarmManager::AddAlarm(const std::string& extension_id, | 56 void AlarmManager::AddAlarm(const std::string& extension_id, |
51 const linked_ptr<Alarm>& alarm) { | 57 const linked_ptr<Alarm>& alarm) { |
52 // TODO(mpcomplete): Better handling of granularity. | 58 AddAlarmImpl(extension_id, alarm, |
53 // http://crbug.com/122683 | 59 base::TimeDelta::FromSeconds(alarm->delay_in_seconds)); |
54 | 60 WriteToPrefs(extension_id); |
55 // Override any old alarm with the same name. | |
56 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name); | |
57 if (old_alarm.first != alarms_.end()) | |
58 RemoveAlarmIterator(old_alarm); | |
59 | |
60 alarms_[extension_id].push_back(alarm); | |
61 base::Timer* timer = new base::Timer(true, alarm->repeating); | |
62 timers_[alarm.get()] = make_linked_ptr(timer); | |
63 timer->Start(FROM_HERE, | |
64 base::TimeDelta::FromSeconds(alarm->delay_in_seconds), | |
65 base::Bind(&AlarmManager::OnAlarm, base::Unretained(this), | |
66 extension_id, alarm->name)); | |
67 } | 61 } |
68 | 62 |
69 const AlarmManager::Alarm* AlarmManager::GetAlarm( | 63 const AlarmManager::Alarm* AlarmManager::GetAlarm( |
70 const std::string& extension_id, const std::string& name) { | 64 const std::string& extension_id, const std::string& name) { |
71 AlarmIterator it = GetAlarmIterator(extension_id, name); | 65 AlarmIterator it = GetAlarmIterator(extension_id, name); |
72 if (it.first == alarms_.end()) | 66 if (it.first == alarms_.end()) |
73 return NULL; | 67 return NULL; |
74 return it.second->get(); | 68 return it.second->get(); |
75 } | 69 } |
76 | 70 |
(...skipping 18 matching lines...) Expand all Loading... |
95 } | 89 } |
96 | 90 |
97 return make_pair(alarms_.end(), AlarmList::iterator()); | 91 return make_pair(alarms_.end(), AlarmList::iterator()); |
98 } | 92 } |
99 | 93 |
100 bool AlarmManager::RemoveAlarm(const std::string& extension_id, | 94 bool AlarmManager::RemoveAlarm(const std::string& extension_id, |
101 const std::string& name) { | 95 const std::string& name) { |
102 AlarmIterator it = GetAlarmIterator(extension_id, name); | 96 AlarmIterator it = GetAlarmIterator(extension_id, name); |
103 if (it.first == alarms_.end()) | 97 if (it.first == alarms_.end()) |
104 return false; | 98 return false; |
| 99 |
105 RemoveAlarmIterator(it); | 100 RemoveAlarmIterator(it); |
| 101 WriteToPrefs(extension_id); |
106 return true; | 102 return true; |
107 } | 103 } |
108 | 104 |
109 void AlarmManager::RemoveAllAlarms(const std::string& extension_id) { | 105 void AlarmManager::RemoveAllAlarms(const std::string& extension_id) { |
110 AlarmMap::iterator list = alarms_.find(extension_id); | 106 AlarmMap::iterator list = alarms_.find(extension_id); |
111 if (list == alarms_.end()) | 107 if (list == alarms_.end()) |
112 return; | 108 return; |
113 | 109 |
114 // Note: I'm using indices rather than iterators here because | 110 // Note: I'm using indices rather than iterators here because |
115 // RemoveAlarmIterator will delete the list when it becomes empty. | 111 // RemoveAlarmIterator will delete the list when it becomes empty. |
116 for (size_t i = 0, size = list->second.size(); i < size; ++i) | 112 for (size_t i = 0, size = list->second.size(); i < size; ++i) |
117 RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); | 113 RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); |
118 | 114 |
119 CHECK(alarms_.find(extension_id) == alarms_.end()); | 115 CHECK(alarms_.find(extension_id) == alarms_.end()); |
| 116 WriteToPrefs(extension_id); |
120 } | 117 } |
121 | 118 |
122 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { | 119 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { |
123 // Cancel the timer first. | 120 // Cancel the timer first. |
124 timers_[iter.second->get()]->Stop(); | 121 timers_[iter.second->get()]->Stop(); |
125 timers_.erase(iter.second->get()); | 122 timers_.erase(iter.second->get()); |
126 | 123 |
127 // Clean up our alarm list. | 124 // Clean up our alarm list. |
128 AlarmList& list = iter.first->second; | 125 AlarmList& list = iter.first->second; |
129 list.erase(iter.second); | 126 list.erase(iter.second); |
130 if (list.empty()) | 127 if (list.empty()) |
131 alarms_.erase(iter.first); | 128 alarms_.erase(iter.first); |
132 } | 129 } |
133 | 130 |
134 void AlarmManager::OnAlarm(const std::string& extension_id, | 131 void AlarmManager::OnAlarm(const std::string& extension_id, |
135 const std::string& name) { | 132 const std::string& name) { |
136 AlarmIterator it = GetAlarmIterator(extension_id, name); | 133 AlarmIterator it = GetAlarmIterator(extension_id, name); |
137 CHECK(it.first != alarms_.end()); | 134 CHECK(it.first != alarms_.end()); |
138 delegate_->OnAlarm(extension_id, *it.second->get()); | 135 const Alarm* alarm = it.second->get(); |
| 136 delegate_->OnAlarm(extension_id, *alarm); |
139 | 137 |
140 if (!(*it.second)->repeating) | 138 if (!alarm->repeating) { |
141 RemoveAlarmIterator(it); | 139 RemoveAlarmIterator(it); |
| 140 } else { |
| 141 // Restart the timer, since it may have been set with a shorter delay |
| 142 // initially. |
| 143 base::Timer* timer = timers_[alarm].get(); |
| 144 timer->Start(FROM_HERE, |
| 145 base::TimeDelta::FromSeconds(alarm->delay_in_seconds), |
| 146 base::Bind(&AlarmManager::OnAlarm, base::Unretained(this), |
| 147 extension_id, alarm->name)); |
| 148 } |
| 149 |
| 150 WriteToPrefs(extension_id); |
| 151 } |
| 152 |
| 153 void AlarmManager::AddAlarmImpl(const std::string& extension_id, |
| 154 const linked_ptr<Alarm>& alarm, |
| 155 base::TimeDelta timer_delay) { |
| 156 // Override any old alarm with the same name. |
| 157 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name); |
| 158 if (old_alarm.first != alarms_.end()) |
| 159 RemoveAlarmIterator(old_alarm); |
| 160 |
| 161 alarms_[extension_id].push_back(alarm); |
| 162 |
| 163 base::Timer* timer = new base::Timer(true, alarm->repeating); |
| 164 timers_[alarm.get()] = make_linked_ptr(timer); |
| 165 timer->Start(FROM_HERE, |
| 166 timer_delay, |
| 167 base::Bind(&AlarmManager::OnAlarm, base::Unretained(this), |
| 168 extension_id, alarm->name)); |
| 169 } |
| 170 |
| 171 void AlarmManager::WriteToPrefs(const std::string& extension_id) { |
| 172 ExtensionService* service = |
| 173 ExtensionSystem::Get(profile_)->extension_service(); |
| 174 if (!service || !service->extension_prefs()) |
| 175 return; |
| 176 |
| 177 std::vector<AlarmPref> alarm_prefs; |
| 178 |
| 179 AlarmMap::iterator list = alarms_.find(extension_id); |
| 180 if (list != alarms_.end()) { |
| 181 for (AlarmList::iterator it = list->second.begin(); |
| 182 it != list->second.end(); ++it) { |
| 183 base::Timer* timer = timers_[it->get()].get(); |
| 184 base::TimeDelta delay = |
| 185 timer->desired_run_time() - base::TimeTicks::Now(); |
| 186 AlarmPref pref; |
| 187 pref.alarm = *it; |
| 188 pref.scheduled_run_time = base::Time::Now() + delay; |
| 189 alarm_prefs.push_back(pref); |
| 190 } |
| 191 } |
| 192 |
| 193 service->extension_prefs()->SetRegisteredAlarms(extension_id, alarm_prefs); |
| 194 } |
| 195 |
| 196 void AlarmManager::ReadFromPrefs(const std::string& extension_id) { |
| 197 ExtensionService* service = |
| 198 ExtensionSystem::Get(profile_)->extension_service(); |
| 199 if (!service || !service->extension_prefs()) |
| 200 return; |
| 201 |
| 202 std::vector<AlarmPref> alarm_prefs = |
| 203 service->extension_prefs()->GetRegisteredAlarms(extension_id); |
| 204 for (size_t i = 0; i < alarm_prefs.size(); ++i) { |
| 205 base::TimeDelta delay = |
| 206 alarm_prefs[i].scheduled_run_time - base::Time::Now(); |
| 207 if (delay < base::TimeDelta::FromSeconds(0)) |
| 208 delay = base::TimeDelta::FromSeconds(0); |
| 209 |
| 210 AddAlarmImpl(extension_id, alarm_prefs[i].alarm, delay); |
| 211 } |
| 212 } |
| 213 |
| 214 void AlarmManager::Observe( |
| 215 int type, |
| 216 const content::NotificationSource& source, |
| 217 const content::NotificationDetails& details) { |
| 218 switch (type) { |
| 219 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| 220 const Extension* extension = |
| 221 content::Details<const Extension>(details).ptr(); |
| 222 ReadFromPrefs(extension->id()); |
| 223 break; |
| 224 } |
| 225 default: |
| 226 NOTREACHED(); |
| 227 break; |
| 228 } |
| 229 } |
| 230 |
| 231 AlarmPref::AlarmPref() { |
| 232 } |
| 233 |
| 234 AlarmPref::~AlarmPref() { |
142 } | 235 } |
143 | 236 |
144 } // namespace extensions | 237 } // namespace extensions |
OLD | NEW |