Index: chrome/browser/extensions/api/alarms/alarm_manager.cc |
diff --git a/chrome/browser/extensions/api/alarms/alarm_manager.cc b/chrome/browser/extensions/api/alarms/alarm_manager.cc |
index 17a48898c3b2317fc039120069fcbe6af7426cbb..f6c508012f96ad3865888c74cfd67e9a17be1bfe 100644 |
--- a/chrome/browser/extensions/api/alarms/alarm_manager.cc |
+++ b/chrome/browser/extensions/api/alarms/alarm_manager.cc |
@@ -9,8 +9,12 @@ |
#include "base/message_loop.h" |
#include "base/values.h" |
#include "chrome/browser/extensions/extension_event_router.h" |
+#include "chrome/browser/extensions/extension_prefs.h" |
+#include "chrome/browser/extensions/extension_service.h" |
#include "chrome/browser/extensions/extension_system.h" |
#include "chrome/browser/profiles/profile.h" |
+#include "chrome/common/chrome_notification_types.h" |
+#include "content/public/browser/notification_service.h" |
namespace extensions { |
@@ -42,6 +46,8 @@ class DefaultAlarmDelegate : public AlarmManager::Delegate { |
AlarmManager::AlarmManager(Profile* profile) |
: profile_(profile), |
delegate_(new DefaultAlarmDelegate(profile)) { |
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
+ content::Source<Profile>(profile_)); |
} |
AlarmManager::~AlarmManager() { |
@@ -49,21 +55,9 @@ AlarmManager::~AlarmManager() { |
void AlarmManager::AddAlarm(const std::string& extension_id, |
const linked_ptr<Alarm>& alarm) { |
- // TODO(mpcomplete): Better handling of granularity. |
- // http://crbug.com/122683 |
- |
- // Override any old alarm with the same name. |
- AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name); |
- if (old_alarm.first != alarms_.end()) |
- RemoveAlarmIterator(old_alarm); |
- |
- alarms_[extension_id].push_back(alarm); |
- base::Timer* timer = new base::Timer(true, alarm->repeating); |
- timers_[alarm.get()] = make_linked_ptr(timer); |
- timer->Start(FROM_HERE, |
- base::TimeDelta::FromSeconds(alarm->delay_in_seconds), |
- base::Bind(&AlarmManager::OnAlarm, base::Unretained(this), |
- extension_id, alarm->name)); |
+ AddAlarmImpl(extension_id, alarm, |
+ base::TimeDelta::FromSeconds(alarm->delay_in_seconds)); |
+ WriteToPrefs(extension_id); |
} |
const AlarmManager::Alarm* AlarmManager::GetAlarm( |
@@ -102,7 +96,9 @@ bool AlarmManager::RemoveAlarm(const std::string& extension_id, |
AlarmIterator it = GetAlarmIterator(extension_id, name); |
if (it.first == alarms_.end()) |
return false; |
+ |
RemoveAlarmIterator(it); |
+ WriteToPrefs(extension_id); |
return true; |
} |
@@ -117,6 +113,7 @@ void AlarmManager::RemoveAllAlarms(const std::string& extension_id) { |
RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); |
CHECK(alarms_.find(extension_id) == alarms_.end()); |
+ WriteToPrefs(extension_id); |
} |
void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { |
@@ -135,10 +132,106 @@ void AlarmManager::OnAlarm(const std::string& extension_id, |
const std::string& name) { |
AlarmIterator it = GetAlarmIterator(extension_id, name); |
CHECK(it.first != alarms_.end()); |
- delegate_->OnAlarm(extension_id, *it.second->get()); |
+ const Alarm* alarm = it.second->get(); |
+ delegate_->OnAlarm(extension_id, *alarm); |
- if (!(*it.second)->repeating) |
+ if (!alarm->repeating) { |
RemoveAlarmIterator(it); |
+ } else { |
+ // Restart the timer, since it may have been set with a shorter delay |
+ // initially. |
+ base::Timer* timer = timers_[alarm].get(); |
+ timer->Start(FROM_HERE, |
+ base::TimeDelta::FromSeconds(alarm->delay_in_seconds), |
+ base::Bind(&AlarmManager::OnAlarm, base::Unretained(this), |
+ extension_id, alarm->name)); |
+ } |
+ |
+ WriteToPrefs(extension_id); |
+} |
+ |
+void AlarmManager::AddAlarmImpl(const std::string& extension_id, |
+ const linked_ptr<Alarm>& alarm, |
+ base::TimeDelta timer_delay) { |
+ // Override any old alarm with the same name. |
+ AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name); |
+ if (old_alarm.first != alarms_.end()) |
+ RemoveAlarmIterator(old_alarm); |
+ |
+ alarms_[extension_id].push_back(alarm); |
+ |
+ base::Timer* timer = new base::Timer(true, alarm->repeating); |
+ timers_[alarm.get()] = make_linked_ptr(timer); |
+ timer->Start(FROM_HERE, |
+ timer_delay, |
+ base::Bind(&AlarmManager::OnAlarm, base::Unretained(this), |
+ extension_id, alarm->name)); |
+} |
+ |
+void AlarmManager::WriteToPrefs(const std::string& extension_id) { |
+ ExtensionService* service = |
+ ExtensionSystem::Get(profile_)->extension_service(); |
+ if (!service || !service->extension_prefs()) |
+ return; |
+ |
+ std::vector<AlarmPref> alarm_prefs; |
+ |
+ AlarmMap::iterator list = alarms_.find(extension_id); |
+ if (list != alarms_.end()) { |
+ for (AlarmList::iterator it = list->second.begin(); |
+ it != list->second.end(); ++it) { |
+ base::Timer* timer = timers_[it->get()].get(); |
+ base::TimeDelta delay = |
+ timer->desired_run_time() - base::TimeTicks::Now(); |
+ AlarmPref pref; |
+ pref.alarm = *it; |
+ pref.scheduled_run_time = base::Time::Now() + delay; |
+ alarm_prefs.push_back(pref); |
+ } |
+ } |
+ |
+ service->extension_prefs()->SetRegisteredAlarms(extension_id, alarm_prefs); |
+} |
+ |
+void AlarmManager::ReadFromPrefs(const std::string& extension_id) { |
+ ExtensionService* service = |
+ ExtensionSystem::Get(profile_)->extension_service(); |
+ if (!service || !service->extension_prefs()) |
+ return; |
+ |
+ std::vector<AlarmPref> alarm_prefs = |
+ service->extension_prefs()->GetRegisteredAlarms(extension_id); |
+ for (size_t i = 0; i < alarm_prefs.size(); ++i) { |
+ base::TimeDelta delay = |
+ alarm_prefs[i].scheduled_run_time - base::Time::Now(); |
+ if (delay < base::TimeDelta::FromSeconds(0)) |
+ delay = base::TimeDelta::FromSeconds(0); |
+ |
+ AddAlarmImpl(extension_id, alarm_prefs[i].alarm, delay); |
+ } |
+} |
+ |
+void AlarmManager::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ switch (type) { |
+ case chrome::NOTIFICATION_EXTENSION_LOADED: { |
+ const Extension* extension = |
+ content::Details<const Extension>(details).ptr(); |
+ ReadFromPrefs(extension->id()); |
+ break; |
+ } |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+AlarmPref::AlarmPref() { |
+} |
+ |
+AlarmPref::~AlarmPref() { |
} |
} // namespace extensions |