OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/extensions/api/alarms/alarms_api.h" | |
6 | |
7 #include "base/strings/string_number_conversions.h" | |
8 #include "base/time/clock.h" | |
9 #include "base/time/default_clock.h" | |
10 #include "base/values.h" | |
11 #include "chrome/browser/extensions/api/alarms/alarm_manager.h" | |
12 #include "chrome/common/extensions/api/alarms.h" | |
13 #include "extensions/common/error_utils.h" | |
14 | |
15 namespace alarms = extensions::api::alarms; | |
16 | |
17 namespace extensions { | |
18 | |
19 namespace { | |
20 | |
21 const char kDefaultAlarmName[] = ""; | |
22 const char kBothRelativeAndAbsoluteTime[] = | |
23 "Cannot set both when and delayInMinutes."; | |
24 const char kNoScheduledTime[] = | |
25 "Must set at least one of when, delayInMinutes, or periodInMinutes."; | |
26 const int kReleaseDelayMinimum = 1; | |
27 const int kDevDelayMinimum = 0; | |
28 | |
29 bool ValidateAlarmCreateInfo(const std::string& alarm_name, | |
30 const alarms::AlarmCreateInfo& create_info, | |
31 const Extension* extension, | |
32 std::string* error, | |
33 std::vector<std::string>* warnings) { | |
34 if (create_info.delay_in_minutes.get() && | |
35 create_info.when.get()) { | |
36 *error = kBothRelativeAndAbsoluteTime; | |
37 return false; | |
38 } | |
39 if (create_info.delay_in_minutes == NULL && | |
40 create_info.when == NULL && | |
41 create_info.period_in_minutes == NULL) { | |
42 *error = kNoScheduledTime; | |
43 return false; | |
44 } | |
45 | |
46 // Users can always use an absolute timeout to request an arbitrarily-short or | |
47 // negative delay. We won't honor the short timeout, but we can't check it | |
48 // and warn the user because it would introduce race conditions (say they | |
49 // compute a long-enough timeout, but then the call into the alarms interface | |
50 // gets delayed past the boundary). However, it's still worth warning about | |
51 // relative delays that are shorter than we'll honor. | |
52 if (create_info.delay_in_minutes.get()) { | |
53 if (*create_info.delay_in_minutes < kReleaseDelayMinimum) { | |
54 static_assert(kReleaseDelayMinimum == 1, | |
55 "warning message must be updated"); | |
56 if (Manifest::IsUnpackedLocation(extension->location())) | |
57 warnings->push_back(ErrorUtils::FormatErrorMessage( | |
58 "Alarm delay is less than minimum of 1 minutes." | |
59 " In released .crx, alarm \"*\" will fire in approximately" | |
60 " 1 minutes.", | |
61 alarm_name)); | |
62 else | |
63 warnings->push_back(ErrorUtils::FormatErrorMessage( | |
64 "Alarm delay is less than minimum of 1 minutes." | |
65 " Alarm \"*\" will fire in approximately 1 minutes.", | |
66 alarm_name)); | |
67 } | |
68 } | |
69 if (create_info.period_in_minutes.get()) { | |
70 if (*create_info.period_in_minutes < kReleaseDelayMinimum) { | |
71 static_assert(kReleaseDelayMinimum == 1, | |
72 "warning message must be updated"); | |
73 if (Manifest::IsUnpackedLocation(extension->location())) | |
74 warnings->push_back(ErrorUtils::FormatErrorMessage( | |
75 "Alarm period is less than minimum of 1 minutes." | |
76 " In released .crx, alarm \"*\" will fire approximately" | |
77 " every 1 minutes.", | |
78 alarm_name)); | |
79 else | |
80 warnings->push_back(ErrorUtils::FormatErrorMessage( | |
81 "Alarm period is less than minimum of 1 minutes." | |
82 " Alarm \"*\" will fire approximately every 1 minutes.", | |
83 alarm_name)); | |
84 } | |
85 } | |
86 | |
87 return true; | |
88 } | |
89 | |
90 } // namespace | |
91 | |
92 AlarmsCreateFunction::AlarmsCreateFunction() | |
93 : clock_(new base::DefaultClock()), owns_clock_(true) {} | |
94 | |
95 AlarmsCreateFunction::AlarmsCreateFunction(base::Clock* clock) | |
96 : clock_(clock), owns_clock_(false) {} | |
97 | |
98 AlarmsCreateFunction::~AlarmsCreateFunction() { | |
99 if (owns_clock_) | |
100 delete clock_; | |
101 } | |
102 | |
103 bool AlarmsCreateFunction::RunAsync() { | |
104 scoped_ptr<alarms::Create::Params> params( | |
105 alarms::Create::Params::Create(*args_)); | |
106 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
107 const std::string& alarm_name = | |
108 params->name.get() ? *params->name : kDefaultAlarmName; | |
109 std::vector<std::string> warnings; | |
110 if (!ValidateAlarmCreateInfo( | |
111 alarm_name, params->alarm_info, extension(), &error_, &warnings)) { | |
112 return false; | |
113 } | |
114 for (std::vector<std::string>::const_iterator it = warnings.begin(); | |
115 it != warnings.end(); ++it) | |
116 WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING, *it); | |
117 | |
118 Alarm alarm(alarm_name, | |
119 params->alarm_info, | |
120 base::TimeDelta::FromMinutes( | |
121 Manifest::IsUnpackedLocation(extension()->location()) | |
122 ? kDevDelayMinimum | |
123 : kReleaseDelayMinimum), | |
124 clock_->Now()); | |
125 AlarmManager::Get(browser_context())->AddAlarm( | |
126 extension_id(), alarm, base::Bind(&AlarmsCreateFunction::Callback, this)); | |
127 | |
128 return true; | |
129 } | |
130 | |
131 void AlarmsCreateFunction::Callback() { | |
132 SendResponse(true); | |
133 } | |
134 | |
135 bool AlarmsGetFunction::RunAsync() { | |
136 scoped_ptr<alarms::Get::Params> params(alarms::Get::Params::Create(*args_)); | |
137 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
138 | |
139 std::string name = params->name.get() ? *params->name : kDefaultAlarmName; | |
140 AlarmManager::Get(browser_context()) | |
141 ->GetAlarm(extension_id(), | |
142 name, | |
143 base::Bind(&AlarmsGetFunction::Callback, this, name)); | |
144 | |
145 return true; | |
146 } | |
147 | |
148 void AlarmsGetFunction::Callback( | |
149 const std::string& name, extensions::Alarm* alarm) { | |
150 if (alarm) { | |
151 results_ = alarms::Get::Results::Create(*alarm->js_alarm); | |
152 } | |
153 SendResponse(true); | |
154 } | |
155 | |
156 bool AlarmsGetAllFunction::RunAsync() { | |
157 AlarmManager::Get(browser_context())->GetAllAlarms( | |
158 extension_id(), base::Bind(&AlarmsGetAllFunction::Callback, this)); | |
159 return true; | |
160 } | |
161 | |
162 void AlarmsGetAllFunction::Callback(const AlarmList* alarms) { | |
163 if (alarms) { | |
164 std::vector<linked_ptr<extensions::api::alarms::Alarm> > create_arg; | |
165 create_arg.reserve(alarms->size()); | |
166 for (size_t i = 0, size = alarms->size(); i < size; ++i) { | |
167 create_arg.push_back((*alarms)[i].js_alarm); | |
168 } | |
169 results_ = alarms::GetAll::Results::Create(create_arg); | |
170 } else { | |
171 SetResult(new base::ListValue()); | |
172 } | |
173 SendResponse(true); | |
174 } | |
175 | |
176 bool AlarmsClearFunction::RunAsync() { | |
177 scoped_ptr<alarms::Clear::Params> params( | |
178 alarms::Clear::Params::Create(*args_)); | |
179 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
180 | |
181 std::string name = params->name.get() ? *params->name : kDefaultAlarmName; | |
182 AlarmManager::Get(browser_context()) | |
183 ->RemoveAlarm(extension_id(), | |
184 name, | |
185 base::Bind(&AlarmsClearFunction::Callback, this, name)); | |
186 | |
187 return true; | |
188 } | |
189 | |
190 void AlarmsClearFunction::Callback(const std::string& name, bool success) { | |
191 SetResult(new base::FundamentalValue(success)); | |
192 SendResponse(true); | |
193 } | |
194 | |
195 bool AlarmsClearAllFunction::RunAsync() { | |
196 AlarmManager::Get(browser_context())->RemoveAllAlarms( | |
197 extension_id(), base::Bind(&AlarmsClearAllFunction::Callback, this)); | |
198 return true; | |
199 } | |
200 | |
201 void AlarmsClearAllFunction::Callback() { | |
202 SetResult(new base::FundamentalValue(true)); | |
203 SendResponse(true); | |
204 } | |
205 | |
206 } // namespace extensions | |
OLD | NEW |