tizen 2.3.1 release
[framework/web/wearable/wrt-plugins-tizen.git] / src / Notification / NotificationManager.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 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/stat.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <bundle.h>
25 #include <appsvc/appsvc.h>
26
27 #include "NotificationManager.h"
28 #include "NotificationUtil.h"
29
30 #include <PlatformException.h>
31 #include <Logger.h>
32
33 namespace DeviceAPI {
34 namespace Notification {
35
36 extern "C" int app_control_to_bundle(app_control_h service, bundle **data);
37
38 static bool notification_package_equal(notification_h handle)
39 {
40     char* package = NULL;
41     char* handle_package = NULL;
42     char cmdline[512] = {0,};
43     char buf[64] = {0,};
44
45     if (notification_get_pkgname(handle, &handle_package))
46     {
47         return false;
48     }
49
50     LOGD("handle package = %s", handle_package);
51
52     if (app_get_id(&package))
53     {
54
55         int ret = 0;
56         int fd = -1;
57         int pid = getpid();
58
59         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
60
61         fd = open(buf, O_RDONLY);
62         if (fd < 0) {
63             return false;
64         }
65
66         ret = read(fd, cmdline, sizeof(cmdline) - 1);
67         if (ret <= 0) {
68             close(fd);
69             return false;
70         }
71
72         cmdline[ret] = 0;
73         close(fd);
74
75         if (strlen(cmdline) == strlen(handle_package))
76         {
77             if (!strncmp(cmdline, handle_package, strlen(cmdline)))
78             {
79                 return true;
80             }
81         }
82     }
83     else
84     {
85         LOGD("package = %s", package);
86
87         if (strlen(package) == strlen(handle_package))
88         {
89             if (!strncmp(package, handle_package, strlen(package)))
90             {
91                 free(package);
92                 return true;
93             }
94         }
95     }
96     free(package);
97     return false;
98 }
99
100 NotificationManager::NotificationManager()
101 {
102 }
103
104 NotificationManager::~NotificationManager()
105 {
106 }
107
108 int NotificationManager::post(StatusNotification *notification)
109 {
110     int id = -1;
111
112     if (!notification) {
113         LOGE("Notification handle is NULL.");
114         throw UnknownException("Notification Handle is NULL.");
115     }
116
117     LOGI("notification id = %d", notification->getID());
118     notification_h handle = (notification_h)notification->getNotificationHandle();
119
120     if (!handle) {
121         LOGD("It doesn't have notification handle.");
122         throw UnknownException("It is Empty Notification.");
123     }
124
125     //set Service
126     int ret = 0;
127
128     bundle *service_data = NULL;
129     app_control_h service = notification->getService();
130
131     LOGI("Service : %p, Flag : %d", service, notification->getLaunchFlag());
132
133     if (service && notification->getLaunchFlag())
134     {
135         ret = app_control_to_bundle(service, &service_data);
136         if (ret != APP_CONTROL_ERROR_NONE)
137         {
138             LOGE("Can't create bundle: %d", ret);
139             throw UnknownException("Can't create bundle");
140         }
141
142         LOGI("Notification Launch Flag True");
143         ret = notification_set_property(handle, 0);
144         if (ret != NOTIFICATION_ERROR_NONE) {
145             LOGE("set_property failed: %d, %s", ret,
146                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
147
148         }
149         ret = notification_set_execute_option(handle,
150             NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data);
151         if (ret != NOTIFICATION_ERROR_NONE)
152         {
153             LOGE("can't set notification option: %d, %s", ret,
154                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
155         }
156     }
157     else
158     {
159         LOGI("Notification Launch Flag False");
160         ret = notification_set_property(handle,
161             NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
162         if (ret != NOTIFICATION_ERROR_NONE) {
163             LOGE("set_property failed: %d, %s", ret,
164                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
165         }
166     }
167
168     //check layout.
169     int type = (int)notification->getNotiType();
170     notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
171
172     switch (type)
173     {
174         case NOTI_TYPE_SIMPLE:
175         {
176             if (notification->getNumber()>0)
177                 noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
178             else
179                 noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
180             break;
181         }
182         case NOTI_TYPE_THUMBNAIL:
183         {
184             noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
185             break;
186         }
187         case NOTI_TYPE_ONGOING:
188         {
189             noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
190             break;
191         }
192          case NOTI_TYPE_PROGRESS:
193         {
194             noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
195             break;
196         }
197     }
198
199     LOGD("Layout type = %d", noti_layout);
200     ret = notification_set_layout(handle, noti_layout);
201     LOGD("set Layout result = %d", ret);
202
203     int privID = -1;
204
205     //if noti already exist, it is update.
206     ret = notification_insert(handle, &privID);
207
208     if (ret != NOTIFICATION_ERROR_NONE) {
209         LOGE("insert failed: %d, %s", ret,
210             NotificationUtil::getNotificationErrorMessage(ret).c_str());
211         NotificationUtil::throwNotificationException(ret,
212             "Notification object post fail");
213     }
214
215     id = privID;
216     LOGD("private ID : %d", privID);
217     notification->setUpdatedFlag(false);
218
219     if (type == NOTI_TYPE_PROGRESS)
220     {
221
222         double value = 0.0;
223
224         ret = notification_get_size(handle, &value);
225         if (ret != NOTIFICATION_ERROR_NONE)
226         {
227             LOGE("get_size failed: %d, %s", ret,
228                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
229             NotificationUtil::throwNotificationException(ret,
230                 "get notification size error");
231         }
232         LOGI("get Size : %d", value);
233         ret = notification_update_size(handle, NOTIFICATION_PRIV_ID_NONE, value);
234         if (ret != NOTIFICATION_ERROR_NONE)
235         {
236             LOGE("update_size failed: %d, %s", ret,
237                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
238             NotificationUtil::throwNotificationException(ret,
239                 "update notification size error");
240         }
241
242         ret = notification_get_progress(handle, &value);
243         if (ret != NOTIFICATION_ERROR_NONE)
244         {
245             LOGE("get_progress failed: %d, %s", ret,
246                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
247             NotificationUtil::throwNotificationException(ret,
248                 "get notification percentage error");
249         }
250         LOGI("get Percentage : %lf", value);
251
252         ret = notification_update_progress(handle, NOTIFICATION_PRIV_ID_NONE,
253             value);
254         if (ret != NOTIFICATION_ERROR_NONE)
255         {
256             LOGE("update_progress failed: %d, %s", ret,
257                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
258         }
259     }
260
261     return id;
262 }
263 void NotificationManager::update(StatusNotification *notification)
264 {
265     if (!notification) {
266         LOGD("INotification is NULL");
267         throw UnknownException("Notificaton is NULL");
268     }
269
270     LOGD("notification id = %d", notification->getID());
271     notification_h handle = (notification_h)notification->getNotificationHandle();
272
273     if (!handle) {
274         LOGD("it doesn't have notification handle.");
275         throw UnknownException("It is Empty Notification.");
276     }
277
278     LOGD("noti type = %d", notification->getNotiType());
279     int ret = 0;
280
281     if (notification->getNotiType() == NOTI_TYPE_PROGRESS)
282     {
283         LOGD("progress type = %d", notification->getProgressType());
284         LOGD("noti id = %d", notification->getID());
285         LOGD("noti progress value = %d", notification->getProgressValue());
286
287         if (NOTI_PROGRESS_TYPE_PERCENTAGE == notification->getProgressType())
288         {
289             LOGD( "Percentage ");
290             ret = notification_update_progress(handle,
291                 NOTIFICATION_PRIV_ID_NONE, notification->getProgressValue());
292         }
293         else if (NOTI_PROGRESS_TYPE_SIZE == notification->getProgressType())
294         {
295             LOGD( "size ");
296             ret = notification_update_size(handle, NOTIFICATION_PRIV_ID_NONE,
297                 notification->getProgressValue());
298         }
299
300         LOGD("notification_update_progress = %d", ret);
301
302         if (NOTIFICATION_ERROR_NONE != ret)
303         {
304             LOGE("%d, %s", ret,
305                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
306             NotificationUtil::throwNotificationException(ret,
307                 "notification_update_progress failed");
308         }
309
310     }
311
312     LOGD("updated Flag = %d", notification->getUpdatedFlag());
313
314     if (notification->getUpdatedFlag())
315     {
316
317         int type = (int)notification->getNotiType();
318         notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
319
320         switch (type)
321         {
322             case NOTI_TYPE_SIMPLE:
323             {
324                 if (notification->getNumber()>0)
325                     noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
326                 else
327                     noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
328                 break;
329             }
330             case NOTI_TYPE_THUMBNAIL:
331             {
332                 noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
333                 break;
334             }
335             case NOTI_TYPE_ONGOING:
336             {
337                 noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
338                 break;
339             }
340             case NOTI_TYPE_PROGRESS:
341             {
342                 noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
343                 break;
344             }
345         }
346
347         LOGD("Layout type = %d", noti_layout);
348         ret = notification_set_layout(handle, noti_layout);
349         LOGD("set Layout result = %d", ret);
350
351
352         bundle *service_data = NULL;
353         app_control_h service = notification->getService();
354
355         if (service)
356         {
357             ret = app_control_to_bundle(service, &service_data);
358             if (ret != APP_CONTROL_ERROR_NONE)
359             {
360                 LOGE("%d", ret);
361                 throw UnknownException("Can't create bundle");
362             }
363
364             if (notification->getLaunchFlag())
365             {
366                 LOGI("Notification Launch Flag True");
367                 ret = notification_set_property(handle, 0);
368                 if (ret != NOTIFICATION_ERROR_NONE) {
369                     LOGE("set_property failed: %d, %s", ret,
370                         NotificationUtil::getNotificationErrorMessage(ret).c_str());
371                 }
372
373                 ret = notification_set_execute_option(handle,
374                     NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL,
375                     service_data);
376                 if (ret != NOTIFICATION_ERROR_NONE)
377                 {
378                     LOGE("Can't set Service option %d, %s", ret,
379                         NotificationUtil::getNotificationErrorMessage(ret).c_str());
380                 }
381             }
382             else
383             {
384                 LOGI("Notification Launch Flag False");
385                 notification_set_property(handle, NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
386             }
387         }
388
389         notification->setLaunchFlag(false);
390
391         LOGD("get Title = %s", notification->getTitle().c_str());
392         ret = notification_update(handle);
393         LOGD("notification_update = %d", ret);
394
395         // init
396         notification->setUpdatedFlag(false);
397
398         if (ret != NOTIFICATION_ERROR_NONE)
399         {
400             LOGE("update failed: %d, %s", ret,
401                 NotificationUtil::getNotificationErrorMessage(ret).c_str());
402             throw UnknownException("Notification Object update fail");
403         }
404     }
405 }
406
407 void NotificationManager::remove(std::string id)
408 {
409     int privID = -1;
410     int ret = 0;
411     bool existFlag = false;
412
413     LOGD("id : %s", id.c_str());
414     std::istringstream stream(id);
415     if (stream.fail())
416     {
417         LOGE("invalid notification ID");
418         throw InvalidValuesException("Invalid notification ID, it don't match id format");
419     }
420
421     stream >> privID;
422
423     notification_h noti = NULL;
424     notification_list_h noti_list = NULL;
425     notification_list_h noti_list_iter = NULL;
426
427     ret = notification_get_grouping_list( NOTIFICATION_TYPE_NONE , -1,
428         &noti_list);
429     if (ret != NOTIFICATION_ERROR_NONE) {
430         LOGD("get notification list failed: %d, %s", ret,
431             NotificationUtil::getNotificationErrorMessage(ret).c_str());
432         NotificationUtil::throwNotificationException(ret,
433             "Can't get noti list");
434     }
435
436     noti_list_iter = notification_list_get_head(noti_list);
437     while ( noti_list_iter != NULL)
438     {
439         noti = notification_list_get_data(noti_list_iter);
440         if (noti != NULL && notification_package_equal(noti))
441         {
442             int noti_priv = -1;
443             ret = notification_get_id(noti, NULL, &noti_priv);
444             if (ret != NOTIFICATION_ERROR_NONE) {
445                 LOGE("get_id failed: %d, %s", ret,
446                     NotificationUtil::getNotificationErrorMessage(ret).c_str());
447             }
448
449             LOGD("notification id = %d", noti_priv);
450             if (noti_priv == privID)
451                 existFlag = true;
452         }
453         noti_list_iter = notification_list_get_next(noti_list_iter);
454     }
455
456     if (noti_list)
457         notification_free_list(noti_list);
458
459     LOGD("notification ID : %d", privID);
460     if (!existFlag) {
461         LOGE("existFlag is NULL");
462         throw NotFoundException("not exist id");
463     }
464
465     ret = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NONE, privID);
466     if (ret != NOTIFICATION_ERROR_NONE) {
467         LOGE("delete_by_priv_id failed: %d, %s", ret,
468             NotificationUtil::getNotificationErrorMessage(ret).c_str());
469         NotificationUtil::throwNotificationException(ret,
470             "notification delete failed");
471     }
472 }
473
474 void NotificationManager::removeAll()
475 {
476     // remove all noti type
477     int ret = notification_delete_all(NOTIFICATION_TYPE_NOTI);
478     if (ret != NOTIFICATION_ERROR_NONE)
479     {
480         LOGE("notification delete failed: %d, %s", ret,
481             NotificationUtil::getNotificationErrorMessage(ret).c_str());
482         NotificationUtil::throwNotificationException(ret,
483             "notification delete failed");
484     }
485
486     ret = notification_delete_all(NOTIFICATION_TYPE_ONGOING);
487     if (ret != NOTIFICATION_ERROR_NONE)
488     {
489         LOGE("notification delete failed: %d, %s", ret,
490             NotificationUtil::getNotificationErrorMessage(ret).c_str());
491         NotificationUtil::throwNotificationException(ret,
492             "notification delete failed");
493     }
494 }
495
496 StatusNotification* NotificationManager::get(std::string id)
497 {
498     int privID = 0;
499
500     std::istringstream stream(id);
501     if (stream.fail())
502     {
503         LOGE("invalid notification id: %s", id.c_str());
504         throw InvalidValuesException("Invalid notification ID, it don't match id format");
505     }
506     stream >> privID;
507
508     LOGI("priv ID : %d", privID);
509
510     notification_h notification = notification_load(NULL, privID);
511
512     if (notification != NULL && notification_package_equal(notification))
513     {
514         StatusNotification* noti = new StatusNotification(notification);
515         return noti;
516     }
517     else
518     {
519         LOGE("It's not notification id or removed notifiation");
520         throw NotFoundException("It is not notification ID or removed notification");
521     }
522     return NULL;
523 }
524
525 std::vector<StatusNotification*> NotificationManager::getAll()
526 {
527     LOGD("OK");
528     std::vector<StatusNotification*> data;
529
530     notification_h noti = NULL;
531     notification_list_h noti_list = NULL;
532     notification_list_h noti_list_iter = NULL;
533     int ret = 0;
534
535     ret = notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1,
536         &noti_list);
537     if (ret != NOTIFICATION_ERROR_NONE)
538     {
539         LOGE("get notification list failed: %d, %s", ret,
540             NotificationUtil::getNotificationErrorMessage(ret).c_str());
541         NotificationUtil::throwNotificationException(ret,
542             "get notification list failed");
543     }
544
545     noti_list_iter = notification_list_get_head(noti_list);
546     while ( noti_list_iter != NULL)
547     {
548         noti = notification_list_get_data(noti_list_iter);
549         if (noti != NULL && notification_package_equal(noti))
550         {
551             int noti_priv = -1;
552             ret = notification_get_id(noti, NULL, &noti_priv);
553             if (ret != NOTIFICATION_ERROR_NONE) {
554                 LOGE("get_id failed: %d, %s", ret,
555                     NotificationUtil::getNotificationErrorMessage(ret).c_str());
556             }
557             LOGD("notification id = %d", noti_priv);
558
559             StatusNotification* notification = new StatusNotification(noti_priv);
560
561             ret = notification_get_id((notification_h)notification->
562                 getNotificationHandle(), NULL, &noti_priv);
563             if (ret != NOTIFICATION_ERROR_NONE) {
564                 LOGE("get_id failed: %d, %s", ret,
565                      NotificationUtil::getNotificationErrorMessage(ret).c_str());
566             }
567
568             LOGD("loaded notification id = %d", noti_priv);
569             data.push_back(notification);
570         }
571
572         noti_list_iter = notification_list_get_next(noti_list_iter);
573     }
574
575     if (noti_list)
576         notification_free_list(noti_list);
577
578     return data;
579 }
580
581 } // Notification
582 } // DeviceAPI