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

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

Issue 10545128: Unrevert r141537: Add extensions::StateStore and use that instead of (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix.crash Created 8 years, 6 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/time.h" 10 #include "base/time.h"
11 #include "base/value_conversions.h"
11 #include "base/values.h" 12 #include "base/values.h"
12 #include "chrome/browser/extensions/extension_event_router.h" 13 #include "chrome/browser/extensions/extension_event_router.h"
13 #include "chrome/browser/extensions/extension_prefs.h"
14 #include "chrome/browser/extensions/extension_service.h" 14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_system.h" 15 #include "chrome/browser/extensions/extension_system.h"
16 #include "chrome/browser/extensions/state_store.h"
16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/chrome_notification_types.h" 18 #include "chrome/common/chrome_notification_types.h"
18 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/notification_service.h"
19 20
20 namespace extensions { 21 namespace extensions {
21 22
22 namespace { 23 namespace {
23 24
24 const char kOnAlarmEvent[] = "alarms.onAlarm"; 25 const char kOnAlarmEvent[] = "alarms.onAlarm";
25 26
27 // A list of alarms that this extension has set.
28 const char kRegisteredAlarms[] = "alarms";
29 const char kAlarmScheduledRunTime[] = "scheduled_run_time";
30
26 // The minimum period between polling for alarms to run. 31 // The minimum period between polling for alarms to run.
27 const base::TimeDelta kDefaultMinPollPeriod = base::TimeDelta::FromMinutes(5); 32 const base::TimeDelta kDefaultMinPollPeriod = base::TimeDelta::FromMinutes(5);
28 33
29 class DefaultAlarmDelegate : public AlarmManager::Delegate { 34 class DefaultAlarmDelegate : public AlarmManager::Delegate {
30 public: 35 public:
31 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {} 36 explicit DefaultAlarmDelegate(Profile* profile) : profile_(profile) {}
32 virtual ~DefaultAlarmDelegate() {} 37 virtual ~DefaultAlarmDelegate() {}
33 38
34 virtual void OnAlarm(const std::string& extension_id, 39 virtual void OnAlarm(const std::string& extension_id,
35 const AlarmManager::Alarm& alarm) { 40 const AlarmManager::Alarm& alarm) {
36 ListValue args; 41 ListValue args;
37 std::string json_args; 42 std::string json_args;
38 args.Append(alarm.ToValue().release()); 43 args.Append(alarm.ToValue().release());
39 base::JSONWriter::Write(&args, &json_args); 44 base::JSONWriter::Write(&args, &json_args);
40 ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension( 45 ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
41 extension_id, kOnAlarmEvent, json_args, NULL, GURL()); 46 extension_id, kOnAlarmEvent, json_args, NULL, GURL());
42 } 47 }
43 48
44 private: 49 private:
45 Profile* profile_; 50 Profile* profile_;
46 }; 51 };
47 52
53 // Contains the state we persist for each alarm.
54 struct AlarmState {
55 linked_ptr<AlarmManager::Alarm> alarm;
56 base::Time scheduled_run_time;
57
58 AlarmState() {}
59 ~AlarmState() {}
60 };
61
48 // Creates a TimeDelta from a delay as specified in the API. 62 // Creates a TimeDelta from a delay as specified in the API.
49 base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) { 63 base::TimeDelta TimeDeltaFromDelay(double delay_in_minutes) {
50 return base::TimeDelta::FromMicroseconds( 64 return base::TimeDelta::FromMicroseconds(
51 delay_in_minutes * base::Time::kMicrosecondsPerMinute); 65 delay_in_minutes * base::Time::kMicrosecondsPerMinute);
52 } 66 }
53 67
68 std::vector<AlarmState> AlarmsFromValue(const base::ListValue* list) {
69 typedef AlarmManager::Alarm Alarm;
70 std::vector<AlarmState> alarms;
71 for (size_t i = 0; i < list->GetSize(); ++i) {
72 base::DictionaryValue* alarm_dict = NULL;
73 AlarmState alarm;
74 alarm.alarm.reset(new Alarm());
75 if (list->GetDictionary(i, &alarm_dict) &&
76 Alarm::Populate(*alarm_dict, alarm.alarm.get())) {
77 base::Value* time_value = NULL;
78 if (alarm_dict->Get(kAlarmScheduledRunTime, &time_value))
79 base::GetValueAsTime(*time_value, &alarm.scheduled_run_time);
80 alarms.push_back(alarm);
81 }
82 }
83 return alarms;
84 }
85
86 scoped_ptr<base::ListValue> AlarmsToValue(
87 const std::vector<AlarmState>& alarms) {
88 scoped_ptr<base::ListValue> list(new ListValue());
89 for (size_t i = 0; i < alarms.size(); ++i) {
90 scoped_ptr<base::DictionaryValue> alarm = alarms[i].alarm->ToValue().Pass();
91 alarm->Set(kAlarmScheduledRunTime,
92 base::CreateTimeValue(alarms[i].scheduled_run_time));
93 list->Append(alarm.release());
94 }
95 return list.Pass();
96 }
97
98
54 } // namespace 99 } // namespace
55 100
56 // AlarmManager 101 // AlarmManager
57 102
58 AlarmManager::AlarmManager(Profile* profile) 103 AlarmManager::AlarmManager(Profile* profile)
59 : profile_(profile), 104 : profile_(profile),
60 delegate_(new DefaultAlarmDelegate(profile)), 105 delegate_(new DefaultAlarmDelegate(profile)),
61 last_poll_time_(base::Time()) { 106 last_poll_time_(base::Time()) {
62 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 107 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
63 content::Source<Profile>(profile_)); 108 content::Source<Profile>(profile_));
109
110 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
111 if (storage)
112 storage->RegisterKey(kRegisteredAlarms);
64 } 113 }
65 114
66 AlarmManager::~AlarmManager() { 115 AlarmManager::~AlarmManager() {
67 } 116 }
68 117
69 void AlarmManager::AddAlarm(const std::string& extension_id, 118 void AlarmManager::AddAlarm(const std::string& extension_id,
70 const linked_ptr<Alarm>& alarm) { 119 const linked_ptr<Alarm>& alarm) {
71 base::TimeDelta alarm_time = TimeDeltaFromDelay(alarm->delay_in_minutes); 120 base::TimeDelta alarm_time = TimeDeltaFromDelay(alarm->delay_in_minutes);
72 AddAlarmImpl(extension_id, alarm, alarm_time); 121 AddAlarmImpl(extension_id, alarm, alarm_time);
73 WriteToPrefs(extension_id); 122 WriteToStorage(extension_id);
74 } 123 }
75 124
76 const AlarmManager::Alarm* AlarmManager::GetAlarm( 125 const AlarmManager::Alarm* AlarmManager::GetAlarm(
77 const std::string& extension_id, const std::string& name) { 126 const std::string& extension_id, const std::string& name) {
78 AlarmIterator it = GetAlarmIterator(extension_id, name); 127 AlarmIterator it = GetAlarmIterator(extension_id, name);
79 if (it.first == alarms_.end()) 128 if (it.first == alarms_.end())
80 return NULL; 129 return NULL;
81 return it.second->get(); 130 return it.second->get();
82 } 131 }
83 132
(...skipping 20 matching lines...) Expand all
104 return make_pair(alarms_.end(), AlarmList::iterator()); 153 return make_pair(alarms_.end(), AlarmList::iterator());
105 } 154 }
106 155
107 bool AlarmManager::RemoveAlarm(const std::string& extension_id, 156 bool AlarmManager::RemoveAlarm(const std::string& extension_id,
108 const std::string& name) { 157 const std::string& name) {
109 AlarmIterator it = GetAlarmIterator(extension_id, name); 158 AlarmIterator it = GetAlarmIterator(extension_id, name);
110 if (it.first == alarms_.end()) 159 if (it.first == alarms_.end())
111 return false; 160 return false;
112 161
113 RemoveAlarmIterator(it); 162 RemoveAlarmIterator(it);
114 WriteToPrefs(extension_id); 163 WriteToStorage(extension_id);
115 return true; 164 return true;
116 } 165 }
117 166
118 void AlarmManager::RemoveAllAlarms(const std::string& extension_id) { 167 void AlarmManager::RemoveAllAlarms(const std::string& extension_id) {
119 AlarmMap::iterator list = alarms_.find(extension_id); 168 AlarmMap::iterator list = alarms_.find(extension_id);
120 if (list == alarms_.end()) 169 if (list == alarms_.end())
121 return; 170 return;
122 171
123 // Note: I'm using indices rather than iterators here because 172 // Note: I'm using indices rather than iterators here because
124 // RemoveAlarmIterator will delete the list when it becomes empty. 173 // RemoveAlarmIterator will delete the list when it becomes empty.
125 for (size_t i = 0, size = list->second.size(); i < size; ++i) 174 for (size_t i = 0, size = list->second.size(); i < size; ++i)
126 RemoveAlarmIterator(AlarmIterator(list, list->second.begin())); 175 RemoveAlarmIterator(AlarmIterator(list, list->second.begin()));
127 176
128 CHECK(alarms_.find(extension_id) == alarms_.end()); 177 CHECK(alarms_.find(extension_id) == alarms_.end());
129 WriteToPrefs(extension_id); 178 WriteToStorage(extension_id);
130 } 179 }
131 180
132 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) { 181 void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) {
133 // Cancel the timer if there are no more alarms. 182 // Cancel the timer if there are no more alarms.
134 // We don't need to reschedule the poll otherwise, because in 183 // We don't need to reschedule the poll otherwise, because in
135 // the worst case we would just poll one extra time. 184 // the worst case we would just poll one extra time.
136 scheduled_times_.erase(iter.second->get()); 185 scheduled_times_.erase(iter.second->get());
137 if (scheduled_times_.empty()) 186 if (scheduled_times_.empty())
138 timer_.Stop(); 187 timer_.Stop();
139 188
(...skipping 12 matching lines...) Expand all
152 delegate_->OnAlarm(extension_id, *alarm); 201 delegate_->OnAlarm(extension_id, *alarm);
153 202
154 std::string extension_id_copy(extension_id); 203 std::string extension_id_copy(extension_id);
155 if (!alarm->repeating) { 204 if (!alarm->repeating) {
156 RemoveAlarmIterator(it); 205 RemoveAlarmIterator(it);
157 } else { 206 } else {
158 // Update our scheduled time for the next alarm. 207 // Update our scheduled time for the next alarm.
159 scheduled_times_[alarm].time = 208 scheduled_times_[alarm].time =
160 last_poll_time_ + TimeDeltaFromDelay(alarm->delay_in_minutes); 209 last_poll_time_ + TimeDeltaFromDelay(alarm->delay_in_minutes);
161 } 210 }
162 WriteToPrefs(extension_id_copy); 211 WriteToStorage(extension_id_copy);
163 } 212 }
164 213
165 void AlarmManager::AddAlarmImpl(const std::string& extension_id, 214 void AlarmManager::AddAlarmImpl(const std::string& extension_id,
166 const linked_ptr<Alarm>& alarm, 215 const linked_ptr<Alarm>& alarm,
167 base::TimeDelta time_delay) { 216 base::TimeDelta time_delay) {
168 // Override any old alarm with the same name. 217 // Override any old alarm with the same name.
169 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name); 218 AlarmIterator old_alarm = GetAlarmIterator(extension_id, alarm->name);
170 if (old_alarm.first != alarms_.end()) 219 if (old_alarm.first != alarms_.end())
171 RemoveAlarmIterator(old_alarm); 220 RemoveAlarmIterator(old_alarm);
172 221
173 alarms_[extension_id].push_back(alarm); 222 alarms_[extension_id].push_back(alarm);
174 AlarmRuntimeInfo info; 223 AlarmRuntimeInfo info;
175 info.extension_id = extension_id; 224 info.extension_id = extension_id;
176 info.time = base::Time::Now() + time_delay; 225 info.time = base::Time::Now() + time_delay;
177 scheduled_times_[alarm.get()] = info; 226 scheduled_times_[alarm.get()] = info;
178 227
179 // TODO(yoz): Is 0 really sane? There could be thrashing. 228 // TODO(yoz): Is 0 really sane? There could be thrashing.
180 ScheduleNextPoll(base::TimeDelta::FromMinutes(0)); 229 ScheduleNextPoll(base::TimeDelta::FromMinutes(0));
181 } 230 }
182 231
183 void AlarmManager::WriteToPrefs(const std::string& extension_id) { 232 void AlarmManager::WriteToStorage(const std::string& extension_id) {
184 ExtensionService* service = 233 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
185 ExtensionSystem::Get(profile_)->extension_service(); 234 if (!storage)
186 if (!service || !service->extension_prefs())
187 return; 235 return;
188 236
189 std::vector<AlarmPref> alarm_prefs; 237 std::vector<AlarmState> alarm_states;
190
191 AlarmMap::iterator list = alarms_.find(extension_id); 238 AlarmMap::iterator list = alarms_.find(extension_id);
192 if (list != alarms_.end()) { 239 if (list != alarms_.end()) {
193 for (AlarmList::iterator it = list->second.begin(); 240 for (AlarmList::iterator it = list->second.begin();
194 it != list->second.end(); ++it) { 241 it != list->second.end(); ++it) {
195 AlarmPref pref; 242 AlarmState pref;
196 pref.alarm = *it; 243 pref.alarm = *it;
197 pref.scheduled_run_time = scheduled_times_[it->get()].time; 244 pref.scheduled_run_time = scheduled_times_[it->get()].time;
198 alarm_prefs.push_back(pref); 245 alarm_states.push_back(pref);
199 } 246 }
200 } 247 }
201 248
202 service->extension_prefs()->SetRegisteredAlarms(extension_id, alarm_prefs); 249 scoped_ptr<Value> alarms(AlarmsToValue(alarm_states).release());
250 storage->SetExtensionValue(extension_id, kRegisteredAlarms, alarms.Pass());
203 } 251 }
204 252
205 void AlarmManager::ReadFromPrefs(const std::string& extension_id) { 253 void AlarmManager::ReadFromStorage(const std::string& extension_id,
206 ExtensionService* service = 254 scoped_ptr<base::Value> value) {
207 ExtensionSystem::Get(profile_)->extension_service(); 255 base::ListValue* list = NULL;
208 if (!service || !service->extension_prefs()) 256 if (!value.get() || !value->GetAsList(&list))
209 return; 257 return;
210 258
211 std::vector<AlarmPref> alarm_prefs = 259 std::vector<AlarmState> alarm_states = AlarmsFromValue(list);
212 service->extension_prefs()->GetRegisteredAlarms(extension_id); 260 for (size_t i = 0; i < alarm_states.size(); ++i) {
213 for (size_t i = 0; i < alarm_prefs.size(); ++i) {
214 base::TimeDelta delay = 261 base::TimeDelta delay =
215 alarm_prefs[i].scheduled_run_time - base::Time::Now(); 262 alarm_states[i].scheduled_run_time - base::Time::Now();
216 if (delay < base::TimeDelta::FromSeconds(0)) 263 if (delay < base::TimeDelta::FromSeconds(0))
217 delay = base::TimeDelta::FromSeconds(0); 264 delay = base::TimeDelta::FromSeconds(0);
218 265
219 AddAlarmImpl(extension_id, alarm_prefs[i].alarm, delay); 266 AddAlarmImpl(extension_id, alarm_states[i].alarm, delay);
220 } 267 }
221 } 268 }
222 269
223 void AlarmManager::ScheduleNextPoll(base::TimeDelta min_period) { 270 void AlarmManager::ScheduleNextPoll(base::TimeDelta min_period) {
224 // 0. If there are no alarms, stop the timer. 271 // 0. If there are no alarms, stop the timer.
225 if (scheduled_times_.empty()) { 272 if (scheduled_times_.empty()) {
226 timer_.Stop(); 273 timer_.Stop();
227 return; 274 return;
228 } 275 }
229 276
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 } 331 }
285 332
286 void AlarmManager::Observe( 333 void AlarmManager::Observe(
287 int type, 334 int type,
288 const content::NotificationSource& source, 335 const content::NotificationSource& source,
289 const content::NotificationDetails& details) { 336 const content::NotificationDetails& details) {
290 switch (type) { 337 switch (type) {
291 case chrome::NOTIFICATION_EXTENSION_LOADED: { 338 case chrome::NOTIFICATION_EXTENSION_LOADED: {
292 const Extension* extension = 339 const Extension* extension =
293 content::Details<const Extension>(details).ptr(); 340 content::Details<const Extension>(details).ptr();
294 ReadFromPrefs(extension->id()); 341 StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
342 if (storage) {
343 storage->GetExtensionValue(extension->id(), kRegisteredAlarms,
344 base::Bind(&AlarmManager::ReadFromStorage,
345 AsWeakPtr(), extension->id()));
346 }
295 break; 347 break;
296 } 348 }
297 default: 349 default:
298 NOTREACHED(); 350 NOTREACHED();
299 break; 351 break;
300 } 352 }
301 } 353 }
302 354
303 AlarmPref::AlarmPref() {
304 }
305
306 AlarmPref::~AlarmPref() {
307 }
308
309 } // namespace extensions 355 } // 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