eec770607280ab5021b881bd38dc82d2ee1164ee
[framework/web/wrt-plugins-tizen.git] / src / Alarm / JSAlarmManager.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18
19 #include <vector>
20 #include <app.h>
21 #include <time.h>
22 #include <string>
23
24 #include <CommonsJavaScript/Converter.h>
25 #include <CommonsJavaScript/Validator.h>
26 #include <CommonsJavaScript/JSUtils.h>
27 #include <CommonsJavaScript/JSDOMExceptionFactory.h>
28
29 #include <JSWebAPIException.h>
30 #include <ArgumentValidator.h>
31 #include <JSUtil.h>
32
33 #include <SecurityExceptions.h>
34 #include <Commons/Exception.h>
35 #include <Commons/Regex.h>
36 #include <JSTizenExceptionFactory.h>
37 #include <JSTizenException.h>
38 #include <JSApplicationControl.h>
39 #include <ApplicationControl.h>
40 #include <ApplicationConverter.h>
41
42 #include <ail.h>
43
44 #include "plugin_config.h"
45 #include "AlarmConverter.h"
46 #include "JSAlarmAbsolute.h"
47 #include "AlarmAbsolute.h"
48 #include "JSAlarmRelative.h"
49 #include "AlarmRelative.h"
50 #include "JSAlarmManager.h"
51
52 #include <TimeTracer.h>
53 #include <Export.h>
54 #include <Logger.h>
55
56 namespace DeviceAPI {
57 namespace Alarm {
58
59 using namespace WrtDeviceApis::Commons;
60 using namespace WrtDeviceApis::CommonsJavaScript;
61 using namespace DeviceAPI::Common;
62
63 static bool alarm_iterate_callback(int alarm_id, void *user_data)
64 {
65     std::vector<int> *alarmIds = reinterpret_cast<std::vector<int>*>(user_data);
66    
67     alarmIds->push_back(alarm_id);
68     return true;
69 }
70
71 JSClassRef JSAlarmManager::m_jsClassRef = NULL;
72
73 JSClassDefinition JSAlarmManager::m_jsClassInfo = {
74         0,
75         kJSClassAttributeNone,
76         TIZEN_ALARM_INTERFACE,
77         NULL,
78         m_property,
79         m_function,
80         initialize,
81         finalize,
82         NULL, //hasProperty,
83         NULL, //getProperty,
84         NULL, //setProperty,
85         NULL, //deleteProperty,Geolocation
86         NULL, //getPropertyNames,
87         NULL,
88         NULL, // constructor
89         NULL,
90         NULL
91 };
92
93 JSStaticFunction JSAlarmManager::m_function[] = {    
94         { ALARM_FUNCTION_API_ADD, JSAlarmManager::add,kJSPropertyAttributeNone },
95         { ALARM_FUNCTION_API_REMOVE, JSAlarmManager::remove,kJSPropertyAttributeNone },
96         { ALARM_FUNCTION_API_REMOVE_ALL, JSAlarmManager::removeAll,kJSPropertyAttributeNone },
97         { ALARM_FUNCTION_API_GET_ALL, JSAlarmManager::getAll,kJSPropertyAttributeNone },
98         { ALARM_FUNCTION_API_GET, JSAlarmManager::get,kJSPropertyAttributeNone },
99         { 0, 0, 0 }
100 };
101
102 JSStaticValue JSAlarmManager::m_property[] = {
103                 { TIZEN_ALARM_CONSTANT_PERIOD_MINUTE, getProperty, NULL, kJSPropertyAttributeReadOnly },
104                 { TIZEN_ALARM_CONSTANT_PERIOD_HOUR, getProperty, NULL, kJSPropertyAttributeReadOnly },
105                 { TIZEN_ALARM_CONSTANT_PERIOD_DAY, getProperty, NULL, kJSPropertyAttributeReadOnly },
106                 { TIZEN_ALARM_CONSTANT_PERIOD_WEEK, getProperty, NULL, kJSPropertyAttributeReadOnly },
107                 { 0, 0, 0, 0 }
108 };
109
110 const JSClassRef DLL_EXPORT JSAlarmManager::getClassRef()
111 {
112     if (!m_jsClassRef) {
113         m_jsClassRef = JSClassCreate(&m_jsClassInfo);
114     }
115     return m_jsClassRef;
116 }
117
118 const JSClassDefinition* JSAlarmManager::getClassInfo() 
119 {
120     return &m_jsClassInfo;
121 }
122
123 JSContextRef JSAlarmManager::gContext = NULL;
124
125 void JSAlarmManager::initialize(JSContextRef ctx, JSObjectRef object) 
126 {
127     gContext = ctx;
128 }
129
130 void JSAlarmManager::finalize(JSObjectRef object) 
131 {
132 }
133
134 bool JSAlarmManager::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception) {
135     return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
136 }
137
138 JSValueRef JSAlarmManager::add(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
139 {
140         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
141         service_h service;
142         struct tm startDate;
143         int delay = 0;
144         int alarm_id;
145         std::string applicationId;
146         std::string page;
147
148         TIME_TRACER_ITEM_BEGIN("(add)ace_check", 0);
149         AceSecurityStatus status = ALARM_CHECK_ACCESS(ALARM_FUNCTION_API_ADD);
150         TIZEN_SYNC_ACCESS_HANDLER(status, ctx, exception);
151         TIME_TRACER_ITEM_END("(add)ace_check", 0);
152
153         try {
154                 ArgumentValidator validator(ctx, argumentCount, arguments);
155                 AlarmConverter converter(ctx);
156                 
157                 // applicationId
158                 std::string appId = validator.toString(1);
159
160                 // alarm
161         JSObjectRef alarmObj = validator.toObject(0);
162                 if (JSValueIsObjectOfClass(ctx, alarmObj, JSAlarmAbsolute::getClassRef())) {
163
164                         JSAlarmAbsolutePriv *priv = static_cast<JSAlarmAbsolutePriv*>(JSObjectGetPrivate(alarmObj));
165                         if (!priv) {
166                                 throw TypeMismatchException("Object is null.");
167                         }
168                         AlarmAbsolutePtr alarmPtr = priv->getObject();
169                         if (!alarmPtr) {
170                                 throw TypeMismatchException("Private object is null.");
171                         }
172         
173                         startDate = alarmPtr->getDate();
174                         service = alarmPtr->getService();
175                         service_set_app_id(service, appId.c_str());
176                         
177                         // appControl
178                         JSObjectRef appControlObj = validator.toObject(2, true);
179                         if (appControlObj) {
180                                 if(!JSValueIsObjectOfClass(ctx, appControlObj, DeviceAPI::Application::JSApplicationControl::getClassRef())) {
181                                         throw TypeMismatchException("Third parameter is not a ApplicationControl object");
182                                 }
183                                 DeviceAPI::Application::ApplicationConverter applicationConverter(ctx);
184                                 DeviceAPI::Application::ApplicationControlPtr appService = applicationConverter.toApplicationControl(appControlObj);
185                                 if(converter.toAlarmService(service, appService) == false) {
186                                         throw TypeMismatchException("Third parameter is not a ApplicationControl object");
187                                 }
188                         } else {
189                                 service_set_operation(service, SERVICE_OPERATION_DEFAULT);
190                         }
191
192                         AbsoluteRecurrence::Type alarmType = alarmPtr->getRecurrenceType();
193
194                         int err = ALARM_ERROR_NONE;
195                         if(alarmType == AbsoluteRecurrence::ByDayValue) {
196                                 int bydayValue = converter.toNativeAlarmValue(alarmPtr->getByDayRecurrence());
197                                 LoggerI("Native bydayValue = " << bydayValue);
198                                 err = alarm_schedule_with_recurrence_week_flag(service, &startDate, bydayValue, &alarm_id);
199                         } else if(alarmType == AbsoluteRecurrence::Interval) {
200                                 int interval = alarmPtr->getInterval();
201                                 err = alarm_schedule_at_date(service, &startDate, interval, &alarm_id);
202                         } else {
203                                 err = alarm_schedule_at_date(service, &startDate, 0, &alarm_id);
204                         }
205
206                         if(err == ALARM_ERROR_NONE) {
207                                 alarmPtr->setId(alarm_id);
208                         } else {
209                                 throw UnknownException("Alarm scheduling failed.");
210                         }
211                         
212                 } else if (JSValueIsObjectOfClass(ctx, alarmObj, JSAlarmRelative::getClassRef())) {
213
214                         JSAlarmRelativePriv *priv = static_cast<JSAlarmRelativePriv*>(JSObjectGetPrivate(alarmObj));
215                         if (!priv) {
216                                 throw TypeMismatchException("Object is null.");
217                         }
218                         AlarmRelativePtr alarmPtr = priv->getObject();
219                         if (!alarmPtr) {
220                                 throw TypeMismatchException("Private object is null.");
221                         }
222
223                         delay = alarmPtr->getDelay();
224                         long interval = alarmPtr->getPeriod();
225                         service = alarmPtr->getService();
226                         service_set_app_id(service, appId.c_str());
227
228                         // appControl
229                         JSObjectRef appControlObj = validator.toObject(2, true);
230                         if (appControlObj) {
231                                 if(!JSValueIsObjectOfClass(ctx, appControlObj, DeviceAPI::Application::JSApplicationControl::getClassRef())) {
232                                         throw TypeMismatchException("Third parameter is not a ApplicationControl object");
233                                 }
234                                 DeviceAPI::Application::ApplicationConverter applicationConverter(ctx);
235                                 DeviceAPI::Application::ApplicationControlPtr appService = applicationConverter.toApplicationControl(appControlObj);
236                                 if(converter.toAlarmService(service, appService) == false) {
237                                         throw TypeMismatchException("Third parameter is not a ApplicationControl object");
238                                 }
239                         } else {
240                                 service_set_operation(service, SERVICE_OPERATION_DEFAULT);
241                         }
242
243                         int err = alarm_schedule_after_delay(service, delay, interval, &alarm_id);
244
245                         if(err == ALARM_ERROR_NONE) {
246                                 alarmPtr->setId(alarm_id);
247                         } else {
248                                 throw UnknownException("Alarm scheduling failed.");
249                         }
250
251                 } else {
252                         LoggerE("First parameter is not a Alarm object");
253                         throw TypeMismatchException("First parameter is not a Alarm object");
254                 }
255                 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
256                 return JSValueMakeUndefined(ctx);
257
258         }  catch (const BasePlatformException &err) {
259         return JSWebAPIException::throwException(ctx, exception, err);
260     } catch (...) {
261         DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
262         return JSWebAPIException::throwException(ctx, exception, err);
263     }
264 }
265
266 JSValueRef JSAlarmManager::remove(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
267 {
268         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
269     AceSecurityStatus status = ALARM_CHECK_ACCESS(ALARM_FUNCTION_API_REMOVE);
270     TIZEN_SYNC_ACCESS_HANDLER(status, ctx, exception);
271     
272         try {
273                 ArgumentValidator validator(ctx, argumentCount, arguments);
274
275                 // id
276         std::string id = validator.toString(0);
277                 
278                 int alarmId = 0;
279                 std::stringstream(id) >> alarmId;
280
281                 if (alarmId <= 0) {
282                         throw InvalidValuesException("Invalid ID");
283                 }
284
285                 TIME_TRACER_ITEM_BEGIN("(remove)alarm_cancel", 0);
286                 int ret = alarm_cancel(alarmId);
287                 TIME_TRACER_ITEM_END("(remove)alarm_cancel", 0);
288
289                 if (ret != ALARM_ERROR_NONE) {
290                         throw NotFoundException("Alarm not found");
291                 }
292                 
293                 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
294                 return JSValueMakeUndefined(ctx);
295         } catch (const BasePlatformException &err) {
296         return JSWebAPIException::throwException(ctx, exception, err);
297     } catch (...) {
298         DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
299         return JSWebAPIException::throwException(ctx, exception, err);
300     }
301 }
302
303 JSValueRef JSAlarmManager::removeAll(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
304 {
305         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
306     AceSecurityStatus status = ALARM_CHECK_ACCESS(ALARM_FUNCTION_API_REMOVE_ALL);
307     TIZEN_SYNC_ACCESS_HANDLER(status, ctx, exception);
308
309         TIME_TRACER_ITEM_BEGIN("(removeAll)alarm_cancel_all", 0);
310         int returnVal = alarm_cancel_all();
311         TIME_TRACER_ITEM_END("(removeAll)alarm_cancel_all", 0);
312
313         if (ALARM_ERROR_NONE != returnVal) {
314                 LoggerE("Error while removing all alarms: "<< returnVal);
315         }
316
317         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
318     return JSValueMakeUndefined(ctx);
319 }
320
321 JSValueRef JSAlarmManager::get(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
322 {
323         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
324     try {
325                 service_h service = NULL;
326                 char* alarmType = NULL;
327                 JSValueRef result = NULL;
328                 
329         ArgumentValidator validator(ctx, argumentCount, arguments);
330             AlarmConverter converter(ctx);
331
332         // id
333         std::string id = validator.toString(0);
334                 int alarmId = 0;
335                 std::stringstream(id) >> alarmId;       
336
337                 if (alarmId <= 0) {
338                         LoggerE("Wrong Alarm ID");
339                         throw InvalidValuesException("Invalid ID");
340                 }
341
342                 TIME_TRACER_ITEM_BEGIN("(get)alarm_get_service", 0);
343                 int ret = alarm_get_service(alarmId, &service);
344                 TIME_TRACER_ITEM_END("(get)alarm_get_service", 0);
345
346                 if (ret != ALARM_ERROR_NONE) {
347                         throw NotFoundException("Alarm not found");
348                 }
349                 
350                 ret = service_get_extra_data(service, ALARM_TYPE_KEY, &alarmType);
351                 if (ret != SERVICE_ERROR_NONE) {
352                         LoggerE("Getting data failed: " << ret);
353                         service_destroy(service);
354                         throw UnknownException("Unknown error occurred.");
355                 }
356                 
357                 if (strcmp(alarmType, ALARM_TYPE_ABSOLUTE_VALUE) == 0) {
358                         AlarmAbsolutePtr privateData = AlarmAbsolutePtr(new AlarmAbsolute(service));
359                         
360                         if(!converter.toAlarmAbsolutePtr(alarmId, service, privateData)) {
361                                 service_destroy(service);
362                 throw TypeMismatchException("Alarm not found");
363             }
364
365             result = JSAlarmAbsolute::createJSObject(ctx, privateData);         
366
367                 } else if(strcmp(alarmType, ALARM_TYPE_RELATIVE_VALUE) == 0) {
368             AlarmRelativePtr privateData = AlarmRelativePtr(new AlarmRelative(service));
369                         
370             if(!converter.toAlarmRelativePtr(alarmId, service, privateData)) {
371                                 service_destroy(service);
372                  throw TypeMismatchException("Alarm not found");
373             }
374                         
375             result = JSAlarmRelative::createJSObject(ctx, privateData);  
376                 } else {
377                         service_destroy(service);
378                         throw UnknownException("Unknown error occurred.");
379                 }
380
381                 service_destroy(service);
382                 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
383                 return result;
384     } catch (const BasePlatformException &err) {
385         return JSWebAPIException::throwException(ctx, exception, err);
386     } catch (...) {
387         DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
388         return JSWebAPIException::throwException(ctx, exception, err);
389     }
390 }
391
392
393 JSValueRef JSAlarmManager::getAll(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
394 {
395         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
396     try {
397                 AlarmConverter converter(ctx);
398                 std::vector<int> alarmIds; 
399                 
400         int error = alarm_foreach_registered_alarm(alarm_iterate_callback, &alarmIds);
401         if (error == ALARM_ERROR_CONNECTION_FAIL) {
402             LoggerE("Alarm system may not be ready yet.");
403             alarmIds.clear();
404         } else if(error != ALARM_ERROR_NONE) {
405             LoggerE("Error occurred while getting all alarms : " << error);
406             throw UnknownException("Unknown error occurred.");
407         }
408
409         JSObjectRef jsResult = JSCreateArrayObject(ctx, 0, NULL);
410             if (jsResult == NULL) {
411                         throw TypeMismatchException("Could not create js array object.");
412             }
413
414                 for (size_t i = 0 ; i < alarmIds.size(); i++) {
415
416             service_h handle = NULL;
417             char* alarmType = NULL;
418                         
419             error = alarm_get_service(alarmIds.at(i), &handle);
420             if(error != ALARM_ERROR_NONE) {
421                 LoggerE("Getting service failed: " << error);
422                 throw NotFoundException("Alarm not found");
423             }
424
425             error = service_get_extra_data(handle, ALARM_TYPE_KEY, &alarmType);
426             if(error != SERVICE_ERROR_NONE) {
427                 LoggerI("Getting data failed: " << error);
428                 service_destroy(handle);
429                 throw UnknownException("Unknown error occurred.");
430             }
431
432                         JSValueRef obj = NULL;
433                         if (strcmp(alarmType, ALARM_TYPE_ABSOLUTE_VALUE) == 0) {
434                                 AlarmAbsolutePtr privateData = AlarmAbsolutePtr(new AlarmAbsolute(handle));
435
436                                 if(!converter.toAlarmAbsolutePtr(alarmIds.at(i), handle, privateData)) {
437                                         service_destroy(handle);
438                                         throw TypeMismatchException("Absolute alarm conversion failed.");
439                                 }
440
441                                 obj = JSAlarmAbsolute::createJSObject(ctx, privateData);
442                                 
443             } else if( !strcmp(alarmType, ALARM_TYPE_RELATIVE_VALUE)) {
444                 AlarmRelativePtr privateData = AlarmRelativePtr(new AlarmRelative(handle));
445                                 
446                 if(!converter.toAlarmRelativePtr(alarmIds.at(i), handle, privateData)) {
447                                         service_destroy(handle);
448                                         throw TypeMismatchException("Relative alarm conversion failed.");
449                 }
450                 obj = JSAlarmRelative::createJSObject(ctx, privateData);
451
452             }  else {
453                     service_destroy(handle);
454                                 throw UnknownException("Unknown error occurred.");
455                         }
456
457             service_destroy(handle);
458                         
459                         if(!JSSetArrayElement(ctx, jsResult, i, obj)) {
460                                 service_destroy(handle);
461                                 throw UnknownException("JS array creation failed.");
462                         }
463                 }
464
465                 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
466                 return jsResult;
467     } catch (const BasePlatformException &err) {
468         return JSWebAPIException::throwException(ctx, exception, err);
469     } catch (...) {
470         DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
471         return JSWebAPIException::throwException(ctx, exception, err);
472     }
473 }
474
475 JSValueRef JSAlarmManager::getProperty(JSContextRef context,
476         JSObjectRef object,
477         JSStringRef propertyName,
478         JSValueRef* exception)
479 {
480     try {
481         if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_MINUTE)) {
482             return JSUtil::toJSValueRef(context, (long)60);
483         } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_HOUR)) {
484             return JSUtil::toJSValueRef(context, (long)3600);
485         } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_DAY)) {
486             return JSUtil::toJSValueRef(context, (long)86400);
487         } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_WEEK)) {
488             return JSUtil::toJSValueRef(context, (long)604800);
489         }
490     } catch (const BasePlatformException &err) {
491         LoggerE("Getting property is failed. %s", err.getMessage().c_str());
492     }
493
494     return NULL;
495 }
496
497 } // Alarm
498 } // TizenApis
499