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" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/common/extensions/api/alarms.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/state_store.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace alarms = api::alarms; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A list of alarms that this extension has set. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRegisteredAlarms[] = "alarms"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAlarmGranularity[] = "granularity"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The minimum period between polling for alarms to run. 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const base::TimeDelta kDefaultMinPollPeriod() { 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return base::TimeDelta::FromDays(1); 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DefaultAlarmDelegate : public AlarmManager::Delegate { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) explicit DefaultAlarmDelegate(content::BrowserContext* context) 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : browser_context_(context) {} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DefaultAlarmDelegate() {} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAlarm(const std::string& extension_id, 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Alarm& alarm) OVERRIDE { 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::ListValue> args(new base::ListValue()); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(alarm.js_alarm->ToValue().release()); 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) args.Pass())); 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter::Get(browser_context_) 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ->DispatchEventToExtension(extension_id, event.Pass()); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::BrowserContext* browser_context_; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a TimeDelta from a delay as specified in the API. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::TimeDelta::FromMicroseconds( 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delay_in_minutes * base::Time::kMicrosecondsPerMinute); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<Alarm> AlarmsFromValue(const base::ListValue* list) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Alarm> alarms; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < list->GetSize(); ++i) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue* alarm_dict = NULL; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Alarm alarm; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list->GetDictionary(i, &alarm_dict) && 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) api::alarms::Alarm::Populate(*alarm_dict, alarm.js_alarm.get())) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value* time_value = NULL; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alarm_dict->Get(kAlarmGranularity, &time_value)) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::GetValueAsTimeDelta(*time_value, &alarm.granularity); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms.push_back(alarm); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return alarms; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<base::ListValue> AlarmsToValue(const std::vector<Alarm>& alarms) { 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::ListValue> list(new base::ListValue()); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < alarms.size(); ++i) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> alarm = 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms[i].js_alarm->ToValue().Pass(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm->Set(kAlarmGranularity, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CreateTimeDeltaValue(alarms[i].granularity)); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list->Append(alarm.release()); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return list.Pass(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AlarmManager 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AlarmManager::AlarmManager(content::BrowserContext* context) 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : browser_context_(context), 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) clock_(new base::DefaultClock()), 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delegate_(new DefaultAlarmDelegate(context)), 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_(this) { 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StateStore* storage = ExtensionSystem::Get(browser_context_)->state_store(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (storage) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage->RegisterKey(kRegisteredAlarms); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AlarmManager::~AlarmManager() { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::AddAlarm(const std::string& extension_id, 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const Alarm& alarm, 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const AddAlarmCallback& callback) { 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::AddAlarmWhenReady, AsWeakPtr(), alarm, callback)); 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAlarm(const std::string& extension_id, 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& name, 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const GetAlarmCallback& callback) { 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::GetAlarmWhenReady, AsWeakPtr(), name, callback)); 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAllAlarms( 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id, const GetAllAlarmsCallback& callback) { 1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::GetAllAlarmsWhenReady, AsWeakPtr(), callback)); 1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAlarm(const std::string& extension_id, 1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& name, 1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAlarmCallback& callback) { 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::RemoveAlarmWhenReady, AsWeakPtr(), name, callback)); 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAllAlarms(const std::string& extension_id, 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAllAlarmsCallback& callback) { 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RunWhenReady(extension_id, base::Bind( 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &AlarmManager::RemoveAllAlarmsWhenReady, AsWeakPtr(), callback)); 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::AddAlarmWhenReady(const Alarm& alarm, 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const AddAlarmCallback& callback, 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddAlarmImpl(extension_id, alarm); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteToStorage(extension_id); 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAlarmWhenReady(const std::string& name, 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const GetAlarmCallback& callback, 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmIterator it = GetAlarmIterator(extension_id, name); 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(it.first != alarms_.end() ? &*it.second : NULL); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::GetAllAlarmsWhenReady(const GetAllAlarmsCallback& callback, 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(list != alarms_.end() ? &list->second : NULL); 1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAlarmWhenReady(const std::string& name, 1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAlarmCallback& callback, 1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id) { 1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AlarmIterator it = GetAlarmIterator(extension_id, name); 1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (it.first == alarms_.end()) { 1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(false); 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RemoveAlarmIterator(it); 1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) WriteToStorage(extension_id); 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(true); 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RemoveAllAlarmsWhenReady( 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const RemoveAllAlarmsCallback& callback, const std::string& extension_id) { 1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (list != alarms_.end()) { 1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Note: I'm using indices rather than iterators here because 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // RemoveAlarmIterator will delete the list when it becomes empty. 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0, size = list->second.size(); i < size; ++i) 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CHECK(alarms_.find(extension_id) == alarms_.end()); 1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) WriteToStorage(extension_id); 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback.Run(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AlarmManager::AlarmIterator AlarmManager::GetAlarmIterator( 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, const std::string& name) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list == alarms_.end()) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return make_pair(alarms_.end(), AlarmList::iterator()); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmList::iterator it = list->second.begin(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != list->second.end(); ++it) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->js_alarm->name == name) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return make_pair(list, it); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return make_pair(alarms_.end(), AlarmList::iterator()); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AlarmManager::SetClockForTesting(base::Clock* clock) { 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) clock_.reset(clock); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<AlarmManager> > 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) g_factory = LAZY_INSTANCE_INITIALIZER; 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<AlarmManager>* 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AlarmManager::GetFactoryInstance() { 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AlarmManager* AlarmManager::Get(content::BrowserContext* browser_context) { 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return BrowserContextKeyedAPIFactory<AlarmManager>::Get(browser_context); 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmList& list = iter.first->second; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list.erase(iter.second); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list.empty()) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms_.erase(iter.first); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel the timer if there are no more alarms. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't need to reschedule the poll otherwise, because in 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the worst case we would just poll one extra time. 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (alarms_.empty()) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_poll_time_ = base::Time(); 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::OnAlarm(AlarmIterator it) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(it.first != alarms_.end()); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Alarm& alarm = *it.second; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extension_id_copy(it.first->first); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnAlarm(extension_id_copy, alarm); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update our scheduled time for the next alarm. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (double* period_in_minutes = 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm.js_alarm->period_in_minutes.get()) { 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the timer's delay in JS time (i.e., convert it from minutes to 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // milliseconds). 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) double period_in_js_time = 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *period_in_minutes * base::Time::kMicrosecondsPerMinute / 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time::kMicrosecondsPerMillisecond; 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Find out how many periods have transpired since the alarm last went off 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // (it's possible that we missed some). 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int transpired_periods = 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (last_poll_time_.ToJsTime() - alarm.js_alarm->scheduled_time) / 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) period_in_js_time; 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Schedule the alarm for the next period that is in-line with the original 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // scheduling. 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) alarm.js_alarm->scheduled_time += 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) period_in_js_time * (transpired_periods + 1); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveAlarmIterator(it); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteToStorage(extension_id_copy); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::AddAlarmImpl(const std::string& extension_id, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Alarm& alarm) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Override any old alarm with the same name. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmIterator old_alarm = GetAlarmIterator(extension_id, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm.js_alarm->name); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_alarm.first != alarms_.end()) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveAlarmIterator(old_alarm); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms_[extension_id].push_back(alarm); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time alarm_time = 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time::FromJsTime(alarm.js_alarm->scheduled_time); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (next_poll_time_.is_null() || alarm_time < next_poll_time_) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetNextPollTime(alarm_time); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::WriteToStorage(const std::string& extension_id) { 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StateStore* storage = ExtensionSystem::Get(browser_context_)->state_store(); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!storage) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::Value> alarms; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator list = alarms_.find(extension_id); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list != alarms_.end()) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms.reset(AlarmsToValue(list->second).release()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms.reset(AlarmsToValue(std::vector<Alarm>()).release()); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage->SetExtensionValue(extension_id, kRegisteredAlarms, alarms.Pass()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::ReadFromStorage(const std::string& extension_id, 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ListValue* list = NULL; 3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (value.get() && value->GetAsList(&list)) { 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<Alarm> alarm_states = AlarmsFromValue(list); 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0; i < alarm_states.size(); ++i) 3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AddAlarmImpl(extension_id, alarm_states[i]); 3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ReadyQueue& extension_ready_queue = ready_actions_[extension_id]; 3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) while (!extension_ready_queue.empty()) { 3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extension_ready_queue.front().Run(extension_id); 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extension_ready_queue.pop(); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ready_actions_.erase(extension_id); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AlarmManager::SetNextPollTime(const base::Time& time) { 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_poll_time_ = time; 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) timer_.Start(FROM_HERE, 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::max(base::TimeDelta::FromSeconds(0), time - clock_->Now()), 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &AlarmManager::PollAlarms); 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AlarmManager::ScheduleNextPoll() { 3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // If there are no alarms, stop the timer. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alarms_.empty()) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_.Stop(); 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) next_poll_time_ = base::Time(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Find the soonest alarm that is scheduled to run and the smallest 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // granularity of any alarm. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // alarms_ guarantees that none of its contained lists are empty. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time soonest_alarm_time = base::Time::FromJsTime( 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarms_.begin()->second.begin()->js_alarm->scheduled_time); 338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeDelta min_granularity = kDefaultMinPollPeriod(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmMap::const_iterator m_it = alarms_.begin(), m_end = alarms_.end(); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m_it != m_end; ++m_it) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmList::const_iterator l_it = m_it->second.begin(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l_it != m_it->second.end(); ++l_it) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time cur_alarm_time = 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::FromJsTime(l_it->js_alarm->scheduled_time); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cur_alarm_time < soonest_alarm_time) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) soonest_alarm_time = cur_alarm_time; 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (l_it->granularity < min_granularity) 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) min_granularity = l_it->granularity; 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta cur_alarm_delta = cur_alarm_time - last_poll_time_; 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (cur_alarm_delta < l_it->minimum_granularity) 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cur_alarm_delta = l_it->minimum_granularity; 3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (cur_alarm_delta < min_granularity) 3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) min_granularity = cur_alarm_delta; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time next_poll(last_poll_time_ + min_granularity); 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the next alarm is more than min_granularity in the future, wait for it. 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Otherwise, only poll as often as min_granularity. 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // As a special case, if we've never checked for an alarm before 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (e.g. during startup), let alarms fire asap. 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_poll_time_.is_null() || next_poll < soonest_alarm_time) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_poll = soonest_alarm_time; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule the poll. 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetNextPollTime(next_poll); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlarmManager::PollAlarms() { 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_poll_time_ = clock_->Now(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run any alarms scheduled in the past. OnAlarm uses vector::erase to remove 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // elements from the AlarmList, and map::erase to remove AlarmLists from the 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AlarmMap. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AlarmMap::iterator m_it = alarms_.begin(), m_end = alarms_.end(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m_it != m_end;) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmMap::iterator cur_extension = m_it++; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate (a) backwards so that removing elements doesn't affect 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // upcoming iterations, and (b) with indices so that if the last 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iteration destroys the AlarmList, I'm not about to use the end 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iterator that the destruction invalidates. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = cur_extension->second.size(); i > 0; --i) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlarmList::iterator cur_alarm = cur_extension->second.begin() + i - 1; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::Time::FromJsTime(cur_alarm->js_alarm->scheduled_time) <= 3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) last_poll_time_) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnAlarm(make_pair(cur_extension, cur_alarm)); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleNextPoll(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)static void RemoveAllOnUninstallCallback() {} 3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AlarmManager::RunWhenReady( 3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& extension_id, const ReadyAction& action) { 3993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ReadyMap::iterator it = ready_actions_.find(extension_id); 4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (it == ready_actions_.end()) 4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) action.Run(extension_id); 4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) else 4043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) it->second.push(action); 4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AlarmManager::OnExtensionLoaded(content::BrowserContext* browser_context, 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const Extension* extension) { 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StateStore* storage = ExtensionSystem::Get(browser_context_)->state_store(); 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (storage) { 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ready_actions_.insert(ReadyMap::value_type(extension->id(), ReadyQueue())); 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) storage->GetExtensionValue( 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension->id(), 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kRegisteredAlarms, 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind( 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &AlarmManager::ReadFromStorage, AsWeakPtr(), extension->id())); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AlarmManager::OnExtensionUninstalled( 421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension, 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UninstallReason reason) { 424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RemoveAllAlarms(extension->id(), base::Bind(RemoveAllOnUninstallCallback)); 425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AlarmManager::Alarm 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Alarm::Alarm() 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : js_alarm(new api::alarms::Alarm()) { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Alarm::Alarm(const std::string& name, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const api::alarms::AlarmCreateInfo& create_info, 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta min_granularity, 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time now) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : js_alarm(new api::alarms::Alarm()) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) js_alarm->name = name; 4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) minimum_granularity = min_granularity; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_info.when.get()) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Absolute scheduling. 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) js_alarm->scheduled_time = *create_info.when; 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) granularity = base::Time::FromJsTime(js_alarm->scheduled_time) - now; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Relative scheduling. 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double* delay_in_minutes = create_info.delay_in_minutes.get(); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delay_in_minutes == NULL) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delay_in_minutes = create_info.period_in_minutes.get(); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(delay_in_minutes != NULL) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "ValidateAlarmCreateInfo in alarms_api.cc should have " 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "prevented this call."; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta delay = TimeDeltaFromDelay(*delay_in_minutes); 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) js_alarm->scheduled_time = (now + delay).ToJsTime(); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) granularity = delay; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (granularity < min_granularity) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) granularity = min_granularity; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for repetition. 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_info.period_in_minutes.get()) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) js_alarm->period_in_minutes.reset( 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new double(*create_info.period_in_minutes)); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Alarm::~Alarm() { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 472