Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / browser / api / alarms / alarms_api.cc
blob937bbb9f68eeb2f9fd07d2e27a7def6bbbe528c2
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 "extensions/browser/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 "extensions/browser/api/alarms/alarm_manager.h"
12 #include "extensions/common/api/alarms.h"
13 #include "extensions/common/error_utils.h"
15 namespace extensions {
17 namespace alarms = api::alarms;
19 namespace {
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;
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() && create_info.when.get()) {
35 *error = kBothRelativeAndAbsoluteTime;
36 return false;
38 if (create_info.delay_in_minutes == NULL && create_info.when == NULL &&
39 create_info.period_in_minutes == NULL) {
40 *error = kNoScheduledTime;
41 return false;
44 // Users can always use an absolute timeout to request an arbitrarily-short or
45 // negative delay. We won't honor the short timeout, but we can't check it
46 // and warn the user because it would introduce race conditions (say they
47 // compute a long-enough timeout, but then the call into the alarms interface
48 // gets delayed past the boundary). However, it's still worth warning about
49 // relative delays that are shorter than we'll honor.
50 if (create_info.delay_in_minutes.get()) {
51 if (*create_info.delay_in_minutes < kReleaseDelayMinimum) {
52 static_assert(kReleaseDelayMinimum == 1,
53 "warning message must be updated");
54 if (Manifest::IsUnpackedLocation(extension->location()))
55 warnings->push_back(ErrorUtils::FormatErrorMessage(
56 "Alarm delay is less than minimum of 1 minutes."
57 " In released .crx, alarm \"*\" will fire in approximately"
58 " 1 minutes.",
59 alarm_name));
60 else
61 warnings->push_back(ErrorUtils::FormatErrorMessage(
62 "Alarm delay is less than minimum of 1 minutes."
63 " Alarm \"*\" will fire in approximately 1 minutes.",
64 alarm_name));
67 if (create_info.period_in_minutes.get()) {
68 if (*create_info.period_in_minutes < kReleaseDelayMinimum) {
69 static_assert(kReleaseDelayMinimum == 1,
70 "warning message must be updated");
71 if (Manifest::IsUnpackedLocation(extension->location()))
72 warnings->push_back(ErrorUtils::FormatErrorMessage(
73 "Alarm period is less than minimum of 1 minutes."
74 " In released .crx, alarm \"*\" will fire approximately"
75 " every 1 minutes.",
76 alarm_name));
77 else
78 warnings->push_back(ErrorUtils::FormatErrorMessage(
79 "Alarm period is less than minimum of 1 minutes."
80 " Alarm \"*\" will fire approximately every 1 minutes.",
81 alarm_name));
85 return true;
88 } // namespace
90 AlarmsCreateFunction::AlarmsCreateFunction()
91 : clock_(new base::DefaultClock()), owns_clock_(true) {
94 AlarmsCreateFunction::AlarmsCreateFunction(base::Clock* clock)
95 : clock_(clock), owns_clock_(false) {
98 AlarmsCreateFunction::~AlarmsCreateFunction() {
99 if (owns_clock_)
100 delete clock_;
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(alarm_name, params->alarm_info, extension(),
111 &error_, &warnings)) {
112 return false;
114 for (std::vector<std::string>::const_iterator it = warnings.begin();
115 it != warnings.end(); ++it)
116 WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING, *it);
118 Alarm alarm(alarm_name, params->alarm_info,
119 base::TimeDelta::FromMinutes(
120 Manifest::IsUnpackedLocation(extension()->location())
121 ? kDevDelayMinimum
122 : kReleaseDelayMinimum),
123 clock_->Now());
124 AlarmManager::Get(browser_context())
125 ->AddAlarm(extension_id(), alarm,
126 base::Bind(&AlarmsCreateFunction::Callback, this));
128 return true;
131 void AlarmsCreateFunction::Callback() {
132 SendResponse(true);
135 bool AlarmsGetFunction::RunAsync() {
136 scoped_ptr<alarms::Get::Params> params(alarms::Get::Params::Create(*args_));
137 EXTENSION_FUNCTION_VALIDATE(params.get());
139 std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
140 AlarmManager::Get(browser_context())
141 ->GetAlarm(extension_id(), name,
142 base::Bind(&AlarmsGetFunction::Callback, this, name));
144 return true;
147 void AlarmsGetFunction::Callback(const std::string& name,
148 extensions::Alarm* alarm) {
149 if (alarm) {
150 results_ = alarms::Get::Results::Create(*alarm->js_alarm);
152 SendResponse(true);
155 bool AlarmsGetAllFunction::RunAsync() {
156 AlarmManager::Get(browser_context())
157 ->GetAllAlarms(extension_id(),
158 base::Bind(&AlarmsGetAllFunction::Callback, this));
159 return true;
162 void AlarmsGetAllFunction::Callback(const AlarmList* alarms) {
163 if (alarms) {
164 std::vector<linked_ptr<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);
169 results_ = alarms::GetAll::Results::Create(create_arg);
170 } else {
171 SetResult(new base::ListValue());
173 SendResponse(true);
176 bool AlarmsClearFunction::RunAsync() {
177 scoped_ptr<alarms::Clear::Params> params(
178 alarms::Clear::Params::Create(*args_));
179 EXTENSION_FUNCTION_VALIDATE(params.get());
181 std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
182 AlarmManager::Get(browser_context())
183 ->RemoveAlarm(extension_id(), name,
184 base::Bind(&AlarmsClearFunction::Callback, this, name));
186 return true;
189 void AlarmsClearFunction::Callback(const std::string& name, bool success) {
190 SetResult(new base::FundamentalValue(success));
191 SendResponse(true);
194 bool AlarmsClearAllFunction::RunAsync() {
195 AlarmManager::Get(browser_context())
196 ->RemoveAllAlarms(extension_id(),
197 base::Bind(&AlarmsClearAllFunction::Callback, this));
198 return true;
201 void AlarmsClearAllFunction::Callback() {
202 SetResult(new base::FundamentalValue(true));
203 SendResponse(true);
206 } // namespace extensions