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

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

Issue 145353013: Do not reschedule all alarms when adding a new alarm (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Yoyo's Created 6 years, 10 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
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/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 229
230 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { 230 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) {
231 AlarmList& list = iter.first->second; 231 AlarmList& list = iter.first->second;
232 list.erase(iter.second); 232 list.erase(iter.second);
233 if (list.empty()) 233 if (list.empty())
234 alarms_.erase(iter.first); 234 alarms_.erase(iter.first);
235 235
236 // Cancel the timer if there are no more alarms. 236 // Cancel the timer if there are no more alarms.
237 // We don't need to reschedule the poll otherwise, because in 237 // We don't need to reschedule the poll otherwise, because in
238 // the worst case we would just poll one extra time. 238 // the worst case we would just poll one extra time.
239 if (alarms_.empty()) 239 if (alarms_.empty()) {
240 timer_.Stop(); 240 timer_.Stop();
241 next_poll_time_ = base::Time();
242 }
241 } 243 }
242 244
243 void AlarmManager::OnAlarm(AlarmIterator it) { 245 void AlarmManager::OnAlarm(AlarmIterator it) {
244 CHECK(it.first != alarms_.end()); 246 CHECK(it.first != alarms_.end());
245 Alarm& alarm = *it.second; 247 Alarm& alarm = *it.second;
246 std::string extension_id_copy(it.first->first); 248 std::string extension_id_copy(it.first->first);
247 delegate_->OnAlarm(extension_id_copy, alarm); 249 delegate_->OnAlarm(extension_id_copy, alarm);
248 250
249 // Update our scheduled time for the next alarm. 251 // Update our scheduled time for the next alarm.
250 if (double* period_in_minutes = 252 if (double* period_in_minutes =
(...skipping 20 matching lines...) Expand all
271 273
272 void AlarmManager::AddAlarmImpl(const std::string& extension_id, 274 void AlarmManager::AddAlarmImpl(const std::string& extension_id,
273 const Alarm& alarm) { 275 const Alarm& alarm) {
274 // Override any old alarm with the same name. 276 // Override any old alarm with the same name.
275 AlarmIterator old_alarm = GetAlarmIterator(extension_id, 277 AlarmIterator old_alarm = GetAlarmIterator(extension_id,
276 alarm.js_alarm->name); 278 alarm.js_alarm->name);
277 if (old_alarm.first != alarms_.end()) 279 if (old_alarm.first != alarms_.end())
278 RemoveAlarmIterator(old_alarm); 280 RemoveAlarmIterator(old_alarm);
279 281
280 alarms_[extension_id].push_back(alarm); 282 alarms_[extension_id].push_back(alarm);
281 283 base::Time alarm_time =
282 ScheduleNextPoll(); 284 base::Time::FromJsTime(alarm.js_alarm->scheduled_time);
285 if (next_poll_time_.is_null() || alarm_time < next_poll_time_)
286 SetNextPollTime(alarm_time);
283 } 287 }
284 288
285 void AlarmManager::WriteToStorage(const std::string& extension_id) { 289 void AlarmManager::WriteToStorage(const std::string& extension_id) {
286 StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); 290 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
287 if (!storage) 291 if (!storage)
288 return; 292 return;
289 293
290 scoped_ptr<base::Value> alarms; 294 scoped_ptr<base::Value> alarms;
291 AlarmMap::iterator list = alarms_.find(extension_id); 295 AlarmMap::iterator list = alarms_.find(extension_id);
292 if (list != alarms_.end()) 296 if (list != alarms_.end())
(...skipping 13 matching lines...) Expand all
306 } 310 }
307 311
308 ReadyQueue& extension_ready_queue = ready_actions_[extension_id]; 312 ReadyQueue& extension_ready_queue = ready_actions_[extension_id];
309 while (!extension_ready_queue.empty()) { 313 while (!extension_ready_queue.empty()) {
310 extension_ready_queue.front().Run(extension_id); 314 extension_ready_queue.front().Run(extension_id);
311 extension_ready_queue.pop(); 315 extension_ready_queue.pop();
312 } 316 }
313 ready_actions_.erase(extension_id); 317 ready_actions_.erase(extension_id);
314 } 318 }
315 319
320 void AlarmManager::SetNextPollTime(const base::Time& time) {
321 next_poll_time_ = time;
322 timer_.Start(FROM_HERE,
323 std::max(base::TimeDelta::FromSeconds(0), time - clock_->Now()),
324 this,
325 &AlarmManager::PollAlarms);
326 }
327
316 void AlarmManager::ScheduleNextPoll() { 328 void AlarmManager::ScheduleNextPoll() {
317 // If there are no alarms, stop the timer. 329 // If there are no alarms, stop the timer.
318 if (alarms_.empty()) { 330 if (alarms_.empty()) {
319 timer_.Stop(); 331 timer_.Stop();
332 next_poll_time_ = base::Time();
320 return; 333 return;
321 } 334 }
322 335
323 // TODO(yoz): Try not to reschedule every single time if we're adding
324 // a lot of alarms.
325
326 // Find the soonest alarm that is scheduled to run and the smallest 336 // Find the soonest alarm that is scheduled to run and the smallest
327 // granularity of any alarm. 337 // granularity of any alarm.
328 // alarms_ guarantees that none of its contained lists are empty. 338 // alarms_ guarantees that none of its contained lists are empty.
329 base::Time soonest_alarm_time = base::Time::FromJsTime( 339 base::Time soonest_alarm_time = base::Time::FromJsTime(
330 alarms_.begin()->second.begin()->js_alarm->scheduled_time); 340 alarms_.begin()->second.begin()->js_alarm->scheduled_time);
331 base::TimeDelta min_granularity = kDefaultMinPollPeriod(); 341 base::TimeDelta min_granularity = kDefaultMinPollPeriod();
332 for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end(); 342 for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end();
333 m_it != m_end; ++m_it) { 343 m_it != m_end; ++m_it) {
334 for (AlarmList::const_iterator l_it = m_it->second.begin(); 344 for (AlarmList::const_iterator l_it = m_it->second.begin();
335 l_it != m_it->second.end(); ++l_it) { 345 l_it != m_it->second.end(); ++l_it) {
(...skipping 13 matching lines...) Expand all
349 359
350 base::Time next_poll(last_poll_time_ + min_granularity); 360 base::Time next_poll(last_poll_time_ + min_granularity);
351 // If the next alarm is more than min_granularity in the future, wait for it. 361 // If the next alarm is more than min_granularity in the future, wait for it.
352 // Otherwise, only poll as often as min_granularity. 362 // Otherwise, only poll as often as min_granularity.
353 // As a special case, if we've never checked for an alarm before 363 // As a special case, if we've never checked for an alarm before
354 // (e.g. during startup), let alarms fire asap. 364 // (e.g. during startup), let alarms fire asap.
355 if (last_poll_time_.is_null() || next_poll < soonest_alarm_time) 365 if (last_poll_time_.is_null() || next_poll < soonest_alarm_time)
356 next_poll = soonest_alarm_time; 366 next_poll = soonest_alarm_time;
357 367
358 // Schedule the poll. 368 // Schedule the poll.
359 test_next_poll_time_ = next_poll; 369 SetNextPollTime(next_poll);
360 base::TimeDelta delay = std::max(base::TimeDelta::FromSeconds(0),
361 next_poll - clock_->Now());
362 timer_.Start(FROM_HERE,
363 delay,
364 this,
365 &AlarmManager::PollAlarms);
366 } 370 }
367 371
368 void AlarmManager::PollAlarms() { 372 void AlarmManager::PollAlarms() {
369 last_poll_time_ = clock_->Now(); 373 last_poll_time_ = clock_->Now();
370 374
371 // Run any alarms scheduled in the past. OnAlarm uses vector::erase to remove 375 // Run any alarms scheduled in the past. OnAlarm uses vector::erase to remove
372 // elements from the AlarmList, and map::erase to remove AlarmLists from the 376 // elements from the AlarmList, and map::erase to remove AlarmLists from the
373 // AlarmMap. 377 // AlarmMap.
374 for (AlarmMap::iterator m_it = alarms_.begin(), m_end = alarms_.end(); 378 for (AlarmMap::iterator m_it = alarms_.begin(), m_end = alarms_.end();
375 m_it != m_end;) { 379 m_it != m_end;) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 if (create_info.period_in_minutes.get()) { 476 if (create_info.period_in_minutes.get()) {
473 js_alarm->period_in_minutes.reset( 477 js_alarm->period_in_minutes.reset(
474 new double(*create_info.period_in_minutes)); 478 new double(*create_info.period_in_minutes));
475 } 479 }
476 } 480 }
477 481
478 Alarm::~Alarm() { 482 Alarm::~Alarm() {
479 } 483 }
480 484
481 } // namespace extensions 485 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/alarms/alarm_manager.h ('k') | chrome/browser/extensions/api/alarms/alarms_api_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698