Upstream version 7.36.149.0
[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 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       COMPILE_ASSERT(kReleaseDelayMinimum == 1, update_warning_message_below);
55       if (Manifest::IsUnpackedLocation(extension->location()))
56         warnings->push_back(ErrorUtils::FormatErrorMessage(
57             "Alarm delay is less than minimum of 1 minutes."
58             " In released .crx, alarm \"*\" will fire in approximately"
59             " 1 minutes.",
60             alarm_name));
61       else
62         warnings->push_back(ErrorUtils::FormatErrorMessage(
63             "Alarm delay is less than minimum of 1 minutes."
64             " Alarm \"*\" will fire in approximately 1 minutes.",
65             alarm_name));
66     }
67   }
68   if (create_info.period_in_minutes.get()) {
69     if (*create_info.period_in_minutes < kReleaseDelayMinimum) {
70       COMPILE_ASSERT(kReleaseDelayMinimum == 1, update_warning_message_below);
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));
82     }
83   }
84
85   return true;
86 }
87
88 }  // namespace
89
90 AlarmsCreateFunction::AlarmsCreateFunction()
91     : clock_(new base::DefaultClock()), owns_clock_(true) {}
92
93 AlarmsCreateFunction::AlarmsCreateFunction(base::Clock* clock)
94     : clock_(clock), owns_clock_(false) {}
95
96 AlarmsCreateFunction::~AlarmsCreateFunction() {
97   if (owns_clock_)
98     delete clock_;
99 }
100
101 bool AlarmsCreateFunction::RunAsync() {
102   scoped_ptr<alarms::Create::Params> params(
103       alarms::Create::Params::Create(*args_));
104   EXTENSION_FUNCTION_VALIDATE(params.get());
105   const std::string& alarm_name =
106       params->name.get() ? *params->name : kDefaultAlarmName;
107   std::vector<std::string> warnings;
108   if (!ValidateAlarmCreateInfo(
109           alarm_name, params->alarm_info, GetExtension(), &error_, &warnings)) {
110     return false;
111   }
112   for (std::vector<std::string>::const_iterator it = warnings.begin();
113        it != warnings.end(); ++it)
114     WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_WARNING, *it);
115
116   Alarm alarm(alarm_name,
117               params->alarm_info,
118               base::TimeDelta::FromMinutes(
119                   Manifest::IsUnpackedLocation(GetExtension()->location()) ?
120                   kDevDelayMinimum : kReleaseDelayMinimum),
121               clock_->Now());
122   AlarmManager::Get(GetProfile())->AddAlarm(
123       extension_id(), alarm, base::Bind(&AlarmsCreateFunction::Callback, this));
124
125   return true;
126 }
127
128 void AlarmsCreateFunction::Callback() {
129   SendResponse(true);
130 }
131
132 bool AlarmsGetFunction::RunAsync() {
133   scoped_ptr<alarms::Get::Params> params(alarms::Get::Params::Create(*args_));
134   EXTENSION_FUNCTION_VALIDATE(params.get());
135
136   std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
137   AlarmManager::Get(GetProfile())
138       ->GetAlarm(extension_id(),
139                  name,
140                  base::Bind(&AlarmsGetFunction::Callback, this, name));
141
142   return true;
143 }
144
145 void AlarmsGetFunction::Callback(
146     const std::string& name, extensions::Alarm* alarm) {
147   if (alarm) {
148     results_ = alarms::Get::Results::Create(*alarm->js_alarm);
149   }
150   SendResponse(true);
151 }
152
153 bool AlarmsGetAllFunction::RunAsync() {
154   AlarmManager::Get(GetProfile())->GetAllAlarms(
155       extension_id(), base::Bind(&AlarmsGetAllFunction::Callback, this));
156   return true;
157 }
158
159 void AlarmsGetAllFunction::Callback(const AlarmList* alarms) {
160   if (alarms) {
161     std::vector<linked_ptr<extensions::api::alarms::Alarm> > create_arg;
162     create_arg.reserve(alarms->size());
163     for (size_t i = 0, size = alarms->size(); i < size; ++i) {
164       create_arg.push_back((*alarms)[i].js_alarm);
165     }
166     results_ = alarms::GetAll::Results::Create(create_arg);
167   } else {
168     SetResult(new base::ListValue());
169   }
170   SendResponse(true);
171 }
172
173 bool AlarmsClearFunction::RunAsync() {
174   scoped_ptr<alarms::Clear::Params> params(
175       alarms::Clear::Params::Create(*args_));
176   EXTENSION_FUNCTION_VALIDATE(params.get());
177
178   std::string name = params->name.get() ? *params->name : kDefaultAlarmName;
179   AlarmManager::Get(GetProfile())
180       ->RemoveAlarm(extension_id(),
181                     name,
182                     base::Bind(&AlarmsClearFunction::Callback, this, name));
183
184   return true;
185 }
186
187 void AlarmsClearFunction::Callback(const std::string& name, bool success) {
188   SetResult(new base::FundamentalValue(success));
189   SendResponse(true);
190 }
191
192 bool AlarmsClearAllFunction::RunAsync() {
193   AlarmManager::Get(GetProfile())->RemoveAllAlarms(
194       extension_id(), base::Bind(&AlarmsClearAllFunction::Callback, this));
195   return true;
196 }
197
198 void AlarmsClearAllFunction::Callback() {
199   SetResult(new base::FundamentalValue(true));
200   SendResponse(true);
201 }
202
203 }  // namespace extensions