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