Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: chrome/browser/extensions/api/alarms/alarm_manager.cc

Issue 10545104: Refactor chrome.alarms interface to support absolute alarm deadlines. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge with r141780 Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/time.h" 10 #include "base/time.h"
11 #include "base/value_conversions.h" 11 #include "base/value_conversions.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "chrome/browser/extensions/extension_event_router.h" 13 #include "chrome/browser/extensions/extension_event_router.h"
14 #include "chrome/browser/extensions/extension_service.h" 14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_system.h" 15 #include "chrome/browser/extensions/extension_system.h"
16 #include "chrome/browser/extensions/state_store.h" 16 #include "chrome/browser/extensions/state_store.h"
17 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/chrome_notification_types.h" 18 #include "chrome/common/chrome_notification_types.h"
19 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/notification_service.h"
20 20
21 namespace extensions { 21 namespace extensions {
22 22
23 namespace { 23 namespace {
24 24
25 const char kOnAlarmEvent[] = "alarms.onAlarm"; 25 const char kOnAlarmEvent[] = "alarms.onAlarm";
26 26
27 // A list of alarms that this extension has set. 27 // A list of alarms that this extension has set.
28 const char kRegisteredAlarms[] = "alarms"; 28 const char kRegisteredAlarms[] = "alarms";
29 const char kAlarmScheduledRunTime[] = "scheduled_run_time"; 29 const char kAlarmGranularity[] = "granularity";
30 30
31 // The minimum period between polling for alarms to run. 31 // The minimum period between polling for alarms to run.
32 const base::TimeDelta kDefaultMinPollPeriod = base::TimeDelta::FromMinutes(5); 32 const base::TimeDelta kDefaultMinPollPeriod = base::TimeDelta::FromMinutes(5);
33 33
34 class DefaultAlarmDelegate : public AlarmManager::Delegate { 34 class DefaultAlarmDelegate : public AlarmManager::Delegate {
35 public: 35 public:
36 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} 36 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {}
37 virtual ~DefaultAlarmDelegate() {} 37 virtual ~DefaultAlarmDelegate() {}
38 38
39 virtual void OnAlarm(const std::string& extension_id, 39 virtual void OnAlarm(const std::string& extension_id,
40 const AlarmManager::Alarm& alarm) { 40 const Alarm& alarm) {
41 ListValue args; 41 ListValue args;
42 std::string json_args; 42 std::string json_args;
43 args.Append(alarm.ToValue().release()); 43 args.Append(alarm.js_alarm->ToValue().release());
44 base::JSONWriter::Write(&args, &json_args); 44 base::JSONWriter::Write(&args, &json_args);
45 ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension( 45 ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
46 extension_id, kOnAlarmEvent, json_args, NULL, GURL()); 46 extension_id, kOnAlarmEvent, json_args, NULL, GURL());
47 } 47 }
48 48
49 private: 49 private:
50 Profile* profile_; 50 Profile* profile_;
51 }; 51 };
52 52
53 // Contains the state we persist for each alarm.
54 struct AlarmState {
55 linked_ptr<AlarmManager::Alarm> alarm;
56 base::Time scheduled_run_time;
57
58 AlarmState() {}
59 ~AlarmState() {}
60 };
61
62 // Creates a TimeDelta from a delay as specified in the API. 53 // Creates a TimeDelta from a delay as specified in the API.
63 base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) { 54 base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) {
64 return base::TimeDelta::FromMicroseconds( 55 return base::TimeDelta::FromMicroseconds(
65 delay_in_minutes * base::Time::kMicrosecondsPerMinute); 56 delay_in_minutes * base::Time::kMicrosecondsPerMinute);
66 } 57 }
67 58
68 std::vector<AlarmState> AlarmsFromValue(const base::ListValue* list) { 59 std::vector<Alarm> AlarmsFromValue(const base::ListValue* list) {
69 typedef AlarmManager::Alarm Alarm; 60 std::vector<Alarm> alarms;
70 std::vector<AlarmState> alarms;
71 for (size_t i = 0; i < list->GetSize(); ++i) { 61 for (size_t i = 0; i < list->GetSize(); ++i) {
72 base::DictionaryValue* alarm_dict = NULL; 62 base::DictionaryValue* alarm_dict = NULL;
73 AlarmState alarm; 63 Alarm alarm;
74 alarm.alarm.reset(new Alarm());
75 if (list->GetDictionary(i, &alarm_dict) && 64 if (list->GetDictionary(i, &alarm_dict) &&
76 Alarm::Populate(*alarm_dict, alarm.alarm.get())) { 65 api::alarms::Alarm::Populate(*alarm_dict, alarm.js_alarm.get())) {
77 base::Value* time_value = NULL; 66 base::Value* time_value = NULL;
78 if (alarm_dict->Get(kAlarmScheduledRunTime, &time_value)) 67 if (alarm_dict->Get(kAlarmGranularity, &time_value))
79 base::GetValueAsTime(*time_value, &alarm.scheduled_run_time); 68 base::GetValueAsTimeDelta(*time_value, &alarm.granularity);
80 alarms.push_back(alarm); 69 alarms.push_back(alarm);
81 } 70 }
82 } 71 }
83 return alarms; 72 return alarms;
84 } 73 }
85 74
86 scoped_ptr<base::ListValue> AlarmsToValue( 75 scoped_ptr<base::ListValue> AlarmsToValue(
87 const std::vector<AlarmState>& alarms) { 76 const std::vector<Alarm>& alarms) {
88 scoped_ptr<base::ListValue> list(new ListValue()); 77 scoped_ptr<base::ListValue> list(new ListValue());
89 for (size_t i = 0; i < alarms.size(); ++i) { 78 for (size_t i = 0; i < alarms.size(); ++i) {
90 scoped_ptr<base::DictionaryValue> alarm = alarms[i].alarm->ToValue().Pass(); 79 scoped_ptr<base::DictionaryValue> alarm =
91 alarm->Set(kAlarmScheduledRunTime, 80 alarms[i].js_alarm->ToValue().Pass();
92 base::CreateTimeValue(alarms[i].scheduled_run_time)); 81 alarm->Set(kAlarmGranularity,
82 base::CreateTimeDeltaValue(alarms[i].granularity));
93 list->Append(alarm.release()); 83 list->Append(alarm.release());
94 } 84 }
95 return list.Pass(); 85 return list.Pass();
96 } 86 }
97 87
98 88
99 } // namespace 89 } // namespace
100 90
101 // AlarmManager 91 // AlarmManager
102 92
103 AlarmManager::AlarmManager(Profile* profile) 93 AlarmManager::AlarmManager(Profile* profile, TimeProvider now)
104 : profile_(profile), 94 : profile_(profile),
95 now_(now),
105 delegate_(new DefaultAlarmDelegate(profile)), 96 delegate_(new DefaultAlarmDelegate(profile)),
106 last_poll_time_(base::Time()) { 97 last_poll_time_(base::Time()) {
107 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 98 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
108 content::Source<Profile>(profile_)); 99 content::Source<Profile>(profile_));
109 100
110 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); 101 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
111 if (storage) 102 if (storage)
112 storage->RegisterKey(kRegisteredAlarms); 103 storage->RegisterKey(kRegisteredAlarms);
113 } 104 }
114 105
115 AlarmManager::~AlarmManager() { 106 AlarmManager::~AlarmManager() {
116 } 107 }
117 108
118 void AlarmManager::AddAlarm(const std::string& extension_id, 109 void AlarmManager::AddAlarm(const std::string& extension_id,
119 const linked_ptr<Alarm>& alarm) { 110 const Alarm& alarm) {
120 base::TimeDelta alarm_time = TimeDeltaFromDelay(alarm->delay_in_minutes); 111 AddAlarmImpl(extension_id, alarm);
121 AddAlarmImpl(extension_id, alarm, alarm_time);
122 WriteToStorage(extension_id); 112 WriteToStorage(extension_id);
123 } 113 }
124 114
125 const AlarmManager::Alarm* AlarmManager::GetAlarm( 115 const Alarm* AlarmManager::GetAlarm(
126 const std::string& extension_id, const std::string& name) { 116 const std::string& extension_id, const std::string& name) {
127 AlarmIterator it = GetAlarmIterator(extension_id, name); 117 AlarmIterator it = GetAlarmIterator(extension_id, name);
128 if (it.first == alarms_.end()) 118 if (it.first == alarms_.end())
129 return NULL; 119 return NULL;
130 return it.second->get(); 120 return &*it.second;
131 } 121 }
132 122
133 const AlarmManager::AlarmList* AlarmManager::GetAllAlarms( 123 const AlarmManager::AlarmList* AlarmManager::GetAllAlarms(
134 const std::string& extension_id) { 124 const std::string& extension_id) {
135 AlarmMap::iterator list = alarms_.find(extension_id); 125 AlarmMap::iterator list = alarms_.find(extension_id);
136 if (list == alarms_.end()) 126 if (list == alarms_.end())
137 return NULL; 127 return NULL;
138 return &list->second; 128 return &list->second;
139 } 129 }
140 130
141 AlarmManager::AlarmIterator AlarmManager::GetAlarmIterator( 131 AlarmManager::AlarmIterator AlarmManager::GetAlarmIterator(
142 const std::string& extension_id, const std::string& name) { 132 const std::string& extension_id, const std::string& name) {
143 AlarmMap::iterator list = alarms_.find(extension_id); 133 AlarmMap::iterator list = alarms_.find(extension_id);
144 if (list == alarms_.end()) 134 if (list == alarms_.end())
145 return make_pair(alarms_.end(), AlarmList::iterator()); 135 return make_pair(alarms_.end(), AlarmList::iterator());
146 136
147 for (AlarmList::iterator it = list->second.begin(); 137 for (AlarmList::iterator it = list->second.begin();
148 it != list->second.end(); ++it) { 138 it != list->second.end(); ++it) {
149 if ((*it)->name == name) 139 if (it->js_alarm->name == name)
150 return make_pair(list, it); 140 return make_pair(list, it);
151 } 141 }
152 142
153 return make_pair(alarms_.end(), AlarmList::iterator()); 143 return make_pair(alarms_.end(), AlarmList::iterator());
154 } 144 }
155 145
156 bool AlarmManager::RemoveAlarm(const std::string& extension_id, 146 bool AlarmManager::RemoveAlarm(const std::string& extension_id,
157 const std::string& name) { 147 const std::string& name) {
158 AlarmIterator it = GetAlarmIterator(extension_id, name); 148 AlarmIterator it = GetAlarmIterator(extension_id, name);
159 if (it.first == alarms_.end()) 149 if (it.first == alarms_.end())
(...skipping 12 matching lines...) Expand all
172 // Note: I'm using indices rather than iterators here because 162 // Note: I'm using indices rather than iterators here because
173 // RemoveAlarmIterator will delete the list when it becomes empty. 163 // RemoveAlarmIterator will delete the list when it becomes empty.
174 for (size_t i = 0, size = list->second.size(); i < size; ++i) 164 for (size_t i = 0, size = list->second.size(); i < size; ++i)
175 RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); 165 RemoveAlarmIterator(AlarmIterator(list, list->second.begin()));
176 166
177 CHECK(alarms_.find(extension_id) == alarms_.end()); 167 CHECK(alarms_.find(extension_id) == alarms_.end());
178 WriteToStorage(extension_id); 168 WriteToStorage(extension_id);
179 } 169 }
180 170
181 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { 171 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) {
182 // Cancel the timer if there are no more alarms.
183 // We don't need to reschedule the poll otherwise, because in
184 // the worst case we would just poll one extra time.
185 scheduled_times_.erase(iter.second->get());
186 if (scheduled_times_.empty())
187 timer_.Stop();
188
189 // Clean up our alarm list.
190 AlarmList& list = iter.first->second; 172 AlarmList& list = iter.first->second;
191 list.erase(iter.second); 173 list.erase(iter.second);
192 if (list.empty()) 174 if (list.empty())
193 alarms_.erase(iter.first); 175 alarms_.erase(iter.first);
176
177 // Cancel the timer if there are no more alarms.
178 // We don't need to reschedule the poll otherwise, because in
179 // the worst case we would just poll one extra time.
180 if (alarms_.empty())
181 timer_.Stop();
194 } 182 }
195 183
196 void AlarmManager::OnAlarm(const std::string& extension_id, 184 void AlarmManager::OnAlarm(AlarmIterator it) {
197 const std::string& name) {
198 AlarmIterator it = GetAlarmIterator(extension_id, name);
199 CHECK(it.first != alarms_.end()); 185 CHECK(it.first != alarms_.end());
200 const Alarm* alarm = it.second->get(); 186 Alarm& alarm = *it.second;
201 delegate_->OnAlarm(extension_id, *alarm); 187 std::string extension_id_copy(it.first->first);
188 delegate_->OnAlarm(extension_id_copy, alarm);
202 189
203 std::string extension_id_copy(extension_id); 190 // Update our scheduled time for the next alarm.
204 if (!alarm->repeating) { 191 if (double* period_in_minutes =
192 alarm.js_alarm->period_in_minutes.get()) {
193 alarm.js_alarm->scheduled_time =
194 (last_poll_time_ +
195 TimeDeltaFromDelay(*period_in_minutes)).ToJsTime();
196 } else {
205 RemoveAlarmIterator(it); 197 RemoveAlarmIterator(it);
206 } else {
207 // Update our scheduled time for the next alarm.
208 scheduled_times_[alarm].time =
209 last_poll_time_ + TimeDeltaFromDelay(alarm->delay_in_minutes);
210 } 198 }
211 WriteToStorage(extension_id_copy); 199 WriteToStorage(extension_id_copy);
212 } 200 }
213 201
214 void AlarmManager::AddAlarmImpl(const std::string& extension_id, 202 void AlarmManager::AddAlarmImpl(const std::string& extension_id,
215 const linked_ptr<Alarm>& alarm, 203 const Alarm& alarm) {
216 base::TimeDelta time_delay) {
217 // Override any old alarm with the same name. 204 // Override any old alarm with the same name.
218 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name); 205 AlarmIterator old_alarm = GetAlarmIterator(extension_id,
206 alarm.js_alarm->name);
219 if (old_alarm.first != alarms_.end()) 207 if (old_alarm.first != alarms_.end())
220 RemoveAlarmIterator(old_alarm); 208 RemoveAlarmIterator(old_alarm);
221 209
222 alarms_[extension_id].push_back(alarm); 210 alarms_[extension_id].push_back(alarm);
223 AlarmRuntimeInfo info;
224 info.extension_id = extension_id;
225 info.time = base::Time::Now() + time_delay;
226 scheduled_times_[alarm.get()] = info;
227 211
228 // TODO(yoz): Is 0 really sane? There could be thrashing. 212 // TODO(yoz): Is 0 really sane? There could be thrashing.
229 ScheduleNextPoll(base::TimeDelta::FromMinutes(0)); 213 ScheduleNextPoll(base::TimeDelta::FromMinutes(0));
230 } 214 }
231 215
232 void AlarmManager::WriteToStorage(const std::string& extension_id) { 216 void AlarmManager::WriteToStorage(const std::string& extension_id) {
233 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); 217 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
234 if (!storage) 218 if (!storage)
235 return; 219 return;
236 220
237 std::vector<AlarmState> alarm_states; 221 scoped_ptr<Value> alarms;
238 AlarmMap::iterator list = alarms_.find(extension_id); 222 AlarmMap::iterator list = alarms_.find(extension_id);
239 if (list != alarms_.end()) { 223 if (list != alarms_.end())
240 for (AlarmList::iterator it = list->second.begin(); 224 alarms.reset(AlarmsToValue(list->second).release());
241 it != list->second.end(); ++it) { 225 else
242 AlarmState pref; 226 alarms.reset(AlarmsToValue(std::vector<Alarm>()).release());
243 pref.alarm = *it;
244 pref.scheduled_run_time = scheduled_times_[it->get()].time;
245 alarm_states.push_back(pref);
246 }
247 }
248
249 scoped_ptr<Value> alarms(AlarmsToValue(alarm_states).release());
250 storage->SetExtensionValue(extension_id, kRegisteredAlarms, alarms.Pass()); 227 storage->SetExtensionValue(extension_id, kRegisteredAlarms, alarms.Pass());
251 } 228 }
252 229
253 void AlarmManager::ReadFromStorage(const std::string& extension_id, 230 void AlarmManager::ReadFromStorage(const std::string& extension_id,
254 scoped_ptr<base::Value> value) { 231 scoped_ptr<base::Value> value) {
255 base::ListValue* list = NULL; 232 base::ListValue* list = NULL;
256 if (!value.get() || !value->GetAsList(&list)) 233 if (!value.get() || !value->GetAsList(&list))
257 return; 234 return;
258 235
259 std::vector<AlarmState> alarm_states = AlarmsFromValue(list); 236 std::vector<Alarm> alarm_states = AlarmsFromValue(list);
260 for (size_t i = 0; i < alarm_states.size(); ++i) { 237 for (size_t i = 0; i < alarm_states.size(); ++i) {
261 base::TimeDelta delay = 238 AddAlarmImpl(extension_id, alarm_states[i]);
262 alarm_states[i].scheduled_run_time - base::Time::Now();
263 if (delay < base::TimeDelta::FromSeconds(0))
264 delay = base::TimeDelta::FromSeconds(0);
265
266 AddAlarmImpl(extension_id, alarm_states[i].alarm, delay);
267 } 239 }
268 } 240 }
269 241
270 void AlarmManager::ScheduleNextPoll(base::TimeDelta min_period) { 242 void AlarmManager::ScheduleNextPoll(base::TimeDelta min_period) {
271 // 0. If there are no alarms, stop the timer. 243 // 0. If there are no alarms, stop the timer.
272 if (scheduled_times_.empty()) { 244 if (alarms_.empty()) {
273 timer_.Stop(); 245 timer_.Stop();
274 return; 246 return;
275 } 247 }
276 248
277 // TODO(yoz): Try not to reschedule every single time if we're adding 249 // TODO(yoz): Try not to reschedule every single time if we're adding
278 // a lot of alarms. 250 // a lot of alarms.
279 251
280 base::Time next_poll(last_poll_time_ + min_period); 252 base::Time next_poll(last_poll_time_ + min_period);
281 253
282 // Find the soonest alarm that is scheduled to run. 254 // Find the soonest alarm that is scheduled to run.
283 AlarmRuntimeInfoMap::iterator min_it = scheduled_times_.begin(); 255 // alarms_ guarantees that none of its contained lists are empty.
284 for (AlarmRuntimeInfoMap::iterator it = min_it; 256 base::Time soonest_alarm_time = base::Time::FromJsTime(
285 it != scheduled_times_.end(); ++it) { 257 alarms_.begin()->second.begin()->js_alarm->scheduled_time);
286 if (it->second.time < min_it->second.time) 258 for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end();
287 min_it = it; 259 m_it != m_end; ++m_it) {
260 for (AlarmList::const_iterator l_it = m_it->second.begin();
261 l_it != m_it->second.end(); ++l_it) {
262 base::Time cur_alarm_time =
263 base::Time::FromJsTime(l_it->js_alarm->scheduled_time);
264 if (cur_alarm_time < soonest_alarm_time)
265 soonest_alarm_time = cur_alarm_time;
266 }
288 } 267 }
289 base::Time soonest_alarm_time(min_it->second.time);
290 268
291 // If the next alarm is more than min_period in the future, wait for it. 269 // If the next alarm is more than min_period in the future, wait for it.
292 // Otherwise, only poll as often as min_period. 270 // Otherwise, only poll as often as min_period.
293 if (last_poll_time_.is_null() || next_poll < soonest_alarm_time) { 271 if (last_poll_time_.is_null() || next_poll < soonest_alarm_time) {
294 next_poll = soonest_alarm_time; 272 next_poll = soonest_alarm_time;
295 } 273 }
296 274
297 // Schedule the poll. 275 // Schedule the poll.
298 next_poll_time_ = next_poll; 276 next_poll_time_ = next_poll;
299 base::TimeDelta delay = std::max(base::TimeDelta::FromSeconds(0), 277 base::TimeDelta delay = std::max(base::TimeDelta::FromSeconds(0),
300 next_poll - base::Time::Now()); 278 next_poll - now_());
301 timer_.Start(FROM_HERE, 279 timer_.Start(FROM_HERE,
302 delay, 280 delay,
303 this, 281 this,
304 &AlarmManager::PollAlarms); 282 &AlarmManager::PollAlarms);
305 } 283 }
306 284
307 void AlarmManager::PollAlarms() { 285 void AlarmManager::PollAlarms() {
308 last_poll_time_ = base::Time::Now(); 286 last_poll_time_ = now_();
309 287
310 // Run any alarms scheduled in the past. Note that we could remove alarms 288 // Run any alarms scheduled in the past. OnAlarm uses vector::erase to remove
311 // during iteration if they are non-repeating. 289 // elements from the AlarmList, and map::erase to remove AlarmLists from the
312 AlarmRuntimeInfoMap::iterator iter = scheduled_times_.begin(); 290 // AlarmMap.
313 while (iter != scheduled_times_.end()) { 291 for (AlarmMap::iterator m_it = alarms_.begin(), m_end = alarms_.end();
314 AlarmRuntimeInfoMap::iterator it = iter; 292 m_it != m_end;) {
315 ++iter; 293 AlarmMap::iterator cur_extension = m_it++;
316 if (it->second.time <= next_poll_time_) { 294
317 OnAlarm(it->second.extension_id, it->first->name); 295 // Iterate (a) backwards so that removing elements doesn't affect
296 // upcoming iterations, and (b) with indices so that if the last
297 // iteration destroys the AlarmList, I'm not about to use the end
298 // iterator that the destruction invalidates.
299 for (size_t i = cur_extension->second.size(); i > 0; --i) {
300 AlarmList::iterator cur_alarm = cur_extension->second.begin() + i - 1;
301 if (base::Time::FromJsTime(cur_alarm->js_alarm->scheduled_time) <=
302 next_poll_time_) {
303 OnAlarm(make_pair(cur_extension, cur_alarm));
304 }
318 } 305 }
319 } 306 }
320 307
321 // Schedule the next poll. The soonest it may happen is after 308 // Schedule the next poll. The soonest it may happen is after
322 // kDefaultMinPollPeriod or after the shortest scheduled delay of any alarm, 309 // kDefaultMinPollPeriod or after the shortest granularity of any alarm,
323 // whichever comes sooner. 310 // whichever comes sooner.
324 base::TimeDelta min_poll_period = kDefaultMinPollPeriod; 311 base::TimeDelta min_poll_period = kDefaultMinPollPeriod;
325 for (AlarmRuntimeInfoMap::iterator it = scheduled_times_.begin(); 312 for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end();
326 it != scheduled_times_.end(); ++it) { 313 m_it != m_end; ++m_it) {
327 min_poll_period = std::min(TimeDeltaFromDelay(it->first->delay_in_minutes), 314 for (AlarmList::const_iterator l_it = m_it->second.begin();
328 min_poll_period); 315 l_it != m_it->second.end(); ++l_it) {
316 if (l_it->granularity < min_poll_period)
317 min_poll_period = l_it->granularity;
318 }
329 } 319 }
330 ScheduleNextPoll(min_poll_period); 320 ScheduleNextPoll(min_poll_period);
331 } 321 }
332 322
333 void AlarmManager::Observe( 323 void AlarmManager::Observe(
334 int type, 324 int type,
335 const content::NotificationSource& source, 325 const content::NotificationSource& source,
336 const content::NotificationDetails& details) { 326 const content::NotificationDetails& details) {
337 switch (type) { 327 switch (type) {
338 case chrome::NOTIFICATION_EXTENSION_LOADED: { 328 case chrome::NOTIFICATION_EXTENSION_LOADED: {
339 const Extension* extension = 329 const Extension* extension =
340 content::Details<const Extension>(details).ptr(); 330 content::Details<const Extension>(details).ptr();
341 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); 331 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
342 if (storage) { 332 if (storage) {
343 storage->GetExtensionValue(extension->id(), kRegisteredAlarms, 333 storage->GetExtensionValue(extension->id(), kRegisteredAlarms,
344 base::Bind(&AlarmManager::ReadFromStorage, 334 base::Bind(&AlarmManager::ReadFromStorage,
345 AsWeakPtr(), extension->id())); 335 AsWeakPtr(), extension->id()));
346 } 336 }
347 break; 337 break;
348 } 338 }
349 default: 339 default:
350 NOTREACHED(); 340 NOTREACHED();
351 break; 341 break;
352 } 342 }
353 } 343 }
354 344
345 // AlarmManager::Alarm
346
347 Alarm::Alarm()
348 : js_alarm(new api::alarms::Alarm()) {
349 }
350
351 Alarm::Alarm(const std::string& name,
352 const api::alarms::AlarmCreateInfo& create_info,
353 base::TimeDelta min_granularity,
354 TimeProvider now)
355 : js_alarm(new api::alarms::Alarm()) {
356 js_alarm->name = name;
357
358 if (create_info.when.get()) {
359 // Absolute scheduling.
360 js_alarm->scheduled_time = *create_info.when;
361 granularity = base::Time::FromJsTime(js_alarm->scheduled_time) - now();
362 } else {
363 // Relative scheduling.
364 double* delay_in_minutes = create_info.delay_in_minutes.get();
365 if (delay_in_minutes == NULL)
366 delay_in_minutes = create_info.period_in_minutes.get();
367 CHECK(delay_in_minutes != NULL)
368 << "ValidateAlarmCreateInfo in alarms_api.cc should have "
369 << "prevented this call.";
370 base::TimeDelta delay = TimeDeltaFromDelay(*delay_in_minutes);
371 js_alarm->scheduled_time = (now() + delay).ToJsTime();
372 granularity = delay;
373 }
374
375 if (granularity < min_granularity)
376 granularity = min_granularity;
377
378 // Check for repetition.
379 if (create_info.period_in_minutes.get()) {
380 js_alarm->period_in_minutes.reset(
381 new double(*create_info.period_in_minutes));
382 }
383 }
384
385 Alarm::~Alarm() {
386 }
387
355 } // namespace extensions 388 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/alarms/alarm_manager.h ('k') | chrome/browser/extensions/api/alarms/alarms_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698