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/time.h" | 10 #include "base/time.h" |
(...skipping 14 matching lines...) Expand all Loading... | |
25 | 25 |
26 // The minimum period between polling for alarms to run. | 26 // The minimum period between polling for alarms to run. |
27 const base::TimeDelta kDefaultMinPollPeriod = base::TimeDelta::FromMinutes(5); | 27 const base::TimeDelta kDefaultMinPollPeriod = base::TimeDelta::FromMinutes(5); |
28 | 28 |
29 class DefaultAlarmDelegate : public AlarmManager::Delegate { | 29 class DefaultAlarmDelegate : public AlarmManager::Delegate { |
30 public: | 30 public: |
31 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} | 31 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} |
32 virtual ~DefaultAlarmDelegate() {} | 32 virtual ~DefaultAlarmDelegate() {} |
33 | 33 |
34 virtual void OnAlarm(const std::string& extension_id, | 34 virtual void OnAlarm(const std::string& extension_id, |
35 const AlarmManager::Alarm& alarm) { | 35 const Alarm& alarm) { |
36 ListValue args; | 36 ListValue args; |
37 std::string json_args; | 37 std::string json_args; |
38 args.Append(alarm.ToValue().release()); | 38 args.Append(alarm.js_alarm->ToValue().release()); |
39 base::JSONWriter::Write(&args, &json_args); | 39 base::JSONWriter::Write(&args, &json_args); |
40 ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension( | 40 ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension( |
41 extension_id, kOnAlarmEvent, json_args, NULL, GURL()); | 41 extension_id, kOnAlarmEvent, json_args, NULL, GURL()); |
42 } | 42 } |
43 | 43 |
44 private: | 44 private: |
45 Profile* profile_; | 45 Profile* profile_; |
46 }; | 46 }; |
47 | 47 |
48 // Creates a TimeDelta from a delay as specified in the API. | 48 // Creates a TimeDelta from a delay as specified in the API. |
49 base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) { | 49 base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) { |
50 return base::TimeDelta::FromMicroseconds( | 50 return base::TimeDelta::FromMicroseconds( |
51 delay_in_minutes * base::Time::kMicrosecondsPerMinute); | 51 delay_in_minutes * base::Time::kMicrosecondsPerMinute); |
52 } | 52 } |
53 | 53 |
54 } // namespace | 54 } // namespace |
55 | 55 |
56 // AlarmManager | 56 // AlarmManager |
57 | 57 |
58 AlarmManager::AlarmManager(Profile* profile) | 58 AlarmManager::AlarmManager(Profile* profile, TimeProvider now) |
59 : profile_(profile), | 59 : profile_(profile), |
60 now_(now), | |
60 delegate_(new DefaultAlarmDelegate(profile)), | 61 delegate_(new DefaultAlarmDelegate(profile)), |
61 last_poll_time_(base::Time()) { | 62 last_poll_time_(base::Time()) { |
62 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | 63 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
63 content::Source<Profile>(profile_)); | 64 content::Source<Profile>(profile_)); |
64 } | 65 } |
65 | 66 |
66 AlarmManager::~AlarmManager() { | 67 AlarmManager::~AlarmManager() { |
67 } | 68 } |
68 | 69 |
69 void AlarmManager::AddAlarm(const std::string& extension_id, | 70 void AlarmManager::AddAlarm(const std::string& extension_id, |
70 const linked_ptr<Alarm>& alarm) { | 71 const Alarm& alarm) { |
71 base::TimeDelta alarm_time = TimeDeltaFromDelay(alarm->delay_in_minutes); | 72 AddAlarmImpl(extension_id, alarm); |
72 AddAlarmImpl(extension_id, alarm, alarm_time); | |
73 WriteToPrefs(extension_id); | 73 WriteToPrefs(extension_id); |
74 } | 74 } |
75 | 75 |
76 const AlarmManager::Alarm* AlarmManager::GetAlarm( | 76 const Alarm* AlarmManager::GetAlarm( |
77 const std::string& extension_id, const std::string& name) { | 77 const std::string& extension_id, const std::string& name) { |
78 AlarmIterator it = GetAlarmIterator(extension_id, name); | 78 AlarmIterator it = GetAlarmIterator(extension_id, name); |
79 if (it.first == alarms_.end()) | 79 if (it.first == alarms_.end()) |
80 return NULL; | 80 return NULL; |
81 return it.second->get(); | 81 return &*it.second; |
82 } | 82 } |
83 | 83 |
84 const AlarmManager::AlarmList* AlarmManager::GetAllAlarms( | 84 const AlarmManager::AlarmList* AlarmManager::GetAllAlarms( |
85 const std::string& extension_id) { | 85 const std::string& extension_id) { |
86 AlarmMap::iterator list = alarms_.find(extension_id); | 86 AlarmMap::iterator list = alarms_.find(extension_id); |
87 if (list == alarms_.end()) | 87 if (list == alarms_.end()) |
88 return NULL; | 88 return NULL; |
89 return &list->second; | 89 return &list->second; |
90 } | 90 } |
91 | 91 |
92 AlarmManager::AlarmIterator AlarmManager::GetAlarmIterator( | 92 AlarmManager::AlarmIterator AlarmManager::GetAlarmIterator( |
93 const std::string& extension_id, const std::string& name) { | 93 const std::string& extension_id, const std::string& name) { |
94 AlarmMap::iterator list = alarms_.find(extension_id); | 94 AlarmMap::iterator list = alarms_.find(extension_id); |
95 if (list == alarms_.end()) | 95 if (list == alarms_.end()) |
96 return make_pair(alarms_.end(), AlarmList::iterator()); | 96 return make_pair(alarms_.end(), AlarmList::iterator()); |
97 | 97 |
98 for (AlarmList::iterator it = list->second.begin(); | 98 for (AlarmList::iterator it = list->second.begin(); |
99 it != list->second.end(); ++it) { | 99 it != list->second.end(); ++it) { |
100 if ((*it)->name == name) | 100 if (it->js_alarm->name == name) |
101 return make_pair(list, it); | 101 return make_pair(list, it); |
102 } | 102 } |
103 | 103 |
104 return make_pair(alarms_.end(), AlarmList::iterator()); | 104 return make_pair(alarms_.end(), AlarmList::iterator()); |
105 } | 105 } |
106 | 106 |
107 bool AlarmManager::RemoveAlarm(const std::string& extension_id, | 107 bool AlarmManager::RemoveAlarm(const std::string& extension_id, |
108 const std::string& name) { | 108 const std::string& name) { |
109 AlarmIterator it = GetAlarmIterator(extension_id, name); | 109 AlarmIterator it = GetAlarmIterator(extension_id, name); |
110 if (it.first == alarms_.end()) | 110 if (it.first == alarms_.end()) |
(...skipping 12 matching lines...) Expand all Loading... | |
123 // Note: I'm using indices rather than iterators here because | 123 // Note: I'm using indices rather than iterators here because |
124 // RemoveAlarmIterator will delete the list when it becomes empty. | 124 // RemoveAlarmIterator will delete the list when it becomes empty. |
125 for (size_t i = 0, size = list->second.size(); i < size; ++i) | 125 for (size_t i = 0, size = list->second.size(); i < size; ++i) |
126 RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); | 126 RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); |
127 | 127 |
128 CHECK(alarms_.find(extension_id) == alarms_.end()); | 128 CHECK(alarms_.find(extension_id) == alarms_.end()); |
129 WriteToPrefs(extension_id); | 129 WriteToPrefs(extension_id); |
130 } | 130 } |
131 | 131 |
132 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { | 132 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { |
133 // Cancel the timer if there are no more alarms. | |
134 // We don't need to reschedule the poll otherwise, because in | |
135 // the worst case we would just poll one extra time. | |
136 scheduled_times_.erase(iter.second->get()); | |
137 if (scheduled_times_.empty()) | |
138 timer_.Stop(); | |
139 | |
140 // Clean up our alarm list. | |
141 AlarmList& list = iter.first->second; | 133 AlarmList& list = iter.first->second; |
142 list.erase(iter.second); | 134 list.erase(iter.second); |
143 if (list.empty()) | 135 if (list.empty()) |
144 alarms_.erase(iter.first); | 136 alarms_.erase(iter.first); |
137 | |
138 // Cancel the timer if there are no more alarms. | |
139 // We don't need to reschedule the poll otherwise, because in | |
140 // the worst case we would just poll one extra time. | |
141 if (alarms_.empty()) | |
142 timer_.Stop(); | |
145 } | 143 } |
146 | 144 |
147 void AlarmManager::OnAlarm(const std::string& extension_id, | 145 void AlarmManager::OnAlarm(AlarmIterator it) { |
148 const std::string& name) { | |
149 AlarmIterator it = GetAlarmIterator(extension_id, name); | |
150 CHECK(it.first != alarms_.end()); | 146 CHECK(it.first != alarms_.end()); |
151 const Alarm* alarm = it.second->get(); | 147 Alarm& alarm = *it.second; |
152 delegate_->OnAlarm(extension_id, *alarm); | 148 std::string extension_id_copy(it.first->first); |
149 delegate_->OnAlarm(extension_id_copy, alarm); | |
153 | 150 |
154 std::string extension_id_copy(extension_id); | 151 // Update our scheduled time for the next alarm. |
155 if (!alarm->repeating) { | 152 if (double* period_in_minutes = |
Matt Perry
2012/06/11 22:32:44
I always thought our style guide banned this, but
| |
153 alarm.js_alarm->period_in_minutes.get()) { | |
154 alarm.js_alarm->scheduled_time = | |
155 (last_poll_time_ + | |
156 TimeDeltaFromDelay(*period_in_minutes)).ToJsTime(); | |
157 } else { | |
156 RemoveAlarmIterator(it); | 158 RemoveAlarmIterator(it); |
157 } else { | |
158 // Update our scheduled time for the next alarm. | |
159 scheduled_times_[alarm].time = | |
160 last_poll_time_ + TimeDeltaFromDelay(alarm->delay_in_minutes); | |
161 } | 159 } |
162 WriteToPrefs(extension_id_copy); | 160 WriteToPrefs(extension_id_copy); |
163 } | 161 } |
164 | 162 |
165 void AlarmManager::AddAlarmImpl(const std::string& extension_id, | 163 void AlarmManager::AddAlarmImpl(const std::string& extension_id, |
166 const linked_ptr<Alarm>& alarm, | 164 const Alarm& alarm) { |
167 base::TimeDelta time_delay) { | |
168 // Override any old alarm with the same name. | 165 // Override any old alarm with the same name. |
169 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name); | 166 AlarmIterator old_alarm = GetAlarmIterator(extension_id, |
167 alarm.js_alarm->name); | |
170 if (old_alarm.first != alarms_.end()) | 168 if (old_alarm.first != alarms_.end()) |
171 RemoveAlarmIterator(old_alarm); | 169 RemoveAlarmIterator(old_alarm); |
172 | 170 |
173 alarms_[extension_id].push_back(alarm); | 171 alarms_[extension_id].push_back(alarm); |
174 AlarmRuntimeInfo info; | |
175 info.extension_id = extension_id; | |
176 info.time = base::Time::Now() + time_delay; | |
177 scheduled_times_[alarm.get()] = info; | |
178 | 172 |
179 // TODO(yoz): Is 0 really sane? There could be thrashing. | 173 // TODO(yoz): Is 0 really sane? There could be thrashing. |
180 ScheduleNextPoll(base::TimeDelta::FromMinutes(0)); | 174 ScheduleNextPoll(base::TimeDelta::FromMinutes(0)); |
181 } | 175 } |
182 | 176 |
183 void AlarmManager::WriteToPrefs(const std::string& extension_id) { | 177 void AlarmManager::WriteToPrefs(const std::string& extension_id) { |
184 ExtensionService* service = | 178 ExtensionService* service = |
185 ExtensionSystem::Get(profile_)->extension_service(); | 179 ExtensionSystem::Get(profile_)->extension_service(); |
186 if (!service || !service->extension_prefs()) | 180 if (!service || !service->extension_prefs()) |
187 return; | 181 return; |
188 | 182 |
189 std::vector<AlarmPref> alarm_prefs; | 183 std::vector<Alarm> alarm_prefs; |
190 | 184 |
191 AlarmMap::iterator list = alarms_.find(extension_id); | 185 AlarmMap::iterator list = alarms_.find(extension_id); |
192 if (list != alarms_.end()) { | 186 if (list != alarms_.end()) { |
193 for (AlarmList::iterator it = list->second.begin(); | 187 for (AlarmList::iterator it = list->second.begin(); |
194 it != list->second.end(); ++it) { | 188 it != list->second.end(); ++it) { |
195 AlarmPref pref; | 189 alarm_prefs.push_back(*it); |
196 pref.alarm = *it; | |
197 pref.scheduled_run_time = scheduled_times_[it->get()].time; | |
198 alarm_prefs.push_back(pref); | |
199 } | 190 } |
200 } | 191 } |
201 | 192 |
202 service->extension_prefs()->SetRegisteredAlarms(extension_id, alarm_prefs); | 193 service->extension_prefs()->SetRegisteredAlarms(extension_id, alarm_prefs); |
Matt Perry
2012/06/11 22:32:44
I have a CL that changes this a bit. The slower on
Jeffrey Yasskin
2012/06/12 19:12:31
I already don't need to copy it to a temp list. I
| |
203 } | 194 } |
204 | 195 |
205 void AlarmManager::ReadFromPrefs(const std::string& extension_id) { | 196 void AlarmManager::ReadFromPrefs(const std::string& extension_id) { |
206 ExtensionService* service = | 197 ExtensionService* service = |
207 ExtensionSystem::Get(profile_)->extension_service(); | 198 ExtensionSystem::Get(profile_)->extension_service(); |
208 if (!service || !service->extension_prefs()) | 199 if (!service || !service->extension_prefs()) |
209 return; | 200 return; |
210 | 201 |
211 std::vector<AlarmPref> alarm_prefs = | 202 std::vector<Alarm> alarm_prefs = |
212 service->extension_prefs()->GetRegisteredAlarms(extension_id); | 203 service->extension_prefs()->GetRegisteredAlarms(extension_id); |
213 for (size_t i = 0; i < alarm_prefs.size(); ++i) { | 204 for (size_t i = 0; i < alarm_prefs.size(); ++i) { |
214 base::TimeDelta delay = | 205 AddAlarmImpl(extension_id, alarm_prefs[i]); |
215 alarm_prefs[i].scheduled_run_time - base::Time::Now(); | |
216 if (delay < base::TimeDelta::FromSeconds(0)) | |
217 delay = base::TimeDelta::FromSeconds(0); | |
218 | |
219 AddAlarmImpl(extension_id, alarm_prefs[i].alarm, delay); | |
220 } | 206 } |
221 } | 207 } |
222 | 208 |
223 void AlarmManager::ScheduleNextPoll(base::TimeDelta min_period) { | 209 void AlarmManager::ScheduleNextPoll(base::TimeDelta min_period) { |
224 // 0. If there are no alarms, stop the timer. | 210 // 0. If there are no alarms, stop the timer. |
225 if (scheduled_times_.empty()) { | 211 if (alarms_.empty()) { |
226 timer_.Stop(); | 212 timer_.Stop(); |
227 return; | 213 return; |
228 } | 214 } |
229 | 215 |
230 // TODO(yoz): Try not to reschedule every single time if we're adding | 216 // TODO(yoz): Try not to reschedule every single time if we're adding |
231 // a lot of alarms. | 217 // a lot of alarms. |
232 | 218 |
233 base::Time next_poll(last_poll_time_ + min_period); | 219 base::Time next_poll(last_poll_time_ + min_period); |
234 | 220 |
235 // Find the soonest alarm that is scheduled to run. | 221 // Find the soonest alarm that is scheduled to run. |
236 AlarmRuntimeInfoMap::iterator min_it = scheduled_times_.begin(); | 222 // alarms_ guarantees that none of its contained lists are empty. |
237 for (AlarmRuntimeInfoMap::iterator it = min_it; | 223 base::Time soonest_alarm_time = base::Time::FromJsTime( |
238 it != scheduled_times_.end(); ++it) { | 224 alarms_.begin()->second.begin()->js_alarm->scheduled_time); |
239 if (it->second.time < min_it->second.time) | 225 for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end(); |
240 min_it = it; | 226 m_it != m_end; ++m_it) { |
227 for (AlarmList::const_iterator | |
228 l_it = m_it->second.begin(), l_end = m_it->second.end(); | |
Matt Perry
2012/06/11 22:32:44
nit: getting rid of l_end would actually require l
Jeffrey Yasskin
2012/06/12 19:12:31
True. I got into this habit in LLVM, where they po
| |
229 l_it != l_end; ++l_it) { | |
230 base::Time cur_alarm_time = | |
231 base::Time::FromJsTime(l_it->js_alarm->scheduled_time); | |
232 if (cur_alarm_time < soonest_alarm_time) | |
233 soonest_alarm_time = cur_alarm_time; | |
234 } | |
241 } | 235 } |
242 base::Time soonest_alarm_time(min_it->second.time); | |
243 | 236 |
244 // If the next alarm is more than min_period in the future, wait for it. | 237 // If the next alarm is more than min_period in the future, wait for it. |
245 // Otherwise, only poll as often as min_period. | 238 // Otherwise, only poll as often as min_period. |
246 if (last_poll_time_.is_null() || next_poll < soonest_alarm_time) { | 239 if (last_poll_time_.is_null() || next_poll < soonest_alarm_time) { |
247 next_poll = soonest_alarm_time; | 240 next_poll = soonest_alarm_time; |
248 } | 241 } |
249 | 242 |
250 // Schedule the poll. | 243 // Schedule the poll. |
251 next_poll_time_ = next_poll; | 244 next_poll_time_ = next_poll; |
252 base::TimeDelta delay = std::max(base::TimeDelta::FromSeconds(0), | 245 base::TimeDelta delay = std::max(base::TimeDelta::FromSeconds(0), |
253 next_poll - base::Time::Now()); | 246 next_poll - now_()); |
254 timer_.Start(FROM_HERE, | 247 timer_.Start(FROM_HERE, |
255 delay, | 248 delay, |
256 this, | 249 this, |
257 &AlarmManager::PollAlarms); | 250 &AlarmManager::PollAlarms); |
258 } | 251 } |
259 | 252 |
260 void AlarmManager::PollAlarms() { | 253 void AlarmManager::PollAlarms() { |
261 last_poll_time_ = base::Time::Now(); | 254 last_poll_time_ = now_(); |
262 | 255 |
263 // Run any alarms scheduled in the past. Note that we could remove alarms | 256 // Run any alarms scheduled in the past. OnAlarm uses vector::erase to remove |
264 // during iteration if they are non-repeating. | 257 // elements from the AlarmList, and map::erase to remove AlarmLists from the |
265 AlarmRuntimeInfoMap::iterator iter = scheduled_times_.begin(); | 258 // AlarmMap, so we have to be careful in the iteration to avoid using |
266 while (iter != scheduled_times_.end()) { | 259 // iterators after it's invalidated them. |
267 AlarmRuntimeInfoMap::iterator it = iter; | 260 for (AlarmMap::iterator m_it = alarms_.begin(), m_end = alarms_.end(); |
268 ++iter; | 261 m_it != m_end;) { |
269 if (it->second.time <= next_poll_time_) { | 262 AlarmMap::iterator cur_extension = m_it; |
270 OnAlarm(it->second.extension_id, it->first->name); | 263 // cur_extension may be invalidated by OnAlarm in the last iteration of the |
264 // nested loop, so increment the iterator before that. | |
265 ++m_it; | |
Matt Perry
2012/06/11 22:32:44
nit: no need to explain iterator details here. Doi
Jeffrey Yasskin
2012/06/12 19:12:31
Sounds good. I left most of the other explanations
| |
266 | |
267 // Iterate with indices and backwards so that (a) removing elements doesn't | |
268 // affect upcoming iterations, and (b) if the last iteration destroys the | |
269 // AlarmList, I'm not about to use the end iterator that the destruction | |
270 // invalidates. | |
271 for (size_t i = cur_extension->second.size(); i > 0; --i) { | |
272 AlarmList::iterator cur_alarm = cur_extension->second.begin() + i - 1; | |
273 if (base::Time::FromJsTime(cur_alarm->js_alarm->scheduled_time) <= | |
274 next_poll_time_) { | |
275 OnAlarm(make_pair(cur_extension, cur_alarm)); | |
276 } | |
271 } | 277 } |
272 } | 278 } |
273 | 279 |
274 // Schedule the next poll. The soonest it may happen is after | 280 // Schedule the next poll. The soonest it may happen is after |
275 // kDefaultMinPollPeriod or after the shortest scheduled delay of any alarm, | 281 // kDefaultMinPollPeriod or after the shortest granularity of any alarm, |
276 // whichever comes sooner. | 282 // whichever comes sooner. |
277 base::TimeDelta min_poll_period = kDefaultMinPollPeriod; | 283 base::TimeDelta min_poll_period = kDefaultMinPollPeriod; |
278 for (AlarmRuntimeInfoMap::iterator it = scheduled_times_.begin(); | 284 for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end(); |
279 it != scheduled_times_.end(); ++it) { | 285 m_it != m_end; ++m_it) { |
280 min_poll_period = std::min(TimeDeltaFromDelay(it->first->delay_in_minutes), | 286 for (AlarmList::const_iterator |
281 min_poll_period); | 287 l_it = m_it->second.begin(), l_end = m_it->second.end(); |
288 l_it != l_end; ++l_it) { | |
289 if (l_it->granularity < min_poll_period) | |
290 min_poll_period = l_it->granularity; | |
291 } | |
282 } | 292 } |
283 ScheduleNextPoll(min_poll_period); | 293 ScheduleNextPoll(min_poll_period); |
284 } | 294 } |
285 | 295 |
286 void AlarmManager::Observe( | 296 void AlarmManager::Observe( |
287 int type, | 297 int type, |
288 const content::NotificationSource& source, | 298 const content::NotificationSource& source, |
289 const content::NotificationDetails& details) { | 299 const content::NotificationDetails& details) { |
290 switch (type) { | 300 switch (type) { |
291 case chrome::NOTIFICATION_EXTENSION_LOADED: { | 301 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
292 const Extension* extension = | 302 const Extension* extension = |
293 content::Details<const Extension>(details).ptr(); | 303 content::Details<const Extension>(details).ptr(); |
294 ReadFromPrefs(extension->id()); | 304 ReadFromPrefs(extension->id()); |
295 break; | 305 break; |
296 } | 306 } |
297 default: | 307 default: |
298 NOTREACHED(); | 308 NOTREACHED(); |
299 break; | 309 break; |
300 } | 310 } |
301 } | 311 } |
302 | 312 |
303 AlarmPref::AlarmPref() { | 313 // AlarmManager::Alarm |
314 | |
315 Alarm::Alarm() | |
316 : js_alarm(new extensions::api::alarms::Alarm()) { | |
304 } | 317 } |
305 | 318 |
306 AlarmPref::~AlarmPref() { | 319 Alarm::Alarm(const std::string& name, |
320 const extensions::api::alarms::AlarmOneShotCreateInfo& create_info, | |
321 base::TimeDelta min_granularity, | |
322 TimeProvider now) | |
323 : js_alarm(new extensions::api::alarms::Alarm()) { | |
324 js_alarm->name = name; | |
325 if (create_info.delay_in_minutes.get()) { | |
326 // Relative scheduling. | |
327 base::TimeDelta delay = TimeDeltaFromDelay(*create_info.delay_in_minutes); | |
328 js_alarm->scheduled_time = (now() + delay).ToJsTime(); | |
329 granularity = std::max(min_granularity, delay); | |
330 } else { | |
331 // Absolute scheduling. | |
332 CHECK(create_info.time.get()) | |
333 << "ValidateAlarmOneShotCreateInfo in alarms_api.cc should have " | |
334 << "prevented this call."; | |
335 js_alarm->scheduled_time = *create_info.time; | |
336 granularity = | |
337 std::max(min_granularity, | |
338 base::Time::FromJsTime(js_alarm->scheduled_time) - now()); | |
339 } | |
340 } | |
341 | |
342 Alarm::Alarm( | |
343 const std::string& name, | |
344 const extensions::api::alarms::AlarmRepeatingCreateInfo& create_info, | |
345 base::TimeDelta min_granularity, | |
346 TimeProvider now) | |
347 : js_alarm(new extensions::api::alarms::Alarm()) { | |
348 js_alarm->name = name; | |
349 base::TimeDelta delay = TimeDeltaFromDelay(create_info.period_in_minutes); | |
350 js_alarm->scheduled_time = (now() + delay).ToJsTime(); | |
351 js_alarm->period_in_minutes.reset( | |
352 new double(create_info.period_in_minutes)); | |
353 granularity = std::max(min_granularity, delay); | |
354 } | |
355 | |
356 Alarm::~Alarm() { | |
307 } | 357 } |
308 | 358 |
309 } // namespace extensions | 359 } // namespace extensions |
OLD | NEW |