alarm_manager.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/alarms/alarm_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/lazy_instance.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/time/clock.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/time/default_clock.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/value_conversions.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/state_store.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/common/extensions/api/alarms.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace alarms = api::alarms; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A list of alarms that this extension has set. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRegisteredAlarms[] = "alarms"; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAlarmGranularity[] = "granularity"; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The minimum period between polling for alarms to run. 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const base::TimeDelta kDefaultMinPollPeriod() { 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return base::TimeDelta::FromDays(1); 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DefaultAlarmDelegate : public AlarmManager::Delegate { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DefaultAlarmDelegate() {} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAlarm(const std::string& extension_id, 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Alarm& alarm) OVERRIDE { 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::ListValue> args(new base::ListValue()); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(alarm.js_alarm->ToValue().release()); 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) args.Pass())); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension( 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_id, event.Pass()); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile_; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a TimeDelta from a delay as specified in the API. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::TimeDelta::FromMicroseconds( 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delay_in_minutes * base::Time::kMicrosecondsPerMinute); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<Alarm> AlarmsFromValue(const base::ListValue* list) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Alarm> alarms; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < list->GetSize(); ++i) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue* alarm_dict = NULL; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Alarm alarm; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list->GetDictionary(i, &alarm_dict) && 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) api::alarms::Alarm::Populate(*alarm_dict, alarm.js_alarm.get())) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value* time_value = NULL; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alarm_dict->Get(kAlarmGranularity, &time_value)) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::GetValueAsTimeDelta(*time_value, &alarm.granularity); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms.push_back(alarm); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return alarms; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<base::ListValue> AlarmsToValue(const std::vector<Alarm>& alarms) { 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::ListValue> list(new base::ListValue()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < alarms.size(); ++i) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> alarm = 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms[i].js_alarm->ToValue().Pass(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm->Set(kAlarmGranularity, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CreateTimeDeltaValue(alarms[i].granularity)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list->Append(alarm.release()); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return list.Pass(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AlarmManager 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AlarmManager::AlarmManager(Profile* profile) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile_(profile), 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) clock_(new base::DefaultClock()), 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_(new DefaultAlarmDelegate(profile)) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(profile_)); 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch content::Source<Profile>(profile_)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (storage) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage->RegisterKey(kRegisteredAlarms); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AlarmManager::~AlarmManager() { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::AddAlarm(const std::string& extension_id, 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const Alarm& alarm, 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const AddAlarmCallback& callback) { 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::AddAlarmWhenReady, AsWeakPtr(), alarm, callback)); 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAlarm(const std::string& extension_id, 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& name, 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const GetAlarmCallback& callback) { 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::GetAlarmWhenReady, AsWeakPtr(), name, callback)); 1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAllAlarms( 1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id, const GetAllAlarmsCallback& callback) { 1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::GetAllAlarmsWhenReady, AsWeakPtr(), callback)); 1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAlarm(const std::string& extension_id, 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& name, 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAlarmCallback& callback) { 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::RemoveAlarmWhenReady, AsWeakPtr(), name, callback)); 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAllAlarms(const std::string& extension_id, 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAllAlarmsCallback& callback) { 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::RemoveAllAlarmsWhenReady, AsWeakPtr(), callback)); 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::AddAlarmWhenReady(const Alarm& alarm, 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const AddAlarmCallback& callback, 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddAlarmImpl(extension_id, alarm); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteToStorage(extension_id); 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAlarmWhenReady(const std::string& name, 1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const GetAlarmCallback& callback, 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmIterator it = GetAlarmIterator(extension_id, name); 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(it.first != alarms_.end() ? &*it.second : NULL); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAllAlarmsWhenReady(const GetAllAlarmsCallback& callback, 1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(list != alarms_.end() ? &list->second : NULL); 1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAlarmWhenReady(const std::string& name, 1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAlarmCallback& callback, 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AlarmIterator it = GetAlarmIterator(extension_id, name); 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (it.first == alarms_.end()) { 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(false); 1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RemoveAlarmIterator(it); 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) WriteToStorage(extension_id); 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(true); 1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAllAlarmsWhenReady( 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAllAlarmsCallback& callback, const std::string& extension_id) { 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (list != alarms_.end()) { 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Note: I'm using indices rather than iterators here because 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // RemoveAlarmIterator will delete the list when it becomes empty. 1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0, size = list->second.size(); i < size; ++i) 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); 1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CHECK(alarms_.find(extension_id) == alarms_.end()); 1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) WriteToStorage(extension_id); 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AlarmManager::AlarmIterator AlarmManager::GetAlarmIterator( 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, const std::string& name) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list == alarms_.end()) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return make_pair(alarms_.end(), AlarmList::iterator()); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmList::iterator it = list->second.begin(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != list->second.end(); ++it) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->js_alarm->name == name) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return make_pair(list, it); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return make_pair(alarms_.end(), AlarmList::iterator()); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AlarmManager::SetClockForTesting(base::Clock* clock) { 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) clock_.reset(clock); 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static base::LazyInstance<ProfileKeyedAPIFactory<AlarmManager> > 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)g_factory = LAZY_INSTANCE_INITIALIZER; 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ProfileKeyedAPIFactory<AlarmManager>* AlarmManager::GetFactoryInstance() { 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AlarmManager* AlarmManager::Get(Profile* profile) { 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ProfileKeyedAPIFactory<AlarmManager>::GetForProfile(profile); 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmList& list = iter.first->second; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list.erase(iter.second); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list.empty()) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms_.erase(iter.first); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel the timer if there are no more alarms. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't need to reschedule the poll otherwise, because in 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the worst case we would just poll one extra time. 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (alarms_.empty()) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_poll_time_ = base::Time(); 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::OnAlarm(AlarmIterator it) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(it.first != alarms_.end()); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Alarm& alarm = *it.second; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extension_id_copy(it.first->first); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnAlarm(extension_id_copy, alarm); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update our scheduled time for the next alarm. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (double* period_in_minutes = 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm.js_alarm->period_in_minutes.get()) { 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the timer's delay in JS time (i.e., convert it from minutes to 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // milliseconds). 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) double period_in_js_time = 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *period_in_minutes * base::Time::kMicrosecondsPerMinute / 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time::kMicrosecondsPerMillisecond; 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Find out how many periods have transpired since the alarm last went off 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // (it's possible that we missed some). 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int transpired_periods = 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (last_poll_time_.ToJsTime() - alarm.js_alarm->scheduled_time) / 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) period_in_js_time; 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Schedule the alarm for the next period that is in-line with the original 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // scheduling. 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) alarm.js_alarm->scheduled_time += 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) period_in_js_time * (transpired_periods + 1); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveAlarmIterator(it); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteToStorage(extension_id_copy); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::AddAlarmImpl(const std::string& extension_id, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Alarm& alarm) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Override any old alarm with the same name. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmIterator old_alarm = GetAlarmIterator(extension_id, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm.js_alarm->name); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_alarm.first != alarms_.end()) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveAlarmIterator(old_alarm); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms_[extension_id].push_back(alarm); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time alarm_time = 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time::FromJsTime(alarm.js_alarm->scheduled_time); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (next_poll_time_.is_null() || alarm_time < next_poll_time_) 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetNextPollTime(alarm_time); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::WriteToStorage(const std::string& extension_id) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!storage) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::Value> alarms; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list != alarms_.end()) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms.reset(AlarmsToValue(list->second).release()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms.reset(AlarmsToValue(std::vector<Alarm>()).release()); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage->SetExtensionValue(extension_id, kRegisteredAlarms, alarms.Pass()); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::ReadFromStorage(const std::string& extension_id, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* list = NULL; 3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (value.get() && value->GetAsList(&list)) { 3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<Alarm> alarm_states = AlarmsFromValue(list); 3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0; i < alarm_states.size(); ++i) 3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AddAlarmImpl(extension_id, alarm_states[i]); 3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ReadyQueue& extension_ready_queue = ready_actions_[extension_id]; 3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) while (!extension_ready_queue.empty()) { 3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extension_ready_queue.front().Run(extension_id); 3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extension_ready_queue.pop(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ready_actions_.erase(extension_id); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AlarmManager::SetNextPollTime(const base::Time& time) { 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_poll_time_ = time; 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) timer_.Start(FROM_HERE, 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::max(base::TimeDelta::FromSeconds(0), time - clock_->Now()), 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &AlarmManager::PollAlarms); 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AlarmManager::ScheduleNextPoll() { 3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // If there are no alarms, stop the timer. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alarms_.empty()) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_poll_time_ = base::Time(); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Find the soonest alarm that is scheduled to run and the smallest 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // granularity of any alarm. 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // alarms_ guarantees that none of its contained lists are empty. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time soonest_alarm_time = base::Time::FromJsTime( 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms_.begin()->second.begin()->js_alarm->scheduled_time); 341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeDelta min_granularity = kDefaultMinPollPeriod(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end(); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m_it != m_end; ++m_it) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmList::const_iterator l_it = m_it->second.begin(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l_it != m_it->second.end(); ++l_it) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time cur_alarm_time = 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::FromJsTime(l_it->js_alarm->scheduled_time); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cur_alarm_time < soonest_alarm_time) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) soonest_alarm_time = cur_alarm_time; 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (l_it->granularity < min_granularity) 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) min_granularity = l_it->granularity; 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta cur_alarm_delta = cur_alarm_time - last_poll_time_; 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (cur_alarm_delta < l_it->minimum_granularity) 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cur_alarm_delta = l_it->minimum_granularity; 3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (cur_alarm_delta < min_granularity) 3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) min_granularity = cur_alarm_delta; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time next_poll(last_poll_time_ + min_granularity); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the next alarm is more than min_granularity in the future, wait for it. 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Otherwise, only poll as often as min_granularity. 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // As a special case, if we've never checked for an alarm before 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (e.g. during startup), let alarms fire asap. 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_poll_time_.is_null() || next_poll < soonest_alarm_time) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_poll = soonest_alarm_time; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule the poll. 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetNextPollTime(next_poll); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::PollAlarms() { 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_poll_time_ = clock_->Now(); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run any alarms scheduled in the past. OnAlarm uses vector::erase to remove 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // elements from the AlarmList, and map::erase to remove AlarmLists from the 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AlarmMap. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmMap::iterator m_it = alarms_.begin(), m_end = alarms_.end(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m_it != m_end;) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator cur_extension = m_it++; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate (a) backwards so that removing elements doesn't affect 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // upcoming iterations, and (b) with indices so that if the last 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iteration destroys the AlarmList, I'm not about to use the end 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iterator that the destruction invalidates. 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = cur_extension->second.size(); i > 0; --i) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmList::iterator cur_alarm = cur_extension->second.begin() + i - 1; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::Time::FromJsTime(cur_alarm->js_alarm->scheduled_time) <= 3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) last_poll_time_) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnAlarm(make_pair(cur_extension, cur_alarm)); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleNextPoll(); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)static void RemoveAllOnUninstallCallback() {} 3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RunWhenReady( 4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id, const ReadyAction& action) { 4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ReadyMap::iterator it = ready_actions_.find(extension_id); 4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (it == ready_actions_.end()) 4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) action.Run(extension_id); 4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) else 4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) it->second.push(action); 4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::Observe( 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_EXTENSION_LOADED: { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<const Extension>(details).ptr(); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StateStore* storage = ExtensionSystem::Get(profile_)->state_store(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (storage) { 4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ready_actions_.insert( 4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ReadyMap::value_type(extension->id(), ReadyQueue())); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage->GetExtensionValue(extension->id(), kRegisteredAlarms, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&AlarmManager::ReadFromStorage, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsWeakPtr(), extension->id())); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: { 4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const Extension* extension = 4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch content::Details<const Extension>(details).ptr(); 4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RemoveAllAlarms( 4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extension->id(), base::Bind(RemoveAllOnUninstallCallback)); 4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 4347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AlarmManager::Alarm 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Alarm::Alarm() 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : js_alarm(new api::alarms::Alarm()) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Alarm::Alarm(const std::string& name, 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const api::alarms::AlarmCreateInfo& create_info, 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta min_granularity, 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time now) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : js_alarm(new api::alarms::Alarm()) { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) js_alarm->name = name; 4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) minimum_granularity = min_granularity; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_info.when.get()) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Absolute scheduling. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) js_alarm->scheduled_time = *create_info.when; 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) granularity = base::Time::FromJsTime(js_alarm->scheduled_time) - now; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Relative scheduling. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double* delay_in_minutes = create_info.delay_in_minutes.get(); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delay_in_minutes == NULL) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delay_in_minutes = create_info.period_in_minutes.get(); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(delay_in_minutes != NULL) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "ValidateAlarmCreateInfo in alarms_api.cc should have " 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "prevented this call."; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta delay = TimeDeltaFromDelay(*delay_in_minutes); 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) js_alarm->scheduled_time = (now + delay).ToJsTime(); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) granularity = delay; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (granularity < min_granularity) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) granularity = min_granularity; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for repetition. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_info.period_in_minutes.get()) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) js_alarm->period_in_minutes.reset( 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new double(*create_info.period_in_minutes)); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Alarm::~Alarm() { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 486