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.
5 #include "chrome/browser/extensions/api/alarms/alarms_api.h"
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"
15 namespace alarms = extensions::api::alarms;
17 namespace extensions {
21 const char kDefaultAlarmName[] = "";
22 const char kAlarmNotFound[] = "No alarm named '*' exists.";
23 const char kBothRelativeAndAbsoluteTime[] =
24 "Cannot set both when and delayInMinutes.";
25 const char kNoScheduledTime[] =
26 "Must set at least one of when, delayInMinutes, or periodInMinutes.";
27 const int kReleaseDelayMinimum = 1;
28 const int kDevDelayMinimum = 0;
30 bool ValidateAlarmCreateInfo(const std::string& alarm_name,
31 const alarms::AlarmCreateInfo& create_info,
32 const Extension* extension,
34 std::vector<std::string>* warnings) {
35 if (create_info.delay_in_minutes.get() &&
36 create_info.when.get()) {
37 *error = kBothRelativeAndAbsoluteTime;
40 if (create_info.delay_in_minutes == NULL &&
41 create_info.when == NULL &&
42 create_info.period_in_minutes == NULL) {
43 *error = kNoScheduledTime;
47 // Users can always use an absolute timeout to request an arbitrarily-short or
48 // negative delay. We won't honor the short timeout, but we can't check it
49 // and warn the user because it would introduce race conditions (say they
50 // compute a long-enough timeout, but then the call into the alarms interface
51 // gets delayed past the boundary). However, it's still worth warning about
52 // relative delays that are shorter than we'll honor.
53 if (create_info.delay_in_minutes.get()) {
54 if (*create_info.delay_in_minutes < kReleaseDelayMinimum) {
55 COMPILE_ASSERT(kReleaseDelayMinimum == 1, update_warning_message_below);
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"
63 warnings->push_back(ErrorUtils::FormatErrorMessage(
64 "Alarm delay is less than minimum of 1 minutes."
65 " Alarm \"*\" will fire in approximately 1 minutes.",
69 if (create_info.period_in_minutes.get()) {
70 if (*create_info.period_in_minutes < kReleaseDelayMinimum) {
71 COMPILE_ASSERT(kReleaseDelayMinimum == 1, update_warning_message_below);
72 if (Manifest::IsUnpackedLocation(extension->location()))
73 warnings->push_back(ErrorUtils::FormatErrorMessage(
74 "Alarm period is less than minimum of 1 minutes."
75 " In released .crx, alarm \"*\" will fire approximately"
79 warnings->push_back(ErrorUtils::FormatErrorMessage(
80 "Alarm period is less than minimum of 1 minutes."
81 " Alarm \"*\" will fire approximately every 1 minutes.",
91 AlarmsCreateFunction::AlarmsCreateFunction()
92 : clock_(new base::DefaultClock()), owns_clock_(true) {}
94 AlarmsCreateFunction::AlarmsCreateFunction(base::Clock* clock)
95 : clock_(clock), owns_clock_(false) {}
97 AlarmsCreateFunction::~AlarmsCreateFunction() {
102 bool AlarmsCreateFunction::RunImpl() {
103 scoped_ptr<alarms::Create::Params> params(
104 alarms::Create::Params::Create(*args_));
105 EXTENSION_FUNCTION_VALIDATE(params.get());
106 const std::string& alarm_name =
107 params->name.get() ? *params->name : kDefaultAlarmName;
108 std::vector<std::string> warnings;
109 if (!ValidateAlarmCreateInfo(
110 alarm_name, params->alarm_info, GetExtension(), &error_, &warnings)) {
113 for (std::vector<std::string>::const_iterator it = warnings.begin();
114 it != warnings.end(); ++it)
115 WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING, *it);
117 Alarm alarm(alarm_name,
119 base::TimeDelta::FromMinutes(
120 Manifest::IsUnpackedLocation(GetExtension()->location()) ?
121 kDevDelayMinimum : kReleaseDelayMinimum),
123 AlarmManager::Get(GetProfile())->AddAlarm(
124 extension_id(), alarm, base::Bind(&AlarmsCreateFunction::Callback, this));
129 void AlarmsCreateFunction::Callback() {
133 bool AlarmsGetFunction::RunImpl() {
134 scoped_ptr<alarms::Get::Params> params(alarms::Get::Params::Create(*args_));
135 EXTENSION_FUNCTION_VALIDATE(params.get());
137 std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
138 AlarmManager::Get(GetProfile())
139 ->GetAlarm(extension_id(),
141 base::Bind(&AlarmsGetFunction::Callback, this, name));
146 void AlarmsGetFunction::Callback(
147 const std::string& name, extensions::Alarm* alarm) {
149 results_ = alarms::Get::Results::Create(*alarm->js_alarm);
152 error_ = ErrorUtils::FormatErrorMessage(kAlarmNotFound, name);
157 bool AlarmsGetAllFunction::RunImpl() {
158 AlarmManager::Get(GetProfile())->GetAllAlarms(
159 extension_id(), base::Bind(&AlarmsGetAllFunction::Callback, this));
163 void AlarmsGetAllFunction::Callback(const AlarmList* alarms) {
165 std::vector<linked_ptr<extensions::api::alarms::Alarm> > create_arg;
166 create_arg.reserve(alarms->size());
167 for (size_t i = 0, size = alarms->size(); i < size; ++i) {
168 create_arg.push_back((*alarms)[i].js_alarm);
170 results_ = alarms::GetAll::Results::Create(create_arg);
172 SetResult(new base::ListValue());
177 bool AlarmsClearFunction::RunImpl() {
178 scoped_ptr<alarms::Clear::Params> params(
179 alarms::Clear::Params::Create(*args_));
180 EXTENSION_FUNCTION_VALIDATE(params.get());
182 std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
183 AlarmManager::Get(GetProfile())
184 ->RemoveAlarm(extension_id(),
186 base::Bind(&AlarmsClearFunction::Callback, this, name));
191 void AlarmsClearFunction::Callback(const std::string& name, bool success) {
193 error_ = ErrorUtils::FormatErrorMessage(kAlarmNotFound, name);
195 SendResponse(success);
198 bool AlarmsClearAllFunction::RunImpl() {
199 AlarmManager::Get(GetProfile())->RemoveAllAlarms(
200 extension_id(), base::Bind(&AlarmsClearAllFunction::Callback, this));
204 void AlarmsClearAllFunction::Callback() {
208 } // namespace extensions