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

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

Issue 10152008: Extension alarms now persist in Preferences. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: no more TimerInfo Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/alarms/alarm_manager.h" 5 #include "chrome/browser/extensions/api/alarms/alarm_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_writer.h" 8 #include "base/json/json_writer.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/values.h" 10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_event_router.h" 11 #include "chrome/browser/extensions/extension_event_router.h"
12 #include "chrome/browser/extensions/extension_prefs.h"
13 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_system.h" 14 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/chrome_notification_types.h"
17 #include "content/public/browser/notification_service.h"
14 18
15 namespace extensions { 19 namespace extensions {
16 20
17 namespace { 21 namespace {
18 22
19 const char kOnAlarmEvent[] = "experimental.alarms.onAlarm"; 23 const char kOnAlarmEvent[] = "experimental.alarms.onAlarm";
20 24
21 class DefaultAlarmDelegate : public AlarmManager::Delegate { 25 class DefaultAlarmDelegate : public AlarmManager::Delegate {
22 public: 26 public:
23 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} 27 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {}
(...skipping 11 matching lines...) Expand all
35 39
36 private: 40 private:
37 Profile* profile_; 41 Profile* profile_;
38 }; 42 };
39 43
40 } 44 }
41 45
42 AlarmManager::AlarmManager(Profile* profile) 46 AlarmManager::AlarmManager(Profile* profile)
43 : profile_(profile), 47 : profile_(profile),
44 delegate_(new DefaultAlarmDelegate(profile)) { 48 delegate_(new DefaultAlarmDelegate(profile)) {
49 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
50 content::Source<Profile>(profile_));
45 } 51 }
46 52
47 AlarmManager::~AlarmManager() { 53 AlarmManager::~AlarmManager() {
48 } 54 }
49 55
50 void AlarmManager::AddAlarm(const std::string& extension_id, 56 void AlarmManager::AddAlarm(const std::string& extension_id,
51 const linked_ptr<Alarm>& alarm) { 57 const linked_ptr<Alarm>& alarm) {
52 // TODO(mpcomplete): Better handling of granularity. 58 AddAlarmImpl(extension_id, alarm,
53 // http://crbug.com/122683 59 base::TimeDelta::FromSeconds(alarm->delay_in_seconds));
54 60 WriteToPrefs(extension_id);
55 // Override any old alarm with the same name.
56 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name);
57 if (old_alarm.first != alarms_.end())
58 RemoveAlarmIterator(old_alarm);
59
60 alarms_[extension_id].push_back(alarm);
61 base::Timer* timer = new base::Timer(true, alarm->repeating);
62 timers_[alarm.get()] = make_linked_ptr(timer);
63 timer->Start(FROM_HERE,
64 base::TimeDelta::FromSeconds(alarm->delay_in_seconds),
65 base::Bind(&AlarmManager::OnAlarm, base::Unretained(this),
66 extension_id, alarm->name));
67 } 61 }
68 62
69 const AlarmManager::Alarm* AlarmManager::GetAlarm( 63 const AlarmManager::Alarm* AlarmManager::GetAlarm(
70 const std::string& extension_id, const std::string& name) { 64 const std::string& extension_id, const std::string& name) {
71 AlarmIterator it = GetAlarmIterator(extension_id, name); 65 AlarmIterator it = GetAlarmIterator(extension_id, name);
72 if (it.first == alarms_.end()) 66 if (it.first == alarms_.end())
73 return NULL; 67 return NULL;
74 return it.second->get(); 68 return it.second->get();
75 } 69 }
76 70
(...skipping 18 matching lines...) Expand all
95 } 89 }
96 90
97 return make_pair(alarms_.end(), AlarmList::iterator()); 91 return make_pair(alarms_.end(), AlarmList::iterator());
98 } 92 }
99 93
100 bool AlarmManager::RemoveAlarm(const std::string& extension_id, 94 bool AlarmManager::RemoveAlarm(const std::string& extension_id,
101 const std::string& name) { 95 const std::string& name) {
102 AlarmIterator it = GetAlarmIterator(extension_id, name); 96 AlarmIterator it = GetAlarmIterator(extension_id, name);
103 if (it.first == alarms_.end()) 97 if (it.first == alarms_.end())
104 return false; 98 return false;
99
105 RemoveAlarmIterator(it); 100 RemoveAlarmIterator(it);
101 WriteToPrefs(extension_id);
106 return true; 102 return true;
107 } 103 }
108 104
109 void AlarmManager::RemoveAllAlarms(const std::string& extension_id) { 105 void AlarmManager::RemoveAllAlarms(const std::string& extension_id) {
110 AlarmMap::iterator list = alarms_.find(extension_id); 106 AlarmMap::iterator list = alarms_.find(extension_id);
111 if (list == alarms_.end()) 107 if (list == alarms_.end())
112 return; 108 return;
113 109
114 // Note: I'm using indices rather than iterators here because 110 // Note: I'm using indices rather than iterators here because
115 // RemoveAlarmIterator will delete the list when it becomes empty. 111 // RemoveAlarmIterator will delete the list when it becomes empty.
116 for (size_t i = 0, size = list->second.size(); i < size; ++i) 112 for (size_t i = 0, size = list->second.size(); i < size; ++i)
117 RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); 113 RemoveAlarmIterator(AlarmIterator(list, list->second.begin()));
118 114
119 CHECK(alarms_.find(extension_id) == alarms_.end()); 115 CHECK(alarms_.find(extension_id) == alarms_.end());
116 WriteToPrefs(extension_id);
120 } 117 }
121 118
122 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { 119 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) {
123 // Cancel the timer first. 120 // Cancel the timer first.
124 timers_[iter.second->get()]->Stop(); 121 timers_[iter.second->get()]->Stop();
125 timers_.erase(iter.second->get()); 122 timers_.erase(iter.second->get());
126 123
127 // Clean up our alarm list. 124 // Clean up our alarm list.
128 AlarmList& list = iter.first->second; 125 AlarmList& list = iter.first->second;
129 list.erase(iter.second); 126 list.erase(iter.second);
130 if (list.empty()) 127 if (list.empty())
131 alarms_.erase(iter.first); 128 alarms_.erase(iter.first);
132 } 129 }
133 130
134 void AlarmManager::OnAlarm(const std::string& extension_id, 131 void AlarmManager::OnAlarm(const std::string& extension_id,
135 const std::string& name) { 132 const std::string& name) {
136 AlarmIterator it = GetAlarmIterator(extension_id, name); 133 AlarmIterator it = GetAlarmIterator(extension_id, name);
137 CHECK(it.first != alarms_.end()); 134 CHECK(it.first != alarms_.end());
138 delegate_->OnAlarm(extension_id, *it.second->get()); 135 const Alarm* alarm = it.second->get();
136 delegate_->OnAlarm(extension_id, *alarm);
139 137
140 if (!(*it.second)->repeating) 138 if (!alarm->repeating) {
141 RemoveAlarmIterator(it); 139 RemoveAlarmIterator(it);
140 } else {
141 // Restart the timer, since it may have been set with a shorter delay
142 // initially.
143 base::Timer* timer = timers_[alarm].get();
144 timer->Start(FROM_HERE,
145 base::TimeDelta::FromSeconds(alarm->delay_in_seconds),
146 base::Bind(&AlarmManager::OnAlarm, base::Unretained(this),
147 extension_id, alarm->name));
148 }
149
150 WriteToPrefs(extension_id);
151 }
152
153 void AlarmManager::AddAlarmImpl(const std::string& extension_id,
154 const linked_ptr<Alarm>& alarm,
155 base::TimeDelta timer_delay) {
156 // Override any old alarm with the same name.
157 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name);
158 if (old_alarm.first != alarms_.end())
159 RemoveAlarmIterator(old_alarm);
160
161 alarms_[extension_id].push_back(alarm);
162
163 base::Timer* timer = new base::Timer(true, alarm->repeating);
164 timers_[alarm.get()] = make_linked_ptr(timer);
165 timer->Start(FROM_HERE,
166 timer_delay,
167 base::Bind(&AlarmManager::OnAlarm, base::Unretained(this),
168 extension_id, alarm->name));
169 }
170
171 void AlarmManager::WriteToPrefs(const std::string& extension_id) {
172 ExtensionService* service =
173 ExtensionSystem::Get(profile_)->extension_service();
174 if (!service || !service->extension_prefs())
175 return;
176
177 std::vector<AlarmPref> alarm_prefs;
178
179 AlarmMap::iterator list = alarms_.find(extension_id);
180 if (list != alarms_.end()) {
181 for (AlarmList::iterator it = list->second.begin();
182 it != list->second.end(); ++it) {
183 base::Timer* timer = timers_[it->get()].get();
184 base::TimeDelta delay =
185 timer->desired_run_time() - base::TimeTicks::Now();
186 AlarmPref pref;
187 pref.alarm = *it;
188 pref.scheduled_run_time = base::Time::Now() + delay;
189 alarm_prefs.push_back(pref);
190 }
191 }
192
193 service->extension_prefs()->SetRegisteredAlarms(extension_id, alarm_prefs);
194 }
195
196 void AlarmManager::ReadFromPrefs(const std::string& extension_id) {
197 ExtensionService* service =
198 ExtensionSystem::Get(profile_)->extension_service();
199 if (!service || !service->extension_prefs())
200 return;
201
202 std::vector<AlarmPref> alarm_prefs =
203 service->extension_prefs()->GetRegisteredAlarms(extension_id);
204 for (size_t i = 0; i < alarm_prefs.size(); ++i) {
205 base::TimeDelta delay =
206 alarm_prefs[i].scheduled_run_time - base::Time::Now();
207 if (delay < base::TimeDelta::FromSeconds(0))
208 delay = base::TimeDelta::FromSeconds(0);
209
210 AddAlarmImpl(extension_id, alarm_prefs[i].alarm, delay);
211 }
212 }
213
214 void AlarmManager::Observe(
215 int type,
216 const content::NotificationSource& source,
217 const content::NotificationDetails& details) {
218 switch (type) {
219 case chrome::NOTIFICATION_EXTENSION_LOADED: {
220 const Extension* extension =
221 content::Details<const Extension>(details).ptr();
222 ReadFromPrefs(extension->id());
223 break;
224 }
225 default:
226 NOTREACHED();
227 break;
228 }
229 }
230
231 AlarmPref::AlarmPref() {
232 }
233
234 AlarmPref::~AlarmPref() {
142 } 235 }
143 236
144 } // namespace extensions 237 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/alarms/alarm_manager.h ('k') | chrome/browser/extensions/extension_prefs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698