- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / alarms / alarms_api.cc
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 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;
29
30 bool ValidateAlarmCreateInfo(const std::string& alarm_name,
31                              const alarms::AlarmCreateInfo& create_info,
32                              const Extension* extension,
33                              std::string* error,
34                              std::vector<std::string>* warnings) {
35   if (create_info.delay_in_minutes.get() &&
36       create_info.when.get()) {
37     *error = kBothRelativeAndAbsoluteTime;
38     return false;
39   }
40   if (create_info.delay_in_minutes == NULL &&
41       create_info.when == NULL &&
42       create_info.period_in_minutes == NULL) {
43     *error = kNoScheduledTime;
44     return false;
45   }
46
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"
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       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"
76             " every 1 minutes.",
77             alarm_name));
78       else
79         warnings->push_back(ErrorUtils::FormatErrorMessage(
80             "Alarm period is less than minimum of 1 minutes."
81             " Alarm \"*\" will fire approximately every 1 minutes.",
82             alarm_name));
83     }
84   }
85
86   return true;
87 }
88
89 }  // namespace
90
91 AlarmsCreateFunction::AlarmsCreateFunction()
92     : clock_(new base::DefaultClock()), owns_clock_(true) {}
93
94 AlarmsCreateFunction::AlarmsCreateFunction(base::Clock* clock)
95     : clock_(clock), owns_clock_(false) {}
96
97 AlarmsCreateFunction::~AlarmsCreateFunction() {
98   if (owns_clock_)
99     delete clock_;
100 }
101
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)) {
111     return false;
112   }
113   for (std::vector<std::string>::const_iterator it = warnings.begin();
114        it != warnings.end(); ++it)
115     WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING, *it);
116
117   Alarm alarm(alarm_name,
118               params->alarm_info,
119               base::TimeDelta::FromMinutes(
120                   Manifest::IsUnpackedLocation(GetExtension()->location()) ?
121                   kDevDelayMinimum : kReleaseDelayMinimum),
122               clock_->Now());
123   AlarmManager::Get(GetProfile())->AddAlarm(
124       extension_id(), alarm, base::Bind(&AlarmsCreateFunction::Callback, this));
125
126   return true;
127 }
128
129 void AlarmsCreateFunction::Callback() {
130   SendResponse(true);
131 }
132
133 bool AlarmsGetFunction::RunImpl() {
134   scoped_ptr<alarms::Get::Params> params(alarms::Get::Params::Create(*args_));
135   EXTENSION_FUNCTION_VALIDATE(params.get());
136
137   std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
138   AlarmManager::Get(GetProfile())
139       ->GetAlarm(extension_id(),
140                  name,
141                  base::Bind(&AlarmsGetFunction::Callback, this, name));
142
143   return true;
144 }
145
146 void AlarmsGetFunction::Callback(
147     const std::string& name, extensions::Alarm* alarm) {
148   if (alarm) {
149     results_ = alarms::Get::Results::Create(*alarm->js_alarm);
150     SendResponse(true);
151   } else {
152     error_ = ErrorUtils::FormatErrorMessage(kAlarmNotFound, name);
153     SendResponse(false);
154   }
155 }
156
157 bool AlarmsGetAllFunction::RunImpl() {
158   AlarmManager::Get(GetProfile())->GetAllAlarms(
159       extension_id(), base::Bind(&AlarmsGetAllFunction::Callback, this));
160   return true;
161 }
162
163 void AlarmsGetAllFunction::Callback(const AlarmList* alarms) {
164   if (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);
169     }
170     results_ = alarms::GetAll::Results::Create(create_arg);
171   } else {
172     SetResult(new base::ListValue());
173   }
174   SendResponse(true);
175 }
176
177 bool AlarmsClearFunction::RunImpl() {
178   scoped_ptr<alarms::Clear::Params> params(
179       alarms::Clear::Params::Create(*args_));
180   EXTENSION_FUNCTION_VALIDATE(params.get());
181
182   std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
183   AlarmManager::Get(GetProfile())
184       ->RemoveAlarm(extension_id(),
185                     name,
186                     base::Bind(&AlarmsClearFunction::Callback, this, name));
187
188   return true;
189 }
190
191 void AlarmsClearFunction::Callback(const std::string& name, bool success) {
192   if (!success)
193     error_ = ErrorUtils::FormatErrorMessage(kAlarmNotFound, name);
194
195   SendResponse(success);
196 }
197
198 bool AlarmsClearAllFunction::RunImpl() {
199   AlarmManager::Get(GetProfile())->RemoveAllAlarms(
200       extension_id(), base::Bind(&AlarmsClearAllFunction::Callback, this));
201   return true;
202 }
203
204 void AlarmsClearAllFunction::Callback() {
205   SendResponse(true);
206 }
207
208 }  // namespace extensions